Ethereum コントラクト開発 Hello world ローカル編

26 min read

この記事について

株式会社CauchyEのメンバーが、社内の開発や勉強会等に関する技術的なアウトプットを行い、弊社の開発における取組や、弊社メンバーの学びに対する取組等をお伝えしていく予定です。弊社の取組の内容や、弊社の雰囲気等が伝わりますと幸いです。

記事作成者自己紹介

株式会社CauchyEのエンジニアの松岡靖典です。
ブロックチェーンの技術的な面白さに魅了され、Web開発の世界を歩み始めました。
NPO法人NEM技術普及推進会NEMTUSの理事としてブロックチェーン技術の普及推進活動に従事したり、個人開発等の取り組みも行っています。
JavaScript, TypeScript, Angular, Firebase, NEM, Symbol, Cosmosが好きですが、チャンスがあれば様々な技術に触れていきたいと思っています。

記事内容要約

弊社のブロックチェーン部門LCNEMではブロックチェーンを用いた様々な開発に取り組んでいます。最近の業務でEthereumを用いた案件の引き合いがあり、技術調査を行って社内の勉強会で共有した内容をこちらの記事にまとめてみました。こちらの記事[1]を参考にさせて頂き、Ethereumのコントラクト開発のHello world的な内容をローカル開発環境で試すという内容です。(機会があれば、テストネットでのコントラクト開発や、NFTが盛り上がりを見せているERC721等の記事もいずれ作成してみたいと思っています。 -> テストネットでのコントラクト開発ERC721のコントラクト開発の記事も公開しましたのでぜひ併せてご参照ください。)

この記事での目標

  • hardhat[2]を用いて自動的に生成されるHello world的なコントラクトを使って、ローカルでのコントラクトの開発のプロセスを一通り試し、コントラクトの開発への理解を深め、次のプロセス(≒テストネットでのコントラクト開発等)に進むための前提となる知識を得ることを目標とします。

環境構築

前提環境

  • OS
    • Ubuntu 20.04 (on WSL2)
  • Node.js
    • v14.17.4 (記事作成時点で最新のLTS)
  • npm
    • 7.20.5 (記事作成時点で最新のnpm)

その他のLinuxやMac等でも可能と思いますが未検証です。

ディレクトリ作成・Node.jsプロジェクトとして初期化

まず最初にレポジトリ直下にcontractsというディレクトリを作成し、作成したcontractsディレクトリ配下をNode.jsプロジェクトとして初期化します。

mkdir contracts
cd contracts
npm init -y

hardhatでコントラクト開発環境を構築

次に、ローカル開発用ネットワーク、コントラクトのコンパイル、コントラクトのデプロイ、テストのための環境構築を行います。
開発環境として、それらの環境が一式そろったhardhatを利用します。

以下コマンドを実行して、hardhatの開発環境の初期化を行います。

npx hardhat init

このコマンドを実行すると途中プロンプトで情報の入力や選択が求められます。以下のようにすべてデフォルトで選択して進めると、Solidityで記述されたHello World的なコントラクトのサンプルと、それをローカル開発用ネットワークへデプロイしたりテストするために必要なリソースが一気に作成されます。必要なパッケージ等もインストールされます。

どのようなリソースが作成されたのか詳細が気になる方はこちらのコミットをご参照ください。

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.6.0

✔ What do you want to do? · Create a sample project
✔ Hardhat project root: · /home/yasunori_matsuoka/github.com/next-web-technology/nft-erc721-sample/contracts
✔ Do you want to add a .gitignore? (Y/n) · y
✔ Do you want to install the sample project's dependencies with npm (hardhat @nomiclabs/hardhat-waffle ethereum-waffle chai @nomiclabs/hardhat-ethers ethers)? (Y/n) · y

~~中略~~

Project created

Try running some of the following tasks:
npx hardhat accounts
npx hardhat compile
npx hardhat test
npx hardhat node
node scripts/sample-script.js
npx hardhat help

環境構築はコマンドで一発で完了でした。
コマンド一発で環境構築ができるのはとても便利ですごいですね!

Solidityでコントラクト記述

自動的にサンプルとして作成されたHello World的なコントラクトのファイルの記述を確認してみると以下のようなファイルが自動的に生成されたようです。

contracts/contracts/Greeter.sol

//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;

import "hardhat/console.sol";


contract Greeter {
  string greeting;
  
  constructor(string memory _greeting) {
    console.log("Deploying a Greeter with greeting:", _greeting);
    greeting = _greeting;
  }
  
  function greet() public view returns (string memory) {
    return greeting;
  }
  
  function setGreeting(string memory _greeting) public {
    console.log("Changing greeting from '%s' to '%s'", greeting, _greeting);
    greeting = _greeting;
  }
}

記述されているコントラクトに目を通すと、以下のような内容のコントラクトと思われます。

  1. デプロイ時に引数として指定した文字列が挨拶文として最初に記録される。
  2. コントラクトの中のgreetという関数が呼ばれたら、現時点で記録されている挨拶文の文字列が取得できる。
  3. コントラクトの中のsetGreetingという関数が新しい挨拶文の文字列を引数として指定されて呼ばれたら、記録されていた古い挨拶文が新しい挨拶文に置き換わる。

コントラクトをコンパイルしてバイトコードを生成

solidityでのコントラクトの記述ができたら、それらをコンパイルしてバイトコードを生成する必要があります。

npx hardhat compileコマンドを実行すると、コンパイルが実行され、contracts/artifacts/contracts/Greeter.sol/Greeter.jsonというファイルが生成されました。ファイルの中身はとても長かったので折り畳み表示しています。興味がある方は展開してご覧ください。

この記事の中ではこれらの情報を直接使用することはないものの、abiやbytecode等の情報をいずれ使うことになりますので覚えておくと良いでしょう。

Greeter.json
{
  "_format": "hh-sol-artifact-1",
  "contractName": "Greeter",
  "sourceName": "contracts/Greeter.sol",
  "abi": [
    {
      "inputs": [
        {
          "internalType": "string",
          "name": "_greeting",
          "type": "string"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "constructor"
    },
    {
      "inputs": [],
      "name": "greet",
      "outputs": [
        {
          "internalType": "string",
          "name": "",
          "type": "string"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "string",
          "name": "_greeting",
          "type": "string"
        }
      ],
      "name": "setGreeting",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    }
  ],
  "bytecode": "0x60806040523480156200001157600080fd5b5060405162000c3238038062000c32833981810160405281019062000037919062000278565b6200006760405180606001604052806022815260200162000c1060229139826200008760201b620001ce1760201c565b80600090805190602001906200007f92919062000156565b5050620004c5565b620001298282604051602401620000a0929190620002fe565b6040516020818303038152906040527f4b5c4277000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506200012d60201b60201c565b5050565b60008151905060006a636f6e736f6c652e6c6f679050602083016000808483855afa5050505050565b8280546200016490620003ea565b90600052602060002090601f016020900481019282620001885760008555620001d4565b82601f10620001a357805160ff1916838001178555620001d4565b82800160010185558215620001d4579182015b82811115620001d3578251825591602001919060010190620001b6565b5b509050620001e39190620001e7565b5090565b5b8082111562000202576000816000905550600101620001e8565b5090565b60006200021d620002178462000362565b62000339565b9050828152602081018484840111156200023657600080fd5b62000243848285620003b4565b509392505050565b600082601f8301126200025d57600080fd5b81516200026f84826020860162000206565b91505092915050565b6000602082840312156200028b57600080fd5b600082015167ffffffffffffffff811115620002a657600080fd5b620002b4848285016200024b565b91505092915050565b6000620002ca8262000398565b620002d68185620003a3565b9350620002e8818560208601620003b4565b620002f381620004b4565b840191505092915050565b600060408201905081810360008301526200031a8185620002bd565b90508181036020830152620003308184620002bd565b90509392505050565b60006200034562000358565b905062000353828262000420565b919050565b6000604051905090565b600067ffffffffffffffff82111562000380576200037f62000485565b5b6200038b82620004b4565b9050602081019050919050565b600081519050919050565b600082825260208201905092915050565b60005b83811015620003d4578082015181840152602081019050620003b7565b83811115620003e4576000848401525b50505050565b600060028204905060018216806200040357607f821691505b602082108114156200041a576200041962000456565b5b50919050565b6200042b82620004b4565b810181811067ffffffffffffffff821117156200044d576200044c62000485565b5b80604052505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f8301169050919050565b61073b80620004d56000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063a41368621461003b578063cfae321714610057575b600080fd5b6100556004803603810190610050919061043d565b610075565b005b61005f61013c565b60405161006c91906104b7565b60405180910390f35b6101226040518060600160405280602381526020016106e3602391396000805461009e90610610565b80601f01602080910402602001604051908101604052809291908181526020018280546100ca90610610565b80156101175780601f106100ec57610100808354040283529160200191610117565b820191906000526020600020905b8154815290600101906020018083116100fa57829003601f168201915b50505050508361026a565b8060009080519060200190610138929190610332565b5050565b60606000805461014b90610610565b80601f016020809104026020016040519081016040528092919081815260200182805461017790610610565b80156101c45780601f10610199576101008083540402835291602001916101c4565b820191906000526020600020905b8154815290600101906020018083116101a757829003601f168201915b5050505050905090565b61026682826040516024016101e49291906104d9565b6040516020818303038152906040527f4b5c4277000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050610309565b5050565b61030483838360405160240161028293929190610510565b6040516020818303038152906040527f2ced7cef000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050610309565b505050565b60008151905060006a636f6e736f6c652e6c6f679050602083016000808483855afa5050505050565b82805461033e90610610565b90600052602060002090601f01602090048101928261036057600085556103a7565b82601f1061037957805160ff19168380011785556103a7565b828001600101855582156103a7579182015b828111156103a657825182559160200191906001019061038b565b5b5090506103b491906103b8565b5090565b5b808211156103d15760008160009055506001016103b9565b5090565b60006103e86103e384610581565b61055c565b90508281526020810184848401111561040057600080fd5b61040b8482856105ce565b509392505050565b600082601f83011261042457600080fd5b81356104348482602086016103d5565b91505092915050565b60006020828403121561044f57600080fd5b600082013567ffffffffffffffff81111561046957600080fd5b61047584828501610413565b91505092915050565b6000610489826105b2565b61049381856105bd565b93506104a38185602086016105dd565b6104ac816106d1565b840191505092915050565b600060208201905081810360008301526104d1818461047e565b905092915050565b600060408201905081810360008301526104f3818561047e565b90508181036020830152610507818461047e565b90509392505050565b6000606082019050818103600083015261052a818661047e565b9050818103602083015261053e818561047e565b90508181036040830152610552818461047e565b9050949350505050565b6000610566610577565b90506105728282610642565b919050565b6000604051905090565b600067ffffffffffffffff82111561059c5761059b6106a2565b5b6105a5826106d1565b9050602081019050919050565b600081519050919050565b600082825260208201905092915050565b82818337600083830152505050565b60005b838110156105fb5780820151818401526020810190506105e0565b8381111561060a576000848401525b50505050565b6000600282049050600182168061062857607f821691505b6020821081141561063c5761063b610673565b5b50919050565b61064b826106d1565b810181811067ffffffffffffffff8211171561066a576106696106a2565b5b80604052505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f830116905091905056fe4368616e67696e67206772656574696e672066726f6d202725732720746f2027257327a2646970667358221220d8b702fd211fe2829242f362fda35c636e2590000ac3fa2b44f0ac2fb1183cd564736f6c634300080400334465706c6f79696e67206120477265657465722077697468206772656574696e673a",
  "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c8063a41368621461003b578063cfae321714610057575b600080fd5b6100556004803603810190610050919061043d565b610075565b005b61005f61013c565b60405161006c91906104b7565b60405180910390f35b6101226040518060600160405280602381526020016106e3602391396000805461009e90610610565b80601f01602080910402602001604051908101604052809291908181526020018280546100ca90610610565b80156101175780601f106100ec57610100808354040283529160200191610117565b820191906000526020600020905b8154815290600101906020018083116100fa57829003601f168201915b50505050508361026a565b8060009080519060200190610138929190610332565b5050565b60606000805461014b90610610565b80601f016020809104026020016040519081016040528092919081815260200182805461017790610610565b80156101c45780601f10610199576101008083540402835291602001916101c4565b820191906000526020600020905b8154815290600101906020018083116101a757829003601f168201915b5050505050905090565b61026682826040516024016101e49291906104d9565b6040516020818303038152906040527f4b5c4277000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050610309565b5050565b61030483838360405160240161028293929190610510565b6040516020818303038152906040527f2ced7cef000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050610309565b505050565b60008151905060006a636f6e736f6c652e6c6f679050602083016000808483855afa5050505050565b82805461033e90610610565b90600052602060002090601f01602090048101928261036057600085556103a7565b82601f1061037957805160ff19168380011785556103a7565b828001600101855582156103a7579182015b828111156103a657825182559160200191906001019061038b565b5b5090506103b491906103b8565b5090565b5b808211156103d15760008160009055506001016103b9565b5090565b60006103e86103e384610581565b61055c565b90508281526020810184848401111561040057600080fd5b61040b8482856105ce565b509392505050565b600082601f83011261042457600080fd5b81356104348482602086016103d5565b91505092915050565b60006020828403121561044f57600080fd5b600082013567ffffffffffffffff81111561046957600080fd5b61047584828501610413565b91505092915050565b6000610489826105b2565b61049381856105bd565b93506104a38185602086016105dd565b6104ac816106d1565b840191505092915050565b600060208201905081810360008301526104d1818461047e565b905092915050565b600060408201905081810360008301526104f3818561047e565b90508181036020830152610507818461047e565b90509392505050565b6000606082019050818103600083015261052a818661047e565b9050818103602083015261053e818561047e565b90508181036040830152610552818461047e565b9050949350505050565b6000610566610577565b90506105728282610642565b919050565b6000604051905090565b600067ffffffffffffffff82111561059c5761059b6106a2565b5b6105a5826106d1565b9050602081019050919050565b600081519050919050565b600082825260208201905092915050565b82818337600083830152505050565b60005b838110156105fb5780820151818401526020810190506105e0565b8381111561060a576000848401525b50505050565b6000600282049050600182168061062857607f821691505b6020821081141561063c5761063b610673565b5b50919050565b61064b826106d1565b810181811067ffffffffffffffff8211171561066a576106696106a2565b5b80604052505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f830116905091905056fe4368616e67696e67206772656574696e672066726f6d202725732720746f2027257327a2646970667358221220d8b702fd211fe2829242f362fda35c636e2590000ac3fa2b44f0ac2fb1183cd564736f6c63430008040033",
  "linkReferences": {},
  "deployedLinkReferences": {}
}

コントラクトの単体テスト

コントラクトは一度デプロイしてしまうと原則として修正は不可能なため、事前に慎重にテストを行う必要があります。
hardhatでは自動テストを実行するための環境も構築されており、サンプルとして以下のようなテストコードが自動生成されていました。

contracts/test/sample-test.js

const { expect } = require("chai");

describe("Greeter", function () {
  it("Should return the new greeting once it's changed", async function () {
    const Greeter = await ethers.getContractFactory("Greeter");
    const greeter = await Greeter.deploy("Hello, world!");
    await greeter.deployed();

    expect(await greeter.greet()).to.equal("Hello, world!");

    const setGreetingTx = await greeter.setGreeting("Hola, mundo!");

    // wait until the transaction is mined
    await setGreetingTx.wait();

    expect(await greeter.greet()).to.equal("Hola, mundo!");
  });
});

テスト内容は以下の通りです。

  1. コントラクトデプロイ時に、"Hello, world!"という文字列を引数として指定してGreeterというコントラクトをデプロイし、
  2. 1のトランザクションがブロックに組み込まれるのを待って、
  3. コントラクト内のgreet関数を呼び出して実行すると、1で指定した"Hello, world!"という文字列が取得できることを確認する。
  4. 次に、コントラクト内のsetGreeting関数を、引数"Hola, mundo!"を指定して、呼び出して実行し、
  5. 4のトランザクションがブロックに組み込まれるのを待って、
  6. コントラクト内のgreet関数を呼び出して実行すると、4で指定した"Hola, mundo!"という文字列が取得できることを確認する。

npx hardhat testコマンドを実行すると、以下のように自動テストが実行され、テストをpassしました!🎉

$ npx hardhat test

Compiling 2 files with 0.8.4
Compilation finished successfully


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 (384ms)


1 passing (385ms)

hardhatでのコントラクトのテストコードと実行結果を一番最初に目の当たりにしたとき、接続先ノードの設定や、トランザクションの発行を行うためのアカウントの秘密鍵等の設定がどこにも明示的に書かれていないにもかかわらず、テストが動くことにとても驚きました。コントラクトの単体テスト用の環境を、hardhatコマンドが全て良い感じに暗黙的に解決してくれているようです。

ローカル開発用ネットワークを明示的に指定してコントラクトをテスト

hardhatでテストをpassすることが確認できましたが、あまりにもあっけなくテストをパスして、実際に動いている実感が少なく不安を感じたので、ローカル開発用ネットワークを動作させ、そこにコントラクトをデプロイしてテストを実行するような形を試してみました。

ローカル開発用ブロックチェーンネットワークを動作させるには、npx hardhat nodeコマンドを実行します。実行すると、以下のようにローカル開発用ブロックチェーンネットワーク上で開発用のETHの残高があるアカウントのアドレスと秘密鍵の情報が一覧で表示された後、待機状態になります。

ここでは、秘密鍵も含めた表示結果をそのまま表示していますが、秘密鍵の情報はこのようにオープンにしてはならないですし、言うまでもありませんが、こちらに表示されている秘密鍵を何らかの形で流用するようなことは絶対に避けてください。

$ npx hardhat node

Started HTTP and WebSocket JSON-RPC server at http://127.0.0.1:8545/

Accounts
========
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

次に、別のターミナルを立ち上げて、npx hardhat test --network localhostコマンドを実行すると、以下のようにテストがpassするとともに、

$ npx hardhat test --network localhost

Greeter
✓ Should return the new greeting once it's changed (217ms)

1 passing (219ms)

ローカル開発用ネットワークのノードのログが表示されているターミナルに、以下のように、コントラクトのデプロイや、コントラクト内の関数の呼び出し等のログが出力されました。
どのようなAPIがコールされ、結果的にブロックチェーン上で何が実行されたかが直感的にわかりやすく、とても便利だと感じました。

web3_clientVersion (2)
eth_chainId
eth_accounts
eth_blockNumber
eth_chainId (2)
eth_estimateGas
eth_feeHistory
eth_sendTransaction
Contract deployment: Greeter
Contract address:    0x9fe46736679d2d9a65f0992f2272de9f3c7fa6e0
Transaction:         0x6936bfa59710ea4a61c599ea06a2479674faeb41e2ffca1d808e53bfedc448eb
From:                0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266
Value:               0 ETH
Gas used:            496990 of 496990
Block #3:            0xa63a564fc6df23e38319871a0ea90ec8967d83c99ed3cd2d57b6a65b3407aa01

console.log:
Deploying a Greeter with greeting: Hello, world!

eth_chainId
eth_getTransactionByHash
eth_chainId
eth_getTransactionReceipt
eth_chainId
eth_call
Contract call:       Greeter#greet
From:                0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266
To:                  0x9fe46736679d2d9a65f0992f2272de9f3c7fa6e0

eth_chainId
eth_estimateGas
eth_feeHistory
eth_sendTransaction
Contract call:       Greeter#setGreeting
Transaction:         0xac1d2cc3158f587b941eaebaa265a1fd4ef89fdca2a1a63e09123e2478ca1b71
From:                0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266
To:                  0x9fe46736679d2d9a65f0992f2272de9f3c7fa6e0
Value:               0 ETH
Gas used:            35426 of 35702
Block #4:            0xd9cdeb3f16b082a5bf295892107683574c24148e0235b7bad012a677dc134adf

console.log:
Changing greeting from 'Hello, world!' to 'Hola, mundo!'

eth_chainId
eth_getTransactionByHash
eth_chainId
eth_getTransactionReceipt
eth_chainId
eth_call
Contract call:       Greeter#greet
From:                0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266
To:                  0x9fe46736679d2d9a65f0992f2272de9f3c7fa6e0

npx hardhat testコマンドだけを実行したときと比べ、テスト結果だけでなく、ノード側のログ出力も確認できたことから、意図通りコントラクトのデプロイやコントラクトのテストが実行できたことをより一層実感できました。

まとめ

ローカルでのコントラクト開発の流れ

  • ディレクトリ作成し、Node.jsプロジェクトとして初期化
  • npx hardhat initで環境構築
  • (solidityでコントラクトを記述 ... この記事では環境構築時に自動生成されたものをそのまま使用)
  • npx hardhat compileで記述したコントラクトをコンパイル
  • (コントラクトのテストコードを記述 ... この記事では環境構築時に自動生成されたものをそのまま使用)
  • npx hardhat testでテスト
  • npx hardhat nodeでローカルでテスト用のEthereumノードを動作させ、npx hardhat testでそのノードに対して明示的にテストを実行させることもできる

所感

  • 開発環境の構築がコマンド一発で済むのはとても便利で感動しました。
  • ローカルでの開発では、秘密鍵等のアカウント情報や、接続先ネットワークのノードの情報等を、hardhatが全て良い感じに暗黙的に解決してくれるようで、それらの情報や設定を、明示的に一切書かずともテストが動くことにとても驚きました。
  • 実際のサービスでサーバーサイドで何らかのコントラクトを呼び出したりする実装を行う場合、今回の記事のようにhardhatコマンドを用いて全てを行うのは不便で、Node.jsで直接実行できるようにする必要があると思います。その場合、hardhatコマンドを使わずに、残高が入った秘密鍵等のアカウント情報や、接続先ネットワークのノードの情報等を適切に指定する実装を加える必要があると感じました。(いずれ機会があれば、記事にしてみたいと思います。 -> テストネットでのコントラクト開発の記事を公開しましたのでぜひご参照ください。)

【エンジニア採用中】
ブロックチェーンやデータサイエンスに興味のあるエンジニアを積極的に採用中です!
以下のページから応募お待ちしております。

https://cauchye.com/company/recruit
脚注
  1. https://qiita.com/mogiken/items/54bc24669068ecadf957 ... この記事を作成するのに、こちらの資料がとても参考になりました。この場を借りてお礼申し上げます。 ↩︎

  2. https://hardhat.org/ ↩︎

Discussion

ログインするとコメントできます