Hardhat 3 示例项目实战:使用 Mocha 与 Ethers 编写与部署测试(02-mocha-ethers 模板详解)
Hardhat 3 示例项目实战使用 Mocha 与 Ethers 编写与部署测试02-mocha-ethers 模板详解【免费下载链接】hardhatHardhat is a development environment to compile, deploy, test, and debug your Ethereum software.项目地址: https://gitcode.com/GitHub_Trending/ha/hardhat导读本文以 Hardhat 仓库中官方提供的02-mocha-ethers项目模板位于 packages/hardhat/templates/02-mocha-ethers为蓝本完整讲解如何在一个 Hardhat 3 项目中同时使用 Foundry 兼容的 Solidity 单元测试与基于 Mocha Ethers.js 的 TypeScript 集成测试并通过 Ignition 模块完成本地链与 Sepolia 的合约部署。读完本文你将掌握npx hardhat test的分组运行方式、hardhat.config.ts中多网络与配置变量Configuration Variable的写法、Ignition 部署命令、hardhat-keystore管理私钥的流程以及如何在本地方真 OP mainnet 网络下发送交易。项目概览一个开箱即用的 Hardhat 3 Mocha Ethers 工程该模板是一个完整的 TypeScript Hardhat 工程用于演示 Hardhat 3 下「Mocha 驱动测试、Ethers.js 交互链上」的标准开发方式。根据模板自身 README 的说明它包含四类关键内容一份简洁的 Hardhat 配置文件hardhat.config.tsFoundry 兼容的 Solidity 单元测试以.t.sol结尾继承forge-std的Test基类使用 Mocha 与 Ethers.js 编写的 TypeScript 集成测试连接不同类型网络的示例包括在本地模拟 OP mainnetOptimism链。从模板目录的实体文件看工程由contracts/合约源码与 Solidity 测试、test/TypeScript 集成测试、ignition/modules/Ignition 部署模块、scripts/独立脚本以及hardhat.config.ts、package.json、tsconfig.json组成其布局在 AGENTS.md 中有明确说明contracts/ Solidity 源码文件 (*.sol) 与单元测试 (*.t.sol) test/ TypeScript 集成测试与 Solidity 单元测试 ignition/ Hardhat Ignition 部署模块 scripts/ 通过 hardhat run 运行的独立脚本 hardhat.config.ts依赖方面模板 package.json 以workspace:前缀声明了hardhat、nomicfoundation/hardhat-toolbox-mocha-ethers、nomicfoundation/hardhat-ethers、nomicfoundation/hardhat-ignition等依赖并直接依赖mocha、chai、ethers、typescript与forge-std。其中forge-std以 Git 引用形式引入这是 Solidity 测试能够使用vm.expectRevert()等 cheatcode 的基础。核心配置多网络模拟与配置变量模板 hardhat.config.ts 是理解整份工程的关键它示范了 Hardhat 3 的声明式配置风格import hardhatToolboxMochaEthersPlugin from nomicfoundation/hardhat-toolbox-mocha-ethers; import { configVariable, defineConfig } from hardhat/config; export default defineConfig({ plugins: [hardhatToolboxMochaEthersPlugin], solidity: { profiles: { default: { version: 0.8.34, }, production: { version: 0.8.34, settings: { optimizer: { enabled: true, runs: 200, }, }, }, }, }, networks: { hardhatMainnet: { type: edr-simulated, chainType: l1, }, hardhatOp: { type: edr-simulated, chainType: op, }, sepolia: { type: http, chainType: l1, url: configVariable(SEPOLIA_RPC_URL), accounts: [configVariable(SEPOLIA_PRIVATE_KEY)], }, }, });配置中值得注意的几点插件聚合nomicfoundation/hardhat-toolbox-mocha-ethers是一个聚合插件。其源码见 src/index.ts通过definePlugin声明了对hardhat-ethers、hardhat-ethers-chai-matchers、hardhat-ignition-ethers、hardhat-keystore、hardhat-mocha、hardhat-network-helpers、hardhat-typechain、hardhat-verify这一组依赖插件的自动加载因此只需在配置中注册它一个插件即可获得全部能力。编译 profiledefault与production两个 profile 都锁定 Solidity0.8.34其中production额外开启优化器runs: 200用于生产构建场景。本地模拟网络hardhatMainnet与hardhatOp均使用type: edr-simulated前者chainType为l1后者为op。这意味着无需真实节点即可在 EDR 模拟器中分别体验普通 L1 与 OP 链的行为差异。外部网络sepolia使用type: http其 RPC 地址与账户私钥均通过configVariable(...)从配置变量中读取避免把敏感信息硬编码进配置文件。运行测试全量、Solidity 与 Mocha 三种方式模板支持两种测试框架并存并且可以通过子命令单独运行。执行以下命令可运行全部测试npx hardhat test也可以按需只运行某一类测试npx hardhat test solidity npx hardhat test mochatest solidity只会执行contracts/下 Foundry 兼容的 Solidity 单元测试test mocha只执行test/目录下由 Mocha 驱动的 TypeScript 测试。这种按框架分组的机制使得「快速跑一遍纯 Solidity 逻辑」或「只跑链上集成测试」都能在一条命令内完成是 Hardhat 3 相比 v2 时代「测试即全量」体验的重要改进。Solidity 单元测试与 Foundry 完全兼容模板在 contracts/Counter.t.sol 中示范了 Solidity 单元测试的写法其注释明确指出「Solidity tests are compatible with foundry, so they use the same syntax and offer the same functionality」// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.34; import {Counter} from ./Counter.sol; import {Test} from forge-std/Test.sol; contract CounterTest is Test { Counter counter; function setUp() public { counter new Counter(); } function test_InitialValue() public view { require(counter.x() 0, Initial value should be 0); } function testFuzz_Inc(uint8 x) public { for (uint8 i 0; i x; i) { counter.inc(); } require(counter.x() x, Value after calling inc x times should be x); } function test_IncByZero() public { vm.expectRevert(); counter.incBy(0); } }这份测试覆盖了三种典型形态普通状态测试test_InitialValue、带参数自动模糊测试fuzz的testFuzz_Inc(uint8 x)以及借助vm.expectRevert()cheatcode 断言回滚的test_IncByZero。被测试合约 contracts/Counter.sol 维护一个uint public x计数器提供inc()与incBy(uint by)两个方法并在每次自增时抛出Increment事件incBy通过require(by 0, ...)拒绝非正增量。Mocha Ethers 集成测试顶层 await 建立网络连接TypeScript 侧测试位于 test/Counter.ts其关键结构是由于 Mocha 不会 awaitdescribe回调因此在文件顶部使用顶层await一次性建立网络连接import { expect } from chai; import { network } from hardhat; const { ethers } await network.create(); describe(Counter, function () { it(Should emit the Increment event when calling the inc() function, async function () { const counter await ethers.deployContract(Counter); await expect(counter.inc()).to.emit(counter, Increment).withArgs(1n); }); it(The sum of the Increment events should match the current value, async function () { const counter await ethers.deployContract(Counter); const deploymentBlockNumber await ethers.provider.getBlockNumber(); // run a series of increments for (let i 1; i 10; i) { await counter.incBy(i); } const events await counter.queryFilter( counter.filters.Increment(), deploymentBlockNumber, latest, ); // check that the aggregated events match the current value let total 0n; for (const event of events) { total event.args.by; } expect(await counter.x()).to.equal(total); }); });第一个用例展示了ethers.deployContract(Counter)的一键部署与 chai 事件断言.to.emit(...).withArgs(1n)第二个用例则通过queryFilter从部署区块拉取全部Increment事件累加其by参数并与链上状态x比对验证「事件总和等于计数器现值」。两例合起来演示了nomicfoundation/hardhat-ethers-chai-matchers提供的事件断言能力与 Ethers.js 的日志查询 API。相关技能的详细说明可参考 packages/hardhat/skills/hardhat-toolbox-mocha-ethers/SKILL.md其中还涵盖了.to.be.revertedWith*、.to.changeEtherBalance(s)等更多 matcher以及ethers.getImpersonatedSigner、loadFixture等进阶用法。用 Ignition 部署从本地模拟到 Sepolia模板内置了一个 Ignition 部署模块 ignition/modules/Counter.ts通过buildModule定义部署流程import { buildModule } from nomicfoundation/hardhat-ignition/modules; export default buildModule(CounterModule, (m) { const counter m.contract(Counter); m.call(counter, incBy, [5n]); return { counter }; });该模块不仅部署Counter合约还紧随其后调用incBy(5n)展示了 Ignition「声明式编排部署后调用」的能力。部署到本地模拟链不指定网络时Ignition 会使用默认的本地模拟链一条命令即可完成npx hardhat ignition deploy ignition/modules/Counter.ts部署到 Sepolia要部署到 Sepolia需要准备两样东西一个有余额的账户私钥以及对应的 RPC 地址。模板的做法是把它们作为配置变量Configuration Variable管理——配置文件中的configVariable(SEPOLIA_PRIVATE_KEY)与configVariable(SEPOLIA_RPC_URL)正是读取这些变量的入口。配置变量可以通过hardhat-keystore插件设置也可以直接设置环境变量。使用hardhat-keystore设置私钥的方式npx hardhat keystore set SEPOLIA_PRIVATE_KEY该命令会提示输入密钥并将其安全保存。设置完成后带上--network sepolia参数执行部署npx hardhat ignition deploy --network sepolia ignition/modules/Counter.ts需要强调的是Sepolia 是真实测试网发送交易需要账户内有足够的测试代币faucet 领取来支付 gasSEPOLIA_RPC_URL对应的 RPC 端点也需要你自行从公共 RPC 服务商处获取。二者均通过配置变量注入确保密钥不出现在仓库与配置文件中。在本地模拟 OP mainnethardhatOp网络实战模板还特别展示了如何连接不同类型的网络其中最有特色的是本地模拟 OP mainnet。配置中hardhatOp网络使用type: edr-simulated搭配chainType: op让你在本机就能体验 Optimism 链上的交易行为。对应的脚本位于 scripts/send-op-tx.tsimport { network } from hardhat; const { ethers } await network.create({ network: hardhatOp, chainType: op, }); console.log(Sending transaction using the OP chain type); const [sender] await ethers.getSigners(); console.log(Sending 1 wei from, sender.address, to itself); console.log(Sending L2 transaction); const tx await sender.sendTransaction({ to: sender.address, value: 1n, }); await tx.wait(); console.log(Transaction sent successfully);脚本通过network.create({ network: hardhatOp, chainType: op })显式选择 OP 类型的本地模拟网络然后以默认签名者向自己发送一笔 1 wei 的 L2 交易并等待确认。在 EDR 模拟的 OP 链上这笔交易会按 L2 语义处理无需真实的基础设施即可验证 L2 交易路径。运行该脚本的方式为npx hardhat run scripts/send-op-tx.ts工程配套文件速览除上述核心文件外模板还包含几份值得留意的配套文件tsconfig.json以es2023为目标、node20模块体系编译types中包含node与mocha并开启verbatimModuleSyntaxgitignore模板中以该名字命名初始化时会复制为.gitignore默认忽略node_modules、dist、artifacts、cache、Typechain 输出目录types、环境文件.env*、覆盖率目录coverage及 gas 快照文件等在 templates/README.md 中说明了这一命名约定npm 打包时会忽略.gitignore故模板使用gitignore文件名规避package.jsondevDependencies与peerDependencies分别列出运行时与工具链依赖初始化时workspace:前缀会被剥离并解析为具体版本。小结一份可直接照搬的 Hardhat 3 开发样板02-mocha-ethers模板把 Hardhat 3 时代最常见的开发诉求浓缩在一个工程里声明式多网络配置、配置变量管理密钥、Foundry 与 Mocha 双轨测试、Ignition 声明式部署、本地 OP 链模拟。无论你是刚接触 Hardhat 3还是想为团队沉淀一套标准的合约开发脚手架都可以直接以 packages/hardhat/templates/02-mocha-ethers 为蓝本将hardhat test、hardhat ignition deploy --network sepolia、hardhat keystore set等命令组合进日常工作流。【免费下载链接】hardhatHardhat is a development environment to compile, deploy, test, and debug your Ethereum software.项目地址: https://gitcode.com/GitHub_Trending/ha/hardhat创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考