web3实战项目 - hardhat框架

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录


前言

我把 从零到可运行的 ERC-721 收藏品 + 简单固定价市场(marketplace) 的完整「一步一步」实操指南(含可复制的命令与示例代码)。适合初学者用 Hardhat + OpenZeppelin + ethers.js 在 Sepolia 测试网 上练手(因为 Goerli 已逐步退役,建议用 Sepolia)。


提示:以下是本篇文章正文内容,下面案例可供参考

一、目标?

用 OpenZeppelin 实现一个简单的 ERC-721 收藏品合约(可 mint 带 metadata 的 NFT),再做一个简单的固定价 marketplace 合约(list / buy / cancel / withdraw),并演示如何在 Sepolia 上部署和用前端或脚本交互。

步骤总览

  1. 环境准备(Node、Hardhat、MetaMask、RPC),node建议最新版本22的版本
  2. 新建 Hardhat 项目并安装依赖
  3. 写 ERC-721 合约(MyCollectible)
  4. 写简单 Marketplace 合约(NftMarketplace,使用 pull payments &
    ReentrancyGuard)
  5. 编写部署脚本并在本地 / Sepolia 部署
  6. 测试:mint → approve → list → buy → withdraw(示例脚本 + 前端调用)
  7. 注意事项(metadata 存储、审计、生产上要改的点)

环境准备(本地)

  • 安装 Node.js(建议使用 LTS,≥18)和 npm/yarn。
  • 安装 MetaMask 浏览器扩展并创建钱包(切换到 Sepolia 测试网并申请测试 ETH)。(Sepolia 是当前推荐的测试网。)
  • 注册并配置一个 RPC 提供商(Alchemy / Infura / QuickNode),拿到 Sepolia RPC URL(放到
    .env)。

初始化项目 & 依赖

执行如下命令

bash 复制代码
mkdir nft-marketplace
cd nft-marketplace
npm init -y
npm install --save-dev hardhat
npx hardhat --init

出现如下界面说明安装成功

我们在选择的时候会遇到一个选项

bash 复制代码
? What type of project would you like to initialize?
❯ A TypeScript Hardhat project using Node Test Runner and Viem
  A TypeScript Hardhat project using Mocha and Ethers.js
  1. Node Test Runner + Viem
    ·· Node.js 新的测试运行器(而不是 Mocha)。
    ··交互库是 Viem(替代 Ethers.js,API 不同,学习成本更高)。
  2. Mocha + Ethers.js
    ··使用经典的 Mocha 测试框架。
    --使用 Ethers.js,几乎所有教程(包括我给你写的脚本)都是基于 Ethers.js。
    建议选择:Node Test Runner + Viem
    生成完成后可以看到
bash 复制代码
contracts/
scripts/
test/
hardhat.config.ts

二、编写智能合约

使用 Hardhat 编写智能合约非常简单,只需在contracts目录中编写一个 Solidity 文件即可。例如,您的contracts/Counter.sol代码如下所示:

bash 复制代码
pragma solidity ^0.8.28;

contract Counter {
  uint public x;

  event Increment(uint by);

  function inc() public {
    x++;
    emit Increment(1);
  }

  function incBy(uint by) public {
    require(by > 0, "incBy: increment should be positive");
    x += by;
    emit Increment(by);
  }
}

Hardhat 会自动检测它,并根据其pragma声明和你的 Hardhat 配置,使用正确版本的 Solidity 进行编译。你只需运行以下命令:

bash 复制代码
npx hardhat build

测试你的合约

测试是任何以太坊项目的关键部分。Hardhat 允许您使用Solidity和TypeScript编写测试,让您可以灵活地根据具体情况选择合适的工具。

安全帽测试针对本地内存区块链运行,这比使用真实网络快得多,并且不需要您花费 ETH 或获取测试网络代币。

Solidity 测试

Hardhat 3 完全支持编写 Solidity 测试。示例项目包含一个 Solidity 测试文件,位于contracts/Counter.t.sol:

bash 复制代码
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);
  }
}

执行下面的命令可以测试所有的合约

bash 复制代码
npx hardhat test

如果您只想运行 Solidity 测试,则可以使用以下命令:

bash 复制代码
npx hardhat test solidity

当您运行此命令时,Hardhat 将:

  1. 编译您的合同和测试。
  2. 收集所有测试文件。包括目录.t.sol中的所有文件contracts/以及目录.sol中的所有文件test/。
  3. 部署这些文件中定义的每个测试合同。
  4. 调用每个以 开头的函数test。如果任何调用被撤销,则相应的测试将被标记为失败。

在上面的例子中:

  • test_InitialValue是单元测试:它们不带参数,并且每次测试执行时运行一次test_IncByZero。
  • testFuzz_Inc是一个模糊测试:由于它接受一个参数,Hardhat
    会使用随机输入多次运行它。如果任何一次运行失败,则模糊测试失败,并打印失败的输入。
  • 如果您的任何测试失败,Hardhat 将提供详细的Solidity
    堆栈跟踪,以帮助您了解原因。要查看它们的实际效果,请首先注释掉vm.expectRevert();以下行test_IncByZero:
bash 复制代码
function test_IncByZero() public {
    // vm.expectRevert();
  counter.incBy(0);
}
bash 复制代码
Failure (1): test_IncByZero()
Reason: revert: incBy: increment should be positive
  at Counter.incBy (contracts/Counter.sol:15)
  at CounterTest.test_IncByZero (contracts/Counter.t.sol:30)

TypeScript 测试

Solidity 测试非常适合快速、集中的单元测试,但在某些情况下却存在不足:

  • 复杂的测试逻辑,其中像 TypeScript 这样的通用语言比 Solidity 更具表现力和人体工程学。
  • 需要真实区块链行为的测试 ,例如区块推进或 Gas
    成本计算。虽然作弊码可以在一定程度上模拟这些行为,但过度模拟难以维护,并且可能导致不准确的假设。
  • 端到端场景,您希望测试您的合同在生产中的行为,涉及多个交易、客户端和用户交互。

为了支持这些用例,Hardhat 允许您使用 TypeScript(或 JavaScript)编写测试,使用

Node.js 测试运行器

或其他框架,例如

摩卡

这些测试在真实的 Node.js 环境中运行,并通过 JSON-RPC 与您的合约进行交互,使其更能代表实际使用情况。

示例项目附带一个 TypeScript 测试文件,位于test/Counter.ts,其中包含以下测试:

bash 复制代码
it("The sum of the Increment events should match the current value", async function () {
  const counter = await viem.deployContract("Counter");

  // run a series of increments
  for (let i = 1n; i <= 10n; i++) {
    await counter.write.incBy([i]);
  }

  const events = await publicClient.getContractEvents({
    address: counter.address,
    abi: counter.abi,
    eventName: "Increment",
    fromBlock: 0n,
    strict: true,
  });

  // check that the aggregated events match the current value
  let total = 0n;
  for (const event of events) {
    total += event.args.by;
  }

  assert.equal(total, await counter.read.x());
});

该测试部署Counter合约,incBy多次调用(每次在单独的交易中),收集所有发出的Increment事件,并验证它们的总和是否与合约的最终价值相匹配。

用 Solidity 编写同样的测试也是可行的,但不太方便,而且测试会在不同的上下文中执行------更接近于单个交易多次调用合约,而不是不同用户随时间推移与其交互。这使得 TypeScript 更适合那些依赖于实际交易流程或区块链行为的场景。

要运行 TypeScript 测试,请使用以下test nodejs任务:

bash 复制代码
npx hardhat test nodejs

编写脚本与网络交互

Hardhat 中的脚本只是一个 TypeScript 或 JavaScript 文件,可以访问您的合约、配置以及 Hardhat 提供的任何其他功能。您可以使用它们来运行自定义逻辑或自动化工作流程。

按照惯例,脚本位于scripts/目录中。您可以随意命名它们,并使用.ts或.js扩展名。

示例项目包含两个脚本。其中一个脚本scripts/send-op-tx.ts展示了如何模拟本地类似 Optimism 的网络并在其上发送交易。

要运行脚本,您可以使用以下run任务:

bash 复制代码
npx hardhat run scripts/send-op-tx.ts

部署合约

示例项目附带我们的官方部署解决方案:Hardhat Ignition,一个用于部署智能合约的声明式系统。

使用 Hardhat Ignition,您可以定义要部署的智能合约实例以及要对其执行的任何操作。这些定义被分组到 Ignition 模块中,然后以最高效的方式进行分析和执行。这包括并行发送独立交易、从错误中恢复以及恢复中断的部署。

Ignition 模块位于ignition/modules/目录中。这是示例模块ignition/modules/Counter.ts:

bash 复制代码
import { buildModule } from "@nomicfoundation/hardhat-ignition/modules";

export default buildModule("CounterModule", (m) => {
  const counter = m.contract("Counter");

  m.call(counter, "incBy", [5n]);

  return { counter };
});
bash 复制代码
npx hardhat ignition deploy ignition/modules/Counter.ts

总结

本文介绍了如何从零开始开发一个ERC-721 NFT收藏品合约和简单的固定价市场(marketplace),并部署到Sepolia测试网。主要内容包括:环境准备(Node.js、Hardhat、MetaMask)、项目初始化、编写ERC-721合约和Marketplace合约、部署流程、测试方法(Solidity和TypeScript测试)以及交互演示。文章提供了详细的步骤指南和代码示例,适合初学者学习使用Hardhat、OpenZeppelin和ethers.js进行区块链开发。特别强调了测试的重要性,并比较了Solidity测试和TypeScript测试的不同适用场景。

相关推荐
leijiwen13 小时前
web3品牌RWA资产自主发行设计方案
web3·区块链
元宇宙时间13 小时前
Nine.fun:连接现实娱乐与Web3经济的全新生态
人工智能·金融·web3·区块链
只会写Bug的程序员13 小时前
【职业方向】2026小目标,从web开发转型web3开发【一】
前端·web3
野老杂谈16 小时前
【Solidity 从入门到精通】第3章 Solidity 基础语法详解
web3·solidity
leijiwen16 小时前
S11e Protocol 数字身份体系架构白皮书
架构·web3·区块链·品牌·rwa
野老杂谈16 小时前
【Solidity 从入门到精通】第2章 Solidity 语言概览与环境搭建
web3·区块链·智能合约·solidity·remix ide
MicroTech20251 天前
微算法科技(NASDAQ MLGO):DPoS驱动区块链治理与DAO机制融合,共筑Web3.0坚实基石
科技·web3·区块链
野老杂谈2 天前
【Solidity 从入门到精通】前言
web3·智能合约·solidity·以太坊·dapp
Web3_Daisy2 天前
消除链上气泡图:为什么换仓正在成为新的链上生存策略?
大数据·人工智能·安全·web3·区块链