hardhat-toolbox-mocha-ethers について
コア `hardhat` スキルを補完し、ethers、Mocha、chai を使ったスマートコントラクトのテスト方法を案内するスキルです。Hardhat プロジェクトの開発者向けです。
主な機能
- 01ネットワーク接続を使った Mocha テストの設定
- 02ethers の署名者とコントラクト操作
- 03フィクスチャを使ったコントラクトのデプロイ
- 04アドレスの偽装とアカウントへの資金追加
- 05トランザクション、イベント、残高変化の検証
活用シーン
- 01コントラクトの読み取りと状態変更をテスト
- 02テスト間でデプロイ設定を再利用
- 03リバート動作と発生イベントを確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ nomicfoundation/ hardhat-skills --skill hardhat-toolbox-mocha-ethersインストール後、Claude Code で/hardhat-toolbox-mocha-ethersを入力して読み込まれたか確認します。
詳細
Hardhat ツールボックス:ethers + Mocha
このスキルは、コアの hardhat スキルを基盤としています。テストの構成、network.create() の形式、networkHelpers、フィクスチャ、型チェックのワークフローについては、まずそちらを読み込んでください。以下はすべて、network.create() が返す接続を基点としています。
このスタックでは Mocha(グローバルな describe / it)のもとでテストを実行し、アサーションには chai を使用します。Mocha は describe のコールバックを await しないため、ファイルの先頭でトップレベルの await を使って接続をセットアップします。
import { expect } from "chai";
import { network } from "hardhat";
const { ethers, networkHelpers } = await network.create();
describe("Counter", function () {
// ...
});
ファイルごとに接続を1つ作成するのが一般的です。テスト間の状態の分離には、新しい接続を describe ごとに作成するのではなく、loadFixture(hardhat スキルを参照)を使用します。
ethers:署名者とコントラクトの操作
コントラクトの型は、コンパイル済み ABI から TypeChain によって生成されます。型チェックを行う前に hardhat build を実行し、最新のコントラクトが型に反映されるようにしてください。
// Provider (read-only chain data)
const blockNumber = await ethers.provider.getBlockNumber();
const balance = await ethers.provider.getBalance("0xabc...");
// Signers (for sending transactions)
const [owner, alice, bob] = await ethers.getSigners(); // default funded accounts
// Utilities
const oneEth = ethers.parseEther("1.0");
// Deploy a contract, returns a fully typed instance.
// Pass constructor args as the second argument, and (optionally) a signer
// other than the default as the third.
const counter = await ethers.deployContract("Counter");
const counterWithArgs = await ethers.deployContract("Counter", [42n]);
const counterFromAlice = await ethers.deployContract("Counter", [], alice);
// Read state and call functions. Args and return types are type-checked
// against the ABI at compile time; passing wrong types or wrong argument
// counts is a TypeScript error.
const value = await counter.x();
await counter.inc();
await counter.incBy(3n);
// Send from a different signer
await counter.connect(alice).inc();
// Send ETH along with a payable call
await counter.deposit({ value: oneEth });
// Attach to an already-deployed contract
const existing = await ethers.getContractAt("Counter", "0xabc...");
loadFixture のセットアップ関数内では(周辺のパターンについては hardhat スキルを参照)、ethers.deployContract が標準的なデプロイ手順です。
async function deployCounterFixture() {
const counter = await ethers.deployContract("Counter");
return { counter };
}
const { counter } = await networkHelpers.loadFixture(deployCounterFixture);
デフォルトで資金が割り当てられているアカウント以外の任意のアドレスからトランザクションを送信するには、ガス代を入金し、ethers.getImpersonatedSigner でなりすまし用の署名者を取得します。なりすましは内部で処理されるため、別途 networkHelpers.impersonateAccount を呼び出す必要はありません。
const addr = "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
await networkHelpers.setBalance(addr, ethers.parseEther("1.0"));
const signer = await ethers.getImpersonatedSigner(addr);
await counter.connect(signer).inc();
Chai マッチャー:Ethereum 固有のアサーション
hardhat-ethers-chai-matchers プラグインは、トランザクション、イベント、残高の変化を検証するマッチャーで chai の expect を拡張します。expect には トランザクションの Promise(書き込み呼び出しの結果で、await していないもの)を渡します。
import { expect } from "chai";
// Reverts
await expect(counter.connect(banned).inc()).to.revert(ethers);
await expect(counter.connect(banned).inc()).to.be.revertedWith(
"only the owner can increment the counter",
);
await expect(counter.connect(banned).inc()).to.be.revertedWithCustomError(
counter,
"Unauthorized",
);
await expect(counter.connect(banned).inc())
.to.be.revertedWithCustomError(counter, "Unauthorized")
.withArgs(banned.address);
// Events
await expect(counter.inc()).to.emit(counter, "Increment");
await expect(counter.inc()).to.emit(counter, "Increment").withArgs(1n);
// ETH balance changes (positive = received, negative = spent, before gas)
await expect(game.claim()).to.changeEtherBalance(ethers, winner, PRIZE);
await expect(game.claim()).to.changeEtherBalances(
ethers,
[winner, loser],
[PRIZE, -STAKE],
);
通常のアサーション(等価性、配列、型)には、Ethereum のマッチャーを使わず、chai の expect を直接使用してください。