Hardhatとは
いい感じにSolidityでのDapp開発ができるやつ(語彙力皆無)
事前準備
- Node.js使えるようにしておく
- VSCode使ってる人はのExtensionをインストールしておくと便利っぽいです
環境
- OS: MacOS Monterey 12.0.1
- Node.js: 18.5.0
(チュートりアルにインストールするversion書いてあるのでそれに従ってください)
チュートリアルをやってみる
これをやっていきます
https://hardhat.org/tutorial/creating-a-new-hardhat-project
プロジェクトの設定
作業用ディレクトリを作って移動
mkdir hardhat-tutorial
cd hardhat-tutorial
npm init すると色々聞かれるけどチュートリアルなので全部EnterでOK
最後に Is this OK? と聞かれるのでyes
npm init
...
Is this OK? (yes)
そしたらHardhatをインストールします。ちょっと時間かかるかも。
npm install --save-dev hardhat
npx hardhat と打つといくつか選択肢が出てきます。
Create a TypeScript project
を選択したい気持ちを抑えて指示通りに Create an empty hardhat.config.js
を選択します。
npx hardhat
👷 Welcome to Hardhat v2.10.0 👷
? What do you want to do? …
Create a JavaScript project
Create a TypeScript project
❯ Create an empty hardhat.config.js
Quit
スマートコンラクトの開発に必要なもの全てが揃うと説明されているプラグインをインストールします。
WARNがいっぱい出てきますが無視します。
npm install --save-dev @nomicfoundation/hardhat-toolbox
hardhat.config.jsにrequire("@nomicfoundation/hardhat-toolbox");
を追加します。
require("@nomicfoundation/hardhat-toolbox");
/** @type import('hardhat/config').HardhatUserConfig */
module.exports = {
solidity: "0.8.9",
};
以上でプロジェクトの設定は完了です。
さっそくスマートコントラクトを書いてコンパイルする
contract用のディレクトリ作成し、Token.solを作成します
mkdir contracts
touch Token.sol
書いてみると言ってみたもののコピペです。
説明文のコメントアウト省いて記載しておきます。
//SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.9;
contract Token {
string public name = "My Hardhat Token";
string public symbol = "MHT";
uint256 public totalSupply = 1000000;
address public owner;
mapping(address => uint256) balances;
event Transfer(address indexed _from, address indexed _to, uint256 _value);
constructor() {
balances[msg.sender] = totalSupply;
owner = msg.sender;
}
function transfer(address to, uint256 amount) external {
require(balances[msg.sender] >= amount, "Not enough tokens");
balances[msg.sender] -= amount;
balances[to] += amount;
emit Transfer(msg.sender, to, amount);
}
function balanceOf(address account) external view returns (uint256) {
return balances[account];
}
}
コンパイルして成功するとartifactsというディレクトリが生成されます
npx hardhat compile
Compiled 1 Solidity file successfully
スマートコントラクトが正しく動作するか確認するためにテストコードを書いていきます。
まずはテスト用のディレクトリとファイルを作成します。
テストはOwnerがトークンの最大供給量を保有しているかを確認しています。
mkdir contracts
touch Token.sol
Token.js
const { expect } = require("chai");
const { loadFixture } = require("@nomicfoundation/hardhat-network-helpers");
describe("Token contract", function () {
async function deployTokenFixture() {
const Token = await ethers.getContractFactory("Token");
const [owner, addr1, addr2] = await ethers.getSigners();
const hardhatToken = await Token.deploy();
await hardhatToken.deployed();
return { Token, hardhatToken, owner, addr1, addr2 };
}
describe("Deployment", function () {
it("Should set the right owner", async function () {
const { hardhatToken, owner } = await loadFixture(deployTokenFixture);
expect(await hardhatToken.owner()).to.equal(owner.address);
});
it("Should assign the total supply of tokens to the owner", async function () {
const { hardhatToken, owner } = await loadFixture(deployTokenFixture);
const ownerBalance = await hardhatToken.balanceOf(owner.address);
expect(await hardhatToken.totalSupply()).to.equal(ownerBalance);
});
});
describe("Transactions", function () {
it("Should transfer tokens between accounts", async function () {
const { hardhatToken, owner, addr1, addr2 } = await loadFixture(
deployTokenFixture
);
await expect(
hardhatToken.transfer(addr1.address, 50)
).to.changeTokenBalances(hardhatToken, [owner, addr1], [-50, 50]);
await expect(
hardhatToken.connect(addr1).transfer(addr2.address, 50)
).to.changeTokenBalances(hardhatToken, [addr1, addr2], [-50, 50]);
});
it("should emit Transfer events", async function () {
const { hardhatToken, owner, addr1, addr2 } = await loadFixture(
deployTokenFixture
);
await expect(hardhatToken.transfer(addr1.address, 50))
.to.emit(hardhatToken, "Transfer")
.withArgs(owner.address, addr1.address, 50);
await expect(hardhatToken.connect(addr1).transfer(addr2.address, 50))
.to.emit(hardhatToken, "Transfer")
.withArgs(addr1.address, addr2.address, 50);
});
it("Should fail if sender doesn't have enough tokens", async function () {
const { hardhatToken, owner, addr1 } = await loadFixture(
deployTokenFixture
);
const initialOwnerBalance = await hardhatToken.balanceOf(owner.address);
await expect(
hardhatToken.connect(addr1).transfer(owner.address, 1)
).to.be.revertedWith("Not enough tokens");
expect(await hardhatToken.balanceOf(owner.address)).to.equal(
initialOwnerBalance
);
});
});
});
これでテストを実行すると成功します。
npx hardhat test
Compiled 1 Solidity file successfully
Token contract
Deployment
✔ Should set the right owner (638ms)
✔ Should assign the total supply of tokens to the owner
Transactions
✔ Should transfer tokens between accounts (67ms)
✔ should emit Transfer events
✔ Should fail if sender doesn't have enough tokens
5 passing (775ms)
テストまでできるようになりました。
これで前半は終わりです。