在buidler.config.ts中設定Solidity版本(自動完成型別註釋!):
Builder方便地捆綁了一個編譯任務,因此編譯是小菜一碟:
$ npx buidler compile
Compiling...
Compiled 1 contract successfully
Buidler使用的Solidity版本控制系統是令人驚歎的。 切換版本很容易,Buidler會根據需要自動下載並安裝Solidity版本,您所需要做的就是在配置中進行更改。 為Buidler團隊提供了巨大的道具來進行設定!
用Ethers和Waffle建立測試環境
現在,我們將設定您的測試環境。
安裝Ethers,Waffle和Builder外掛:
$ npm install --save-dev @nomiclabs/buidler-ethers ethers ethereum-waffle chai @types/chai
將所需的型別定義新增到tsconfig.json中:
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"outDir": "dist",
"resolveJsonModule": true
},
"include": ["./scripts", "./test"],
"files": [
"./buidler.config.ts",
"node_modules/@nomiclabs/buidler-ethers/src/type-extensions.d.ts",
}
設定builder.config.ts以使用Ethers外掛:
import { BuidlerConfig, usePlugin } from "@nomiclabs/buidler/config";
usePlugin("@nomiclabs/buidler-ethers");
const config: BuidlerConfig = {
solc: {
version: "0.5.12"
}
};
export default config;
設定TypeChain
TypeChain是一個非常酷的工具,可為您的智慧合約提供完整的輸入介面。 設定完成後,我們可以在Typescript中獲得合同功能的型別提示!
在撰寫本文時,Buidler沒有TypeChain外掛。 如果有人不先做,我打算很快就自己建一個!
首先安裝庫和Ethers繫結:
$ npm install --save-dev typechain typechain-target-ethers
透過執行命令生成型別檔案。 outDir定義了生成檔案的儲存位置,最後用引號引起來的字串將提取構建目錄中所有生成的合同:
$ ./node_modules/.bin/typechain --target ethers --outDir typechain 'build/*.json'
現在在typechain /目錄中,您應該看到生成了一些檔案,其中一個是Counter.d.ts。 這是主要的合約型別檔案,為我們提供了編寫型別安全測試所需的資訊!
編寫和執行合約測試
編寫測試大多遵循Waffle語法,但有一個主要區別:ethers.provider物件是從“ @ nomiclabs / buidler”庫而不是ethereum-waffle庫匯入的。
現在讓我們編寫一個測試。 在test /目錄中建立一個名為counter.ts的檔案:
import { ethers } from "@nomiclabs/buidler";
import chai from "chai";
import { deployContract, getWallets, solidity } from "ethereum-waffle";
import CounterArtifact from "../build/Counter.json";
import { Counter } from "../typechain/Counter"
chai.use(solidity);
const { expect } = chai;
describe("Counter", () => {
// 1
const provider = ethers.provider;
// 2
let [wallet] = getWallets(provider);
// 3
let counter: Counter;
beforeEach(async () => {
counter = await deployContract(wallet, CounterArtifact) as Counter;
const initialCount = await counter.getCount();
// 4
expect(initialCount).to.eq(0);
expect(counter.address).to.properAddress;
});
// 5
it("should count up", async () => {
await counter.countUp();
let count = await counter.getCount();
expect(count).to.eq(1);
await counter.countUp();
count = await counter.getCount();
expect(count).to.eq(2);
});
it("should count down", async () => {
// 6
await counter.countDown();
const count = await counter.getCount();
expect(count).to.eq(0);
});
});
編號行的說明:
1.使用從Buidler匯入的provider
2.從getWallets功能獲取錢包另外請注意,您可以使用此函式對任意數量的錢包進行結構分解,例如:
let [wallet1, wallet2, wallet3] = getWallets(provider);
3.匯入Counter型別,並將其用作在beforeEach中部署的變數的型別。
4. Waffle有一些有用的Chai匹配器,用於編寫合同測試,例如BigNumber匹配器和以太坊地址匹配器。 在這裡檢視所有內容。
5.透過簡單的測試來計數並確保Counter正常工作。
6.注意的那些人將看到此測試將失敗。
讓我們開始執行測試!
$ npx buidler test
注意到結果有異常嗎?
All contracts have already been compiled, skipping compilation.
Counter
✓ should count up (143ms)
1) should count down
1 passing (593ms)
1 failing
1) Counter
should count down:
Error: VM Exception while processing transaction: revert Uint256 underflow
at Counter.countDown (contracts/Counter.sol:24)
這是您的Solidity程式碼中的STACK TRACE,其中顯示發生還原的行號!!! line逐行註釋合同以檢視觸發哪個還原的日子已經一去不復返了。
部署合約
經過測試後,迴圈的最後一步是部署合約。
第一步是將網路配置新增到buidler.config.ts檔案。 我們將為此使用rinkeby,但您可以類似地新增任何網路(即mainnet):
import { BuidlerConfig, usePlugin } from "@nomiclabs/buidler/config";
import waffleDefaultAccounts from "ethereum-waffle/dist/config/defaultAccounts";
usePlugin("@nomiclabs/buidler-ethers");
const INFURA_API_KEY = "";
const RINKEBY_PRIVATE_KEY = "";
const config: BuidlerConfig = {
solc: {
version: "0.5.12"
},
paths: {
artifacts: "./build"
},
networks: {
buidlerevm: {
accounts: waffleDefaultAccounts.map(acc => ({
balance: acc.balance,
privateKey: acc.secretKey
}))
},
rinkeby: {
url: `https://rinkeby.infura.io/v3/${INFURA_API_KEY}`,
accounts: [RINKEBY_PRIVATE_KEY]
}
}
};
export default config;
我將Infura用作以太坊節點端點,但是任何遠端端點都可以使用。 如果您從未這樣做,請從Infura獲取API金鑰。
現在,我們在指令碼/資料夾內建立一個名為deploy.ts的部署指令碼:
import { ethers } from "@nomiclabs/buidler";
async function main() {
const factory = await ethers.getContract("Counter")
// If we had constructor arguments, they would be passed into deploy()
let contract = await factory.deploy();
// The address the Contract WILL have once mined
console.log(contract.address);
// The transaction that was sent to the network to deploy the Contract
console.log(contract.deployTransaction.hash);
// The contract is NOT deployed yet; we must wait until it is mined
await contract.deployed()
}
main()
.then(() => process.exit(0))
.catch(error => {
console.error(error);
process.exit(1);
});
超級簡單的東西!
現在,只需執行指令碼,我們就可以在控制檯中看到我們的地址和交易雜湊:
$ npx buidler run --network rinkeby scripts/deploy.ts
All contracts have already been compiled, skipping compilation.
0x01FF454Dd078dC7f3cd0905601d093b17E7B9CD7
0x2ae1444920ed76420fb69c9f2fc914c20956efc2ae05c94ab1ea53f224aa0930
我們可以轉到Etherscan,檢視該事務實際上已成功完成。
你有它! 完整的分步指南,用於設定型別安全的增壓構建,測試,部署環境,並使用一些很酷的新工具。
收尾
為了使所有內容整潔無比,讓我們製作一些方便的NPM指令碼。 將以下內容新增到您的package.json中:
"scripts": {
"build": "npm run compile && npm run typechain",
"compile": "npx buidler compile",
"typechain": "npx buidler compile && typechain --outDir typechain --target ethers 'build/*.json'",
"test": "npx buidler test"
}
構建指令碼執行合同編譯並生成TypeChain繫結,並且測試指令碼執行合同測試。
附加:在etherscan上驗證
Buidler有一個超級方便的外掛,可用於在Etherscan上驗證合約,此任務比看起來應該的要複雜得多。 他們的工具可以為您處理拼合,這對於匯入其他合約,使用OpenZeppelin庫等的合約非常方便。
我們可以從安裝外掛開始:
$ npm install --save-dev @nomiclabs/buidler-etherscan
然後,我們新增到tsconfig.json中,以確保我們的Typescript環境瞭解此外掛:
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"outDir": "dist",
"resolveJsonModule": true
},
"include": ["./scripts", "./test"],
"files": [
"./buidler.config.ts",
"node_modules/@nomiclabs/buidler-ethers/src/type-extensions.d.ts",
"node_modules/@nomiclabs/buidler-etherscan/src/type-extensions.d.ts"
]
}
接下來,我們將所需的配置新增到我們的buidler.config.ts中(跳到Etherscan並從您的帳戶頁面獲取API金鑰):
import { BuidlerConfig, usePlugin } from "@nomiclabs/buidler/config";
import waffleDefaultAccounts from "ethereum-waffle/dist/config/defaultAccounts";
usePlugin("@nomiclabs/buidler-ethers");
usePlugin("@nomiclabs/buidler-etherscan");
const INFURA_API_KEY = "";
const RINKEBY_PRIVATE_KEY = "";
const ETHERSCAN_API_KEY = "";
const config: BuidlerConfig = {
solc: {
version: "0.5.12"
},
paths: {
artifacts: "./build"
},
networks: {
buidlerevm: {
accounts: waffleDefaultAccounts.map(acc => ({
balance: acc.balance,
privateKey: acc.secretKey
}))
},
rinkeby: {
url: `https://rinkeby.infura.io/v3/${INFURA_API_KEY}`,
accounts: [RINKEBY_PRIVATE_KEY]
}
},
etherscan: {
// The url for the Etherscan API you want to use.
url: "https://api-rinkeby.etherscan.io/api",
// Your API key for Etherscan
// Obtain one at https://etherscan.io/
apiKey: ETHERSCAN_API_KEY
}
};
export default config;
希望我們可以方便地保留上一步中的部署地址,因為這樣我們就可以簡單地執行此外掛提供的內建任務:
$ npx buidler verify-contract --contract-name Counter --address 0xF0E6Ea29799E85fc1A97B7b78382fd034A6d7864
All contracts have already been compiled, skipping compilation.
Successfully submitted contract at 0xF0E6Ea29799E85fc1A97B7b78382fd034A6d7864 for verification on etherscan. Waiting for verification result...
Successfully verified contract on etherscan
易如反掌! 現在,在Etherscan上檢查合約地址,您可以檢視完整的合約原始碼,並直接從網頁上讀寫合約。
最後的想法
在整個使用過程中,Buidler對其devex的使用給我留下了深刻的印象。 它已經具有大量很酷的功能,並且他們計劃建造更多更酷的東西。 除了Solidity堆疊跟蹤,該團隊還計劃推出另一個急需的智慧合約除錯功能:console.log!。
我一定會密切關注這個專案,並盡我所能為其生態系統做出貢獻。