はじめに(Introduction)
EVM互換のブロックチェーンで動作するスマートコントラクトをHardhatを使って作成します。
ここではスマートコントラクトのソース作成とデプロイまでを行います。
前回の準備が終わっているものとします。
ソース作成
ERC-20の標準トークンを作成します。
contracts
フォルダ配下に以下のファイルを作成します。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract SampleToken is ERC20, Ownable {
constructor(
string memory name_,
string memory symbol_
) ERC20(name_, symbol_) Ownable(msg.sender) {}
function mint(address account, uint256 value) external onlyOwner {
_mint(account, value);
}
}
ライセンス情報
1行目はソースコードのライセンス情報です。
コンパイラの0.6.8
以降から推奨となっています。
(記載しない場合はコンパイル時に警告がでます。)
ライセンスの一覧はリンク先にあります。
// SPDX-License-Identifier: MIT
コンパイルバージョン
2行目は、コンパイルバージョンです。
ここでは、コンパイルバージョンは^0.8.24
を指定しています。
基本的には最新版を使うと良いです。
pragma solidity ^0.8.24;
インポート
4行目、5行目は外部ファイルのインポートです。
ここでは、Openzeppelinが提供してる、ERC20.sol
とOwnable.sol
をインポートしています。
ERC20.sol
はERC20の抽象コントラクトです。
Ownable.sol
はアクセス制御用の抽象コントラクトです。
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
コントラクト
7行目はコントラクトの宣言です。
contract
のSampleToken
はコントラクト名となります。
is
の後は継承するコントラクトです。(複数あるので,
カンマで連結しています。Openzeppelin)
ここでは、ERC20
とOwnable
となります。
contract SampleToken is ERC20, Ownable {
コンストラクタ
8~11行目はコンストラクタです。
string memory name_
とstring memory symbol_
はコンストラクタのパラメータとなります。ERC20(name_, symbol_)
とOwnable(msg.sender)
は継承しているコントラクトのコンストラクタです。
パラメータをそのままERC20
のコンストラクトに設定しています。
Ownable
にはトランザクション発行者であるmsg.sender
を設定しています。
ここでは、コンストラクタでの処理はありません。
constructor(
string memory name_,
string memory symbol_
) ERC20(name_, symbol_) Ownable(msg.sender) {}
発行
13~15行目はERC20のコインを発行します。
ERC20
の標準仕様には発行(mint
)は存在しませんが、Openzeppelinが提供しているコードには_mint
という内部実行可能(internal
)な関数が用意されているのでそれを使用してERC20のコインを発行します。
だれでも発行可能にしてしまうとコインに価値が無くなってしまうので、onlyOwner
を付与してこのコントラクトのオーナーだけが発行可能としています。
function mint(address account, uint256 value) external onlyOwner {
_mint(account, value);
}
デプロイモジュール作成
ignition/modules
フォルダ配下に以下のファイル(SampleToken.js
)を作成します。
const { buildModule } = require("@nomicfoundation/hardhat-ignition/modules");
module.exports = buildModule("SampleTokenModule", (m) => {
const NAME = "Sample Token";
const SYMBOL = "STC";
const sampleToken = m.contract("SampleToken", [NAME, SYMBOL]);
return { sampleToken };
});
1行目はbuildModule
のインポートです。
const { buildModule } = require("@nomicfoundation/hardhat-ignition/modules");
3行目はbuildModule
でモジュールを作成してエクスポートしています。
このモジュールはSampleTokenModule
をして識別されます。
module.exports = buildModule("SampleTokenModule", (m) => {
4,5行目はコンストラクトのパラメータです。
const NAME = "Sample Token";
const SYMBOL = "STC";
6行目でコントラクトを生成しています。
const sampleToken = m.contract("SampleToken", [NAME, SYMBOL]);
7行目で生成したコントラクトを返しています。
return { sampleToken };
デプロイ
以下のコマンドでモジュールをデプロイします。
npx hardhat ignition deploy .\ignition\modules\SampleToken.js
以下のような結果がでると思います。
You are running Hardhat Ignition against an in-process instance of Hardhat Network.
This will execute the deployment, but the results will be lost.
You can use --network <network-name> to deploy to a different network.
Hardhat Ignition 🚀
Deploying [ SampleTokenModule ]
Batch #1
Executed SampleTokenModule#SampleToken
[ SampleTokenModule ] successfully deployed 🚀
Deployed Addresses
SampleTokenModule#SampleToken - 0x5FbDB2315678afecb367f032d93F642f64180aa3
コントラクトがコンパイルされていない場合、先頭に以下のような行が入ります。
Compiled 8 Solidity files successfully (evm target: paris).
ローカルノードにデプロイ
2つのターミナルを使います。
一つのターミナルで以下のコマンドを使用してローカルノードを立てます。
npx hardhat node
もう一つのターミナルで以下のコマンドを使用してデプロイします。
--network localhost
でネットワークを指定しています。
npx hardhat --network localhost ignition deploy .\ignition\modules\SampleToken.js
以下のような結果になります。
Hardhat Ignition 🚀
Deploying [ SampleTokenModule ]
Batch #1
Executed SampleTokenModule#SampleToken
[ SampleTokenModule ] successfully deployed 🚀
Deployed Addresses
SampleTokenModule#SampleToken - 0x5FbDB2315678afecb367f032d93F642f64180aa3
デプロイされている状態でもう一度デプロイしてみます。
npx hardhat --network localhost ignition deploy .\ignition\modules\SampleToken.js
以下のような結果になります。
一回デプロイされているので前回デプロイしたものを返します。
[ SampleTokenModule ] Nothing new to deploy based on previous execution stored in .\ignition\deployments\chain-31337
Deployed Addresses
SampleTokenModule#SampleToken - 0x5FbDB2315678afecb367f032d93F642f64180aa3
ignition
フォルダ配下にdeployments
フォルダがありその下にchain-31337
フォルダが出来ていると思います。
このignition/deployments/chain-31337
フォルダにデプロイ時の情報が入っています。
まとめ(Conclusion)
Hardhatでコントラクトの作成とデプロイ用のモジュールを作成をしました。
理解しやすいように、かなりシンプルなつくりにしています。
次回はコントラクトのテストを作成したいと思います。