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测试的不同适用场景。

相关推荐
alex1005 小时前
【一天一个Web3概念】深入解析Web3空投:类型、参与策略与安全指南
安全·web3·airdrop·空投
木西4 天前
React Native DApp 开发全栈实战·从 0 到 1 系列(完结篇)
react native·web3·智能合约
木西4 天前
React Native DApp 开发全栈实战·从 0 到 1 系列(跨链转账-合约部分)
web3·智能合约·solidity
木西6 天前
React Native DApp 开发全栈实战·从 0 到 1 系列(兑换-前端部分)
react native·web3·solidity
木西9 天前
React Native DApp 开发全栈实战·从 0 到 1 系列(兑换-合约部分)
web3·智能合约·solidity
全干engineer10 天前
区块链web3项目实战-Truffle petshop
web3·区块链
Armonia生态10 天前
Armonia Mall超级数字生态WEB3商城的引领者
web3·armonia-mall
alex10011 天前
【一天一个Web3概念】Web3.0赛道分析:新一轮技术浪潮下的机遇与挑战
web3
Web3_Daisy12 天前
克隆代币 + 捆绑开盘:多链环境下的低成本发币玩法
人工智能·web3·区块链·比特币