今更ながらではあるが、2023年9月にConsensysよりTruffleの開発停止が発表された。
上記ブログでは、今後のSmartContractの開発環境はHardhatを利用するようにアナウンスされている。
自分も今までTruffleのみでHardhatは利用していなかったのでこれを機にHardhatの使い方の基本を学ぶ。
ここで取り扱うのはEthereumのSmartContractである。
Hardhat公式ブログのGuidesをやっていく。
hardhat.org
環境
環境については以下で実施。node.jsのインストール等の説明は割愛する。
1. hardhatのインストール
早速hardhatをインストールする。適当なディレクトリを作成してその中で作業を実施。
今回は`hardhat_sample`というディレクトリを作成して作業した。
インストール自体はスムーズ。以下のコマンドを実行するだけで良い。
yarn init -y yarn add --dev hardhat
以下のコマンドでバージョンを確認。無事インストールできている。
yarn hardhat --version
yarn run v1.22.21 $ /Users/nakajo/work/ethereum-test/hardhat_sample/node_modules/.bin/hardhat --version 2.22.3
2. hardhatプロジェクトの作成(初期化)
続いて、hardhatプロジェクトを作成する。以下の初期化コマンドを実行すると。
必要なフォルダや設定ファイル、依存ライブラリなどを自動で作成してくれる。
npx hardhat init
初期化コマンドを実行するとhardhatの構成を聞かれる。ここでは一番簡単な先頭のJavaScriptプロジェクトを選択。本番用など実際に広く利用するプロジェクトの場合はTypeScriptを選択することをおすすめする。
今回は基本編なので各選択肢の詳細については解説しない。(というか僕もそんなにわかってない)
Enterキーで選択すると、次にプロジェクトルートのディレクトリを聞かれる。特に変更する必要はないのでそのままEnter。
次は.gitignoreファイルを作成していいかを聞かれる。今回はまだ作成されていないのでここもyを選択して作成してもらう。
最後にplug-in(依存ライブラリ)をインストールして良いか聞かれる。中にはhardhatの基本的な機能を使うのに必要なものも多く含まれているので、特段理由がなければここもyを選択で良いと思う。
plug-inのインストールが終わればプロジェクト作成は完了。
3. Contractの作成からデプロイまで
hardhatプロジェクトの環境を作成したので早速Contractを作成し、hardhat内蔵のローカルノードにデプロイするまでをやってみる。
作成するContractはもはや定番となるERC20Token Contract。
なのでまず最初に`@openzeppelin/contracts`ライブラリをインストールする。
yarn add -D @openzeppelin/contracts@5.0.2
※バージョン変わると構成変わったりなどでcompile通らなくなることがあるので、記事執筆時にインストールしたバージョンを指定している。
次にコントラクトを作成する。作成する場所はtruffleと同じく、 contracts/ディレクトリ以下。hardhatプロジェクト初期化時にはサンプルとしてLock.solというコントラクトが入っている。
contracts/GLDToken.sol ファイルを作成して、以下の内容をコピペする。
// contracts/GLDToken.sol // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; contract GLDToken is ERC20 { constructor(uint256 initialSupply) ERC20("Gold", "GLD") { _mint(msg.sender, initialSupply); } }
コントラクトを作成したのでデプロイのためにcompileする。compileするためにコマンドを実行。
npx hardhat compile
これで、contracts/以下のファイルが全てコンパイルされる。コンパイル結果のファイルはartifacts/以下に格納される。
続いて、コントラクトをデプロイするためのプログラムを作成。truffleでいうところのmigrationファイル。
Hardhatではignitionというplugi-inを使う。truffleとの違いは、名前が示す通りmigrationではなくあくまでデプロイ作業を簡略・整理するためのライブラリであること。
まぁ、Truffleでもmigration機構を有効活用できるケースはかなり限られていたので妥当ではある。
iginitionはプロジェクト作成時にすでにインストール済みなので、deploy用ファイルを作成して実行するだけである。
ちなみに、サンプルとしてすでに iginition/modules/Lock.jsが生成されている。
ここでは先ほど作成したGLDTokenをデプロイするため、iginition/modules/GLDToken.jsファイルを以下の内容で作成する。
const { buildModule } = require("@nomicfoundation/hardhat-ignition/modules"); const INITIAL_SUPPLY = 1_000_000_000_000_000n; module.exports = buildModule("GLDTokenModule", (m) => { const initialSupply = m.getParameter("initialSupply", INITIAL_SUPPLY); const token = m.contract("GLDToken", [initialSupply], {}); return { token }; });
Contractをデプロイするために、デプロイ先となるhardhatの内蔵nodeを起動する。
npx hardhat node
つづいて新しいコンソールを開いて、以下のコマンドを実行してGLDTokenをデプロイする。
npx hardhat ignition deploy ./ignition/modules/GLDToken.js --network localhost
デプロイに成功した時のスクショ。
また、デプロイが成功すると ignition/deployments/ 以下にデプロイ結果を記録したファイルがchainIDごとに生成される。
後から、Contractのアドレスや消費した手数料などを確認したい場合はここから確認できる。
4. テストネットへのデプロイ
最後にテストネットであるSepoliaにデプロイする。
まずはデプロイ先のネットワーク情報をconfigファイルに設定する。この辺りはtruffleとほとんど同じ。
修正するファイルは hardhat.config.js。
初期状態ではsolidityの設定のみがあるので、その下に以下のnetworks設定を追記する。
networks: { sepolia: { url: "https://sepolia.infura.io/v3/<key>", accounts: [privatekey] } }
hardhat.config.jsの全体として以下のようになる。
require("@nomicfoundation/hardhat-toolbox"); /** @type import('hardhat/config').HardhatUserConfig */ module.exports = { solidity: "0.8.24", networks: { sepolia: { url: "https://sepolia.infura.io/v3/<key>", accounts: [privatekey] } } };
hardhat.config.jsで設定できる他のオプションについては公式ページを参照。
hardhat.org
設定が終わったら、以下のコマンドを実行。--networkオプションに今設定したsepoliaを指定するだけ。
npx hardhat ignition deploy ./ignition/modules/GLDToken.js --network sepolia
sepoliaなどのhardhatが認識しているネットワークにデプロイする場合は確認を求められるので、y を入力する必要がある。
以上でSepoliaへのデプロイも完了。
まとめ
- 基本的な部分ではTruffleとあまり大きな使い方の違いはない。
- Truffleについてある程度精通していればそれほど苦労はしなさそうと感じた。
- ethereumとの接続に使うライブラリにethers.jsを用いているので、細かい作業をする場合はethers.jsに慣れないといけない。
- Truffleではweb3.jsを用いていたので、ethers.jsの使い方を学び直すのが一番大変そう。