====== Hardhatを使ったスマートコントラクト開発 ====== ほぼ Hardhat オフィシャルの[[https://hardhat.org/getting-started/|ドキュメント]]通りに Hardhat を使ってみます。 ===== 前提 ===== npm をインストールしておいてください。 ===== インストール ===== :!: 下記「npx hardhat」コマンドを実行すると「What do you want to do?」と聞かれますので、今回は「Create a basic sample project」で作業を進めます。それ以外はデフォルトのままエンターを入力してください。 > mkdir hardhat_project > cd hardhat_project hardhat_project> npx hardhat Need to install the following packages: hardhat Ok to proceed? (y) y 888 888 888 888 888 888 888 888 888 888 888 888 888 888 888 8888888888 8888b. 888d888 .d88888 88888b. 8888b. 888888 888 888 88b 888P d88 888 888 88b 88b 888 888 888 .d888888 888 888 888 888 888 .d888888 888 888 888 888 888 888 Y88b 888 888 888 888 888 Y88b. 888 888 Y888888 888 Y88888 888 888 Y888888 Y888 Welcome to Hardhat v2.9.3 ? What do you want to do? … ❯ Create a basic sample project Create an advanced sample project Create an advanced sample project that uses TypeScript Create an empty hardhat.config.js Quit √ What do you want to do? · Create a basic sample project √ Hardhat project root: · C:\Users\shinobu\NoNameSeminer\ethereum\hardhat_project √ Do you want to add a .gitignore? (Y/n) · y √ Help us improve Hardhat with anonymous crash reports & basic usage data? (Y/n) · true You need to install these dependencies to run the sample project: npm install --save-dev "hardhat@^2.9.3" "@nomiclabs/hardhat-waffle@^2.0.0" "ethereum-waffle@^3.0.0" "chai@^4.2.0" "@nomiclabs/hardhat-ethers@^2.0.0" "ethers@^5.0.0" Project created See the README.md file for some example tasks you can run. 上記の最後で指定された通り、必要な npm パッケージをインストールします。 hardhat_project> npm install --save-dev "hardhat@^2.9.3" "@nomiclabs/hardhat-waffle@^2.0.0" "ethereum-waffle@^3.0.0" "chai@^4.2.0" "@nomiclabs/hardhat-ethers@^2.0.0" "ethers@^5.0.0" 生成されたファイルを確認してみます。 hardhat_project> ls ディレクトリ: C:\Users\shinobu\NoNameSeminer\ethereum\hardhat_project Mode LastWriteTime Length Name ---- ------------- ------ ---- d----- 2022/05/11 13:34 contracts d----- 2022/05/11 13:43 node_modules d----- 2022/05/11 13:34 scripts d----- 2022/05/11 13:34 test -a---- 2022/05/11 13:34 83 .gitignore -a---- 2022/05/11 11:16 572 hardhat.config.js -a---- 2022/05/11 13:43 863535 package-lock.json -a---- 2022/05/11 13:43 249 package.json -a---- 2022/05/11 11:16 467 README.md * contracts: スマートコントラクトのソースコードを格納するディレクトリ * サンプルの「Greeter.sol」が既に格納されています。 * scripts: スマートコントラクトを ethereum ブロックチェーンにデプロイするためのスクリプトを格納するディレクトリ(他の目的のスクリプトが格納されることもあるかもしれません。) * サンプルの「Greeter」スマートコントラクトをデプロイする sample-script.js が既に格納されています。 * test: テストプログラムを格納するディレクトリ * サンプルの「Greeter」スマートコントラクトをテストする sample-test.js が既に格納されています。 * hardhat.config.js: Hardhat の設定ファイル Hardhat のバージョンとコマンドの仕様を確認してみます。 hardhat_project> npx hardhat Hardhat version 2.9.3 Usage: hardhat [GLOBAL OPTIONS] [TASK OPTIONS] GLOBAL OPTIONS: --config A Hardhat config file. --emoji Use emoji in messages. --help Shows this message, or a task's help if its name is provided --max-memory The maximum amount of memory that Hardhat can use. --network The network to connect to. --show-stack-traces Show stack traces. --tsconfig A TypeScript config file. --verbose Enables Hardhat verbose logging --version Shows hardhat's version. AVAILABLE TASKS: check Check whatever you need clean Clears the cache and deletes all artifacts compile Compiles the entire project, building all artifacts console Opens a hardhat console flatten Flattens and prints contracts and their dependencies help Prints this message node Starts a JSON-RPC server on top of Hardhat Network run Runs a user-defined script after compiling the project test Runs mocha tests To get help for a specific task run: npx hardhat help [task] ===== コンパイル ===== Hardhat セットアップ時に自動的に作成されている contracts/Greeter.sol をコンパイルします。 hardhat_project> npx hardhat compile ===== テスト ===== Hardhat セットアップ時に自動的に作成されている test/sample-test.js を使って Greeter スマートコントラクトのテストを行います。 hardhat_project> npx hardhat test Greeter Deploying a Greeter with greeting: Hello, world! Changing greeting from 'Hello, world!' to 'Hola, mundo!' ✔ Should return the new greeting once it's changed (1328ms) 1 passing (1s) ===== node の起動 ===== Hardhat を Ganache や ganache-cli のように ethereum ブロックチェーン(node)を起動することができます。 ethereum ブロックチェーンにスマートコントラクトをデプロイし、Hardhat 外部からも連携ができるように、ethereum ブロックチェーンを起動します。 新たなターミナル(PowerShell等)を起動し、以下のコマンドで node を起動してください。 hardhat_project> npx hardhat node Hardhat の node には固定で以下のアカウントが自動作成されます。これは毎回同じアドレスであるため、以下の情報も毎回利用できます。 Accounts ======== WARNING: These accounts, and their private keys, are publicly known. Any funds sent to them on Mainnet or any other live network WILL BE LOST. Account #0: 0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266 (10000 ETH) Private Key: 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 Account #1: 0x70997970c51812dc3a010c7d01b50e0d17dc79c8 (10000 ETH) Private Key: 0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d Account #2: 0x3c44cdddb6a900fa2b585dd299e03d12fa4293bc (10000 ETH) Private Key: 0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a Account #3: 0x90f79bf6eb2c4f870365e785982e1f101e93b906 (10000 ETH) Private Key: 0x7c852118294e51e653712a81e05800f419141751be58f605c371e15141b007a6 Account #4: 0x15d34aaf54267db7d7c367839aaf71a00a2c6a65 (10000 ETH) Private Key: 0x47e179ec197488593b187f80a00eb0da91f1b9d0b13f8733639f19c30a34926a Account #5: 0x9965507d1a55bcc2695c58ba16fb37d819b0a4dc (10000 ETH) Private Key: 0x8b3a350cf5c34c9194ca85829a2df0ec3153be0318b5e2d3348e872092edffba Account #6: 0x976ea74026e726554db657fa54763abd0c3a0aa9 (10000 ETH) Private Key: 0x92db14e403b83dfe3df233f83dfa3a0d7096f21ca9b0d6d6b8d88b2b4ec1564e Account #7: 0x14dc79964da2c08b23698b3d3cc7ca32193d9955 (10000 ETH) Private Key: 0x4bbbf85ce3377467afe5d46f804f221813b2bb87f24d81f60f1fcdbf7cbf4356 Account #8: 0x23618e81e3f5cdf7f54c3d65f7fbc0abf5b21e8f (10000 ETH) Private Key: 0xdbda1821b80551c9d65939329250298aa3472ba22feea921c0cf5d620ea67b97 Account #9: 0xa0ee7a142d267c1f36714e4a8f75612f20a79720 (10000 ETH) Private Key: 0x2a871d0798f97d79848a013d4936a73bf4cc922c825d33c1cf7073dff6d409c6 Account #10: 0xbcd4042de499d14e55001ccbb24a551f3b954096 (10000 ETH) Private Key: 0xf214f2b2cd398c806f84e317254e0f0b801d0643303237d97a22a48e01628897 Account #11: 0x71be63f3384f5fb98995898a86b02fb2426c5788 (10000 ETH) Private Key: 0x701b615bbdfb9de65240bc28bd21bbc0d996645a3dd57e7b12bc2bdf6f192c82 Account #12: 0xfabb0ac9d68b0b445fb7357272ff202c5651694a (10000 ETH) Private Key: 0xa267530f49f8280200edf313ee7af6b827f2a8bce2897751d06a843f644967b1 Account #13: 0x1cbd3b2770909d4e10f157cabc84c7264073c9ec (10000 ETH) Private Key: 0x47c99abed3324a2707c28affff1267e45918ec8c3f20b8aa892e8b065d2942dd Account #14: 0xdf3e18d64bc6a983f673ab319ccae4f1a57c7097 (10000 ETH) Private Key: 0xc526ee95bf44d8fc405a158bb884d9d1238d99f0612e9f33d006bb0789009aaa Account #15: 0xcd3b766ccdd6ae721141f452c550ca635964ce71 (10000 ETH) Private Key: 0x8166f546bab6da521a8369cab06c5d2b9e46670292d85c875ee9ec20e84ffb61 Account #16: 0x2546bcd3c84621e976d8185a91a922ae77ecec30 (10000 ETH) Private Key: 0xea6c44ac03bff858b476bba40716402b03e41b8e97e276d1baec7c37d42484a0 Account #17: 0xbda5747bfd65f08deb54cb465eb87d40e51b197e (10000 ETH) Private Key: 0x689af8efa8c651a91ad287602527f3af2fe9f6501a7ac4b061667b5a93e037fd Account #18: 0xdd2fd4581271e230360230f9337d5c0430bf44c0 (10000 ETH) Private Key: 0xde9be858da4a475276426320d5e9262ecfc3ba460bfac56360bfa6c4c28b4ee0 Account #19: 0x8626f6940e2eb28930efb4cef49b2d1f2c9c1199 (10000 ETH) Private Key: 0xdf57089febbacf7ba0bc227dafbffa9fc08a93fdc68e1e42411a14efcf23656e WARNING: These accounts, and their private keys, are publicly known. Any funds sent to them on Mainnet or any other live network WILL BE LOST. ===== デプロイ ===== Hardhat セットアップ時に自動的に作成されている scripts/sample-script.js を使って Greeter スマートコントラクトを ethereum ブロックチェーンにデプロイします。 先ほど立ち上げた node にデプロイするために「--network localhost」オプションを指定します。 hardhat_project> npx hardhat run scripts/sample-script.js --network localhost Deploying a Greeter with greeting: Hello, Hardhat! Greeter deployed to: 0x5FbDB2315678afecb367f032d93F642f64180aa3 上記の場合だと「0x5FbDB2315678afecb367f032d93F642f64180aa3」が Greeter スマートコントラクトのアドレスですので、メモしておいてください。 ===== コンソールでスマートコントラクトの実行 ===== 「npx hardhat console」でコンソールが起動します。 先ほど立ち上げた node に接続するために「--network localhost」オプションを指定します。 hardhat_project> npx hardhat console --network localhost Welcome to Node.js v16.13.1. > const Greeter = await ethers.getContractAt('Greeter', '0x5fbdb2315678afecb367f032d93f642f64180aa3'); undefined > await Greeter.greet(); 'Hello, Hardhat!' > await Greeter.setGreeting('Hello, World! World is fun!!!'); { hash: '0x3868b3b8f7a87a5fd8453444eba9f17193e1835be6ea6cd90ce1b31e41a03b16', type: 2, accessList: [], blockHash: '0x481f987f494e634543be25dbc0e262504709acdf0f00fa9f7ad80d2cf344a4f4', blockNumber: 2, transactionIndex: 0, confirmations: 1, from: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', gasPrice: BigNumber { _hex: '0x2dd9cf7c', _isBigNumber: true }, maxPriorityFeePerGas: BigNumber { _hex: '0x00', _isBigNumber: true }, maxFeePerGas: BigNumber { _hex: '0x3a07aa98', _isBigNumber: true }, gasLimit: BigNumber { _hex: '0x8c47', _isBigNumber: true }, to: '0x5FbDB2315678afecb367f032d93F642f64180aa3', value: BigNumber { _hex: '0x00', _isBigNumber: true }, nonce: 1, data: '0xa41368620000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001d48656c6c6f2c20576f726c642120576f726c642069732066756e212121000000', r: '0x240d275144cca8e5e06e0e46e181c19d8b24605211e0e03af72f9159a24b1a7c', s: '0x6953c1d27ef130ce4330d95191c7d861b85b338ae2d44a1c27fb3ed94acab803', v: 0, creates: null, chainId: 31337, wait: [Function (anonymous)] } > await Greeter.greet(); 'Hello, World! World is fun!!!' ===== 別の node に接続する ===== hardhat.config.js に ethereum ブロックチェーン(node) の設定を追加することで、メインネットや Ropsten や Ganache の node に接続することができます。 以下、Ganache を設定して console 接続する例です。 hardhat.config.js の module.exports に以下を追加。 module.exports = { solidity: "0.8.4", networks: { ganache: { url: "http://localhost:7545", } }, }; ganache にコンソール接続 hardhat_project> npx hardhat console --network ganache Welcome to Node.js v16.13.1. Type ".help" for more information. > const signers = await ethers.getSigners(); undefined > signers[0].address '0x9A99681B214e78152a3b6D851852E2C295f89E09' ===== hardhat console でアカウントの切り替え ===== TODO: もっと良い方法があるはず! Hardhat はデフォルトでアカウント一覧の先頭のアカウントが使用される。 hardhat console でトランザクションが発生するような処理を行った場合、上記のアカウントが sender として使用されることになる。 hardhat.config.js の network 設定で「アカウント一覧」を絞ることで「先頭のアカウント」を変更し、トランザクションの sender を変更する。 > code hardhat.config.js hardhat.confg.js の network 設定に以下を追記。 networks: { localhost_account2: { url: 'http://127.0.0.1:8545', //from: '0x70997970C51812dc3A010C7d01b50e0d17dc79C8', accounts: [ '0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d', '0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a', ], }, hardhat console 使用時に以下のように「localhost_account2」を選択すれば、上記 accounts の先頭が sender として使用される。 > npx hardhat console --network localhost_account2