はじめに(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でコントラクトの作成とデプロイ用のモジュールを作成をしました。
理解しやすいように、かなりシンプルなつくりにしています。
次回はコントラクトのテストを作成したいと思います。