AllIsHackedOff

Just a memo, just a progress

ethers.jsをconsoleから使えるタスクランナーbuidlers.devに触ってみる

サンプルのインストール

ローカルにbuidlerをインストール

yarn init
# global installするとtypescript互換モードが使えなくなる感あるのでローカルにいれます
yarn add --dev @nomiclabs/buidler

起動 (builderとtypoしても優しく訂正してくれる...はず)

yarn buidler

起動時のダイアログ

888               d8b      888 888
888               Y8P      888 888
888                        888 888
88888b.  888  888 888  .d88888 888  .d88b.  888d888
888 "88b 888  888 888 d88" 888 888 d8P  Y8b 888P"
888  888 888  888 888 888  888 888 88888888 888
888 d88P Y88b 888 888 Y88b 888 888 Y8b.     888
88888P"   "Y88888 888  "Y88888 888  "Y8888  888

👷 Welcome to Buidler v1.0.1 👷‍‍

? What do you want to do? …
❯ Create a sample project # こいつを選択
  Create an empty buidler.config.js
  Quit

サンプルプロジェクトで使いたいライブラリをインストール

yarn add --save @nomiclabs/buidler-truffle5 @nomiclabs/buidler-web3 web3

コントラクトのコンパイル(built-inタスクの実行)

# デフォルトで用意されているcompileタスクが実行される
yarn buidler compile
# contracts下がコンパイルされ、build下に成果物(artifactファイル)が生成される

コントラクトをコンパイルするとbuildしたにbuidlerのartifactファイルが生成される。build成果物自体はtruffleのものと違いコンパクトではあるが networks の項目がないのでこのファイル他のコンポーネントコントラクトと通信するために使い回せるかは謎である。

{
  "contractName": "Greeter",
  "abi": [ /* 略 */ ],
  "bytecode": "0x608060405234801561001057600080fd5b506040516104e03803806104e08339818101604052602081101561003357600080fd5b810190808051604051939291908464010000000082111561005357600080fd5b8382019150602082018581111561006957600080fd5b825186600182028301116401000000008211171561008657600080fd5b8083526020830192505050908051906020019080838360005b838110156100ba57808201518184015260208101905061009f565b50505050905090810190601f1680156100e75780820380516001836020036101000a031916815260200191505b506040525050506100fd8161010360201b60201c565b506101c2565b806000908051906020019061011992919061011d565b5050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061015e57805160ff191683800117855561018c565b8280016001018555821561018c579182015b8281111561018b578251825591602001919060010190610170565b5b509050610199919061019d565b5090565b6101bf91905b808211156101bb5760008160009055506001016101a3565b5090565b90565b61030f806101d16000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063a41368621461003b578063cfae3217146100f6575b600080fd5b6100f46004803603602081101561005157600080fd5b810190808035906020019064010000000081111561006e57600080fd5b82018360208201111561008057600080fd5b803590602001918460018302840111640100000000831117156100a257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050610179565b005b6100fe610193565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561013e578082015181840152602081019050610123565b50505050905090810190601f16801561016b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b806000908051906020019061018f929190610235565b5050565b606060008054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561022b5780601f106102005761010080835404028352916020019161022b565b820191906000526020600020905b81548152906001019060200180831161020e57829003601f168201915b5050505050905090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061027657805160ff19168380011785556102a4565b828001600101855582156102a4579182015b828111156102a3578251825591602001919060010190610288565b5b5090506102b191906102b5565b5090565b6102d791905b808211156102d35760008160009055506001016102bb565b5090565b9056fea265627a7a723158204b258d436f26c71ba0028877c11fb5e10e2229c35e34015e83b7ca402052b2ed64736f6c634300050b0032",
  "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c8063a41368621461003b578063cfae3217146100f6575b600080fd5b6100f46004803603602081101561005157600080fd5b810190808035906020019064010000000081111561006e57600080fd5b82018360208201111561008057600080fd5b803590602001918460018302840111640100000000831117156100a257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050610179565b005b6100fe610193565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561013e578082015181840152602081019050610123565b50505050905090810190601f16801561016b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b806000908051906020019061018f929190610235565b5050565b606060008054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561022b5780601f106102005761010080835404028352916020019161022b565b820191906000526020600020905b81548152906001019060200180831161020e57829003601f168201915b5050505050905090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061027657805160ff19168380011785556102a4565b828001600101855582156102a4579182015b828111156102a3578251825591602001919060010190610288565b5b5090506102b191906102b5565b5090565b6102d791905b808211156102d35760008160009055506001016102bb565b5090565b9056fea265627a7a723158204b258d436f26c71ba0028877c11fb5e10e2229c35e34015e83b7ca402052b2ed64736f6c634300050b0032",
  "linkReferences": {},
  "deployedLinkReferences": {}
}

サンプルコード中に含まれているタスクの実行

truffle buidler accconts
# builder.config.jsにかかれているacccountsタスクが起動する
# 20個のアカウントが表示されるはず

デフォルトではBuidler EVM Networkに接続してコントラクトのデプロイやテストの実行などを行う。Builder EVMのネットワークはtaskを走らせる度に立ち上がる buidler.config.jsでよしなに gasfromのアドレスを指定することができる。

buidler.config.jsの例

module.exports = {
  defaultNetworks: "buidlerevm",
  networks: {
    localhost: {
      url: 'http://127.0.0.1:8545'
    },
    buidlerevm: {
      gas: 0,
      gasPrice: 0,
      accounts: [ // 指定しないと20個のアカウントに10000EHがデフォルトで付与されて用意される
        { 
          privateKey: "0xB3BB3A1EB4EBAAE568DB332251B77F5A029E44DB3C1CA9F39056B29C86ADC62C",
          balance: "0x" + `${55 * (10**10)}`,
        }
      ],
      blockGasLimit: 99 * (10**5),
      hardfork: "constantinople",
    },
  },
};

デプロイ

run yarn buidler run scripts/sample-script.js

sample-script.jsは下記 Truffleとそれほど書き方は変わらない。artifactファイルを読み込んで諸々の操作を行う。ただスクリプトを走らせているだけなのでカスタマイズはTruffleのマイグレーションよりは効くだろう。ただし、順序制御的なものは導入されていない

// We require the Buidler Runtime Environment explicitly here. This is optional
// when running the script with `buidler run <script>`: you'll find the Buidler
// Runtime Environment's members available as global variable in that case.
const env = require("@nomiclabs/buidler");

async function main() {
  // You can run Buidler tasks from a script.
  // For example, we make sure everything is compiled by running "compile"
  await env.run("compile");

  // We require the artifacts once our contracts are compiled
  const Greeter = env.artifacts.require("Greeter");
  const greeter = await Greeter.new("Hello, world!");

  console.log("Greeter address:", greeter.address);
}

// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main()
  .then(() => process.exit(0))
  .catch(error => {
    console.error(error);
    process.exit(1);
  });

デプロイの出力

All contracts have already been compiled, skipping compilation.
All contracts have already been compiled, skipping compilation.
Greeter address: 0x7c2C195CD6D34B8F845992d380aADB2730bB9C6F
✨  Done in 3.41s.

buidlerは起動時にconfigファイルを指定できるので、ビルド対象のコントラクトディレクトリ、ビルド成果物の配備先などもよしなに切り替えることができる。一例としてsolidity 0.4.xと0.5.xを共存させる場合の例が公式チュートリアルには記載されている

builder.config_xxxx.js

module.exports = {
  paths: {
    sources: "./contracts/5", // 0.5系を配備するディレクトリ
    // test
    // cache
    // artifacts
    // root などを指定可能
  }
  /* この下にネットワークの設定など */
};

設定ファイルの読み替え

yarn buidler compile --config builder.config_xxxx.js

テスト実行時のスタックトレース

1) Contract: ERC721
       like an ERC721
         transfers
           via safeTransferFrom
             to a contract that does not implement the required function
               reverts:
     Error: Transaction reverted: function selector was not recognized and there's no fallback function
      at ERC721Mock.<unrecognized-selector> (contracts/mocks/ERC721Mock.sol:9)
      at ERC721Mock._checkOnERC721Received (contracts/token/ERC721/ERC721.sol:334)
      at ERC721Mock._safeTransferFrom (contracts/token/ERC721/ERC721.sol:196)
      at ERC721Mock.safeTransferFrom (contracts/token/ERC721/ERC721.sol:179)
      at ERC721Mock.safeTransferFrom (contracts/token/ERC721/ERC721.sol:162)
      at TruffleContract.safeTransferFrom (node_modules/@nomiclabs/truffle-contract/lib/execute.js:157:24)
      at Context.<anonymous> (test/token/ERC721/ERC721.behavior.js:262:30)

  2) Contract: ERC721
       internal functions
         _burn(address, uint256)
           with minted token
             with burnt token
               reverts when burning a token id that has been deleted:
     TypeError: this.token.methods.aurn(address,uint256) is not a function
      at Context.<anonymous> (test/token/ERC721/ERC721.test.js:82:58)
      at process._tickCallback (internal/process/next_tick.js:68:7)

同じテストをTruffleで実行したときの出力

1) Contract: ERC721
       like an ERC721
         transfers
           via safeTransferFrom
             to a contract that does not implement the required function
               reverts:
     Error: Returned error: VM Exception while processing transaction: revert
     at PromiEvent (node_modules/truffle/build/webpack:/packages/contract/lib/promievent.js:9:1)
      at TruffleContract.safeTransferFrom (node_modules/truffle/build/webpack:/packages/contract/lib/execute.js:169:1)
      at Context.<anonymous> (test/token/ERC721/ERC721.behavior.js:262:30)

  2) Contract: ERC721
       internal functions
         _burn(address, uint256)
           with minted token
             with burnt token
               reverts when burning a token id that has been deleted:
     TypeError: this.token.methods.aurn(address,uint256) is not a function
      at Context.<anonymous> (test/token/ERC721/ERC721.test.js:82:58)
      at process._tickCallback (internal/process/next_tick.js:68:7)

と、たしかにTruffleよりも親切そうだ