ずっとtruffleを使ってきましたが、主要なサービスのサンプルコードなど、ほぼhardhatな感じなのでHardhatを試してみます。
基本的にこちらの記事を参考にさせていただきました(ありがとうございます)が、私のやりたいことと少し違うところもあるので修正しながら自分で試してみます。
HardhatはEtherrum上のContractを作成するためのフレームワークです。
前提
- macOS上
- nodeインストール済み(18.x)
準備
作業場の作成と必要モジュールインストール
cd
mkdir test-hardhat
cd test-hardhat
npm init -y
npm install --save-dev hardhat
プロジェクトの生成
npx hardhatを実行すると以下のような感じの表示が出ます。
npx hardhat
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.13.0 👷
? What do you want to do? …
❯ Create a JavaScript project
Create a TypeScript project
Create an empty hardhat.config.js
Quit
Create a JavaScript projectを選択し、後はデフォルトかyesで進めます。
TypeScriptも使えるんですね(コントラクト自体をTSとかで書けるわけではありません)。
Contractファイルの作成と記述
contractsの中にファイルを生成。
touch contracts/Hello.sol
最低限の記述をします。
Ethereum上のコントラクトはSolidityで記述します(JSに似てますが違います)。
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.9;
contract Hello {
function greet() public pure returns (string memory) {
return "Hello World";
}
}
// SPDX-License-Identifier: UNLICENSEDの記述がないと怒られます。
Deployファイルの作成(編集)
新しくファイルを作ってもいいのですが、すでにscripts/deploy.jsというファイルがあるのでそれを編集します。
Lock.solをデプロイする記述が書かれているのでその部分は削除します。
const hre = require("hardhat");
async function main() {
const Hello = await hre.ethers.getContractFactory("Hello");
const hello = await Hello.deploy();
await hello.deployed();
console.log(`Deployed to ${hello.address}`);
}
// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});
ローカルノードの実行
テスト実行するnodeを起動させてみます。
truffleだとGanache(CLI)に相当するもの。
npx hardhat node
testnetやmainnetを利用する場合はINFURAやAlchemy等のノードサービスを利用することになります(もちろん自分でnode立ててもいいです)。
Deploy
デプロイは以下のようにネットワークとスクリプトを指定して行うようです。
npx hardhat run --network localhost scripts/deploy.js
出力されるデプロイ先アドレスをメモしておきます(実行に必要なため)。
コントラクトの実行
コンソールを利用して動作確認ができます。
実行には、abiとアドレス情報が必要になります。
- abi: artifacts/contracts/Hello.sol/Hello.json中のapi要素部となります(配列をコピーしておきます)。
- アドレス: 先程出力されたものです。
コンソールの起動
npx hardhat console --network localhost
コンソールでの操作
以下のように対話的に変数を設定しながら最終的にgreet()を実行します。
> const abi = [
{
"inputs": [],
"name": "greet",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "pure",
"type": "function"
}
]
undefined
> const address = "0x5FbDB2315678afecb367f032d93F642f64180aa3"
undefined
> const hello = await ethers.getContractAt(abi, address)
undefined
> await hello.greet()
'Hello World'
おまけ
テストしてみる
テストもかけます。
とりあえずファイル生成。testフォルダ中に生成します。
touch test/Hello.js
とりあえずreturn値をチェックするだけ。
const { expect } = require("chai");
const { ethers } = require("hardhat");
describe("Hello Contract", function(){
it("Shoud return Hello World.",async function(){
const Hello = await ethers.getContractFactory("Hello");
const hello = await Hello.deploy();
await hello.deployed();
expect(await hello.greet()).to.equal("Hello World");
});
});
テストを実行します。
npx hardhat test test/Hello.js
npx hardhat test とすると全てのテストが実行される。
テストネットやメインネットでのデプロイについてはこちらをどうぞ。