基於truffle進行合約部署

1.Truffle 簡介

1.1.什麼是 Truffle

Truffle 是一個世界級的開發環境,測試框架,以太坊的資源管理通道,致力於讓以太坊上的開發變得簡單。

Truffle 有以下特性:

內置的智能合約編譯,鏈接,部署和二進制文件的管理;

快速開發下的自動合約測試;

腳本化的,可擴展的部署與發佈框架;

部署到不管多少的公網或私網的網絡環境管理功能;

使用 EthPM&NPM 提供的包管理,使用 ERC190 標準;

與合約直接通信的直接交互控制檯;

可配的構建流程,支持緊密集成;

在 Truffle 環境裏支持執行外部的腳本。

1.2.環境要求和安裝

環境要求:

NodeJS 5.0+;

Windows,Linux,或 Mac OS X。

安裝方式:

$ npm install -g truffle

Truffle 需要以太坊客戶端,需要支持標準的 JSON RPC API。

如果你是 Windows 用戶,推薦使用 Powershell 或 Git BASH 來安裝和使用 Truffle 框架。

1.3.Truffle 開發工具

當開發基於 Truffle 的應用時,推薦使用 EthereumJS TestRPC,它是一個完整的在內存中的區塊鏈僅僅存在於開發的設備上。它在執行交易時是實時返回,而不等待默認的出塊時間,這樣可以快速驗證新寫的代碼,當出現錯誤時,也能即時反饋給你。它同時還是一個支持自動化測試的功能強大的客戶端,Truffle 充分利用它的特性,能將測試運行時間提速近 90%。

使用 TestRPC 客戶端充分測試後,可是嘗試使用正式發佈的客戶端:Geth (go-ethereum)、WebThree(cpp-ethereum)、More,這些是完整的客戶端實現,包括挖礦,網絡,塊及交易的處理,Truffle 可以在不需要額外配置的情況下發布到這些客戶端。

2.Truffle 工程創建

創建工程目錄,可以使用文件瀏覽器或使用下面的命令在命令行創建一個目錄:

$ mkdir myproject

接下來,通過下面的命令初始化一個 Truffle 工程:

$ truffle

Truffle v3.4.11 - a development framework for Ethereum

$ cd myproject

$ truffle init

完成後,將擁有如下目錄:

  • app/ - 應用文件運行的默認目錄,這裏麪包括推薦的 javascript 文件和 css 樣式文件目錄,但可以完全決定如何使用這些目錄;
  • contract/ - Truffle 默認的合約文件存放地址;
  • migrations/ - 存放發佈腳本文件 ;
  • test/ - 用來測試應用和合約的測試文件;
  • truffle.js - Truffle 的配置文件。
  • truffle init 會默認創建一個構建在以太坊內的代幣 demo 應用:METACOIN,可以使用這個工程來進行快速的學習,或者也可以刪除這些文件來創建一個自己的工程。

3.編譯合約

3.1.合約位置

所有合約應該位於 ./contracts 目錄,默認提供一個合約文件,一個庫文件,均以 .sol 結尾作爲示例。

儘管庫文件有一定的特殊性,但爲簡單起見,當前均稱之爲合約。

3.2.命令

要編譯合約,使用:

truffle compile

Truffle 僅默認編譯自上次編譯後被修改過的文件,來減少不必要的編譯。如果想編譯全部文件,可以使用 --compile-all 選項:

truffle compile —compile-all

3.3. 約定

Truffle 需要定義的合約名稱和文件名準確匹配。

舉例來說,如果文件名爲 MyContract.sol,那麼合約文件須爲如下兩者之一:

contract MyContract {

  ...

}

// or

library MyContract {

  ...

}

這種匹配是區分大小寫的,也就是說大小寫也要一致,推薦大寫每一個開頭字母。

3.4.依賴

可以通過使用 import 來聲明依賴,Truffle 將會按正確順序依次編譯合約,並在需要的時候自動關聯庫。

3.5.編譯目錄

編譯的輸出位於 ./build/contracts 目錄,如果目錄不存在會自動創建。

編譯文件對於 Truffle 框架能否正常工作至關重要,不應該在正常的編譯或發佈以外手動修改這些文件。

4..移植

4.1.移植目的

 

移植是由一些 Javascript 文件組成來協助發佈到以太坊網絡,主要目的是用來緩存你的發佈任務,它的存在基於你的發佈需求會改變的前提。

當你的工程發生了重要的改變,你將創建新的移植腳本來將這些變化帶到區塊鏈上,之前運行移植的歷史記錄通過一個特殊的 Migrations 合約來記錄到鏈上。

4.2.命令

執行移植,使用下述命令:

truffle migrate

如果你之前的移植是成功執行的,這個命令會執行所有的位於 migrations 目錄內的移植腳本,truffle migrate 僅會執行新創建的移植。

如果沒有新的移植腳本,這個命令不同執行任何操作,可以使用選項 --reset 來從頭執行移植腳本。

4.3.移植腳本文件

一個樣例文件如下:文件名:4_example_migration.js

module.exports = function(deployer) {

  // deployment steps

  deployer.deploy(MyContract);

};

 

需要注意的是文件名以數字開頭,一個描述性的後綴結尾,數字前綴是必須的,用於記錄移植是否成功,後綴僅是爲了提高可讀性,以方便理解。

移植 js 裏的 exports 的函數接受一個 deployer 對象作爲第一個參數,這個對象用於發佈過程,提供了一個清晰的語法支持,同時提供一些通過的合約部署職責,比如保存發佈的文件以備稍後使用。deployer 對象是用來緩存(stage)發佈任務的主要操作接口。

像所有其它在 Truffle 中的代碼一樣,Truffle 提供了自己代碼的合約抽象層(contract abstractions),並且進行了初始化,以方便可以便利的與以太坊的網絡交互,這些抽象接口是發佈流程的一部分。

4.4.部署器(deployer

移植文件會使用部署器來緩存部署任務,因此可以按一定順序排列發佈任務,它們會按正確順序執行:

// Stage deploying A before B

deployer.deploy(A);

deployer.deploy(B);

 

另一選中可選的部署方式是使用 Promise,將部署任務做成一個隊列,是否部署依賴於前一個合約的執行情況:

// Deploy A, then deploy B, passing in A's newly deployed address

deployer.deploy(A).then(function() {

  return deployer.deploy(B, A.address);

});

 

如果想更清晰,也可以選擇實現一個 Promise 鏈。

可以根據發佈到的網絡的具體情況進行不同的部署流程,要實現不同條件的不同部署步驟,移植代碼中需要第二個參數 network。示例如下:

module.exports = function(deployer, network) {

  // Add demo data if we're not deploying to the live network.

  if (network != "live") {

    deployer.exec("add_demo_data.js");

  }

}

 

指定一個網絡:大多數 Truffle 提供的命令根據指定的網絡不同而表現不同,會使用對應網絡下的合約和配置信息,可以通過 --network 選項在參數上進行控制:

$ truffle migrate --network live

networks: {

  development: {

    host: "localhost",

    port: 8545,

    network_id: "*" // match any network

  },

  live: {

    host: "178.25.19.88", // Random IP for example purposes (do not use)

    port: 80,

    network_id: 1,        // Ethereum public network

    // optional config values

    // gas

    // gasPrice

    // from - default address to use for any transaction Truffle makes during migrations

  }

}

 

在上面這個例子中,Truffle 會在 live 網絡中進行移植,如果配置如上述配置示例的 Example 所指定的內容的話,是最終在以太坊網絡上進行部署。

4.5.部署 API

4.5.1.DEPLOYER.DEPLOY

發佈一個指定的合約,第一參數是合約對象,後面是一些可選的構造器參數。這個函數適用於單例合約,它只會在 dapp 中只創建一個這個合約的實例(單例),函數會在部署後設置合約的地址(如:C ontract.address 將等於新的部署地址),它將會覆蓋之前存儲的地址。也可以傳入一個合約數組,或數組的數組來加速多合約的部署。

需要注意的是如果庫的地址可用,deploy 會自動爲這個部署的合約聯接任何需要的庫,因此如果合約依賴某個庫,應該先部署這個庫:

// Deploy a single contract without constructor arguments

deployer.deploy(A);



// Deploy a single contract with constructor arguments

deployer.deploy(A, arg1, arg2, ...);



// Deploy multiple contracts, some with arguments and some without.

// This is quicker than writing three `deployer.deploy()` statements as the deployer

// can perform the deployment as a batched request.

deployer.deploy([

  [A, arg1, arg2, ...],

  B,

  [C, arg1]

]);

4.5.2.DEPLOYER.LINK

聯接一個已經發布的庫到一個或多個合約,destinations 可以是一個合約或多個合約組成的一個數組,如果目標合約並不依賴這個庫,部署器會忽略掉這個合約。

這對於在 dapp 中不打算部署的合約(如:非單例)但卻需要在使用前先聯接的情況下非常有用。

// Deploy library LibA, then link LibA to contract B

deployer.deploy(LibA);

deployer.link(LibA, B);



// Link LibA to many contracts

deployer.link(LibA, [B, C, D]);

4.5.3.DEPLOYER.AUTOLINK(CONTRACT)

關聯合約依賴的所有庫,這需要所依賴的庫已經部署,或在其前一步部署:

// Assume A depends on a LibB and LibC

deployer.deploy([LibB, LibC]);

deployer.autolink(A);

 

另外可以省略參數來調用函數 autolink(),這會自動關聯合約依賴的所有庫,需要保證在調用這個函數前,所有被需要的庫已經部署:

// Link *all* libraries to all available contracts

deployer.autolink();

4.5.4.DEPLOYER.THEN

Promise 語法糖,執行做生意的部署流程:

deployer.then(function() {

  // Create a new version of A

  return A.new();

}).then(function(instance) {

  // Set the new instance of A's address on B.

  var b = B.deployed();

  return b.setA(instance.address);

});

4.5.5.DEPLOYER.EXEC

執行 truffle exec 做爲部署的一部分:

// Run the script, relative to the migrations file.

deployer.exec("../path/to/file/demo_data.js");

5.實例

5.1.環境安裝

npm install nodejs

npm install -g solc

npm install -g truffle

npm intall -g truffle-flattener

5.2.配置truffle

require('dotenv').config();

//const { MNEMONIC, PROJECT_ID } = process.env;



const private_keys = [

  process.env.PK1

]



const HDWalletProvider = require('@truffle/hdwallet-provider');



module.exports = {



  networks: {

    dev: {

     host: "127.0.0.1",     // Localhost (default: none)

     port: 7545,            // Standard Ethereum port (default: none)

     network_id: "5777",       // Any network (default: none)

    },



    bsctest: {

      provider: () => new HDWalletProvider({

        privateKeys:['0x8b9d4e96fb91e23axxxxxxxxxxx65e0843d'],

        providerOrUrl:`https://bsc-testnet.nodereal.io/v1/77055bfxxxxxxxd5d5b9`,

        numberOfAddress:1  

      }),

      network_id: 97,       

      confirmations: 2,    

      timeoutBlocks: 50, 

      gas: 5000000,         

      gasPrice: 50000000000, 

      skipDryRun: false     // Skip dry run before migrations? (default: false for public nets )

    },



  // Set default mocha options here, use special reporters, etc.

  mocha: {

    // timeout: 100000

  },



  // Configure your compilers

  compilers: {

    solc: {

      version: "0.8.1",      // Fetch exact version from solc-bin

    }

  },



};

配置部署的信息,以bsctest爲例。

5.3.編譯合約

test@MacBook-Pro TripleC % sudo truffle compile --network bsctest



Compiling your contracts...

===========================

> Everything is up to date, there is nothing to compile.

5.4.部署合約

test@MacBook-Pro TripleC % sudo truffle migrate --network bsctest



Compiling your contracts...

===========================

> Everything is up to date, there is nothing to compile.





Starting migrations...

======================

> Network name:    'bsc'

> Network id:      56

> Block gas limit: 140000000 (0x8583b00)





1685499904_deploy__triplec_medal.js

===================================

[ '0xe245fa636F67E491b8052D7C77256Fc192edAd86' ]



   Deploying 'TriplecMedal'

   ------------------------

   > transaction hash:    0x5aeb0933e5eaf680a2df06b41dc59ab1131481e5e5730400cf8e37b9559a6ee4

   > Blocks: 3            Seconds: 9

   > contract address:    0xB8e8037410D23db82E111111b44920f1E92113A1

   > block number:        34105401

   > block timestamp:     1701830356

   > account:             0xe245fa636F671111111d86

   > balance:             0.401088294

   > gas used:            4581180 (0x45e73c)

   > gas price:           50 gwei

   > value sent:          0 ETH

   > total cost:          0.229059 ETH



   Pausing for 2 confirmations...



   -------------------------------

   > confirmation number: 2 (block: 34105405)

   > Saving artifacts

   -------------------------------------

   > Total cost:            0.229059 ETH



Summary

=======

> Total deployments:   1

> Final cost:          0.229059 ETH

這樣就可以得到contract address了

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章