web3hardhat 框架实战-ERC20
文章目录
- 前言
- 一、环境准备
- 二、项目创建
- 三、ERC20功能实现
- 合约代码,主要编写了ERC20的标准功能(**balanceOf,transfer,approve**)
- 合约测试
- 合约部署
- 总结
前言
随着区块链技术的不断发展,Web3 生态正在逐渐从概念走向落地应用。其中,代币经济作为去中心化应用的核心组成部分,ERC20 代币标准因其简单易用和广泛兼容而成为首选。在本篇博客中,我将基于 Hardhat v3 框架,带你从零实现一个功能完整的 ERC20 代币合约,支持 mint(铸造)、burn(销毁) 以及 transfer(转账) 功能。
通过这个小型 Demo,你不仅可以掌握 ERC20 的核心逻辑,还能熟悉 Hardhat 的智能合约开发、部署和测试流程,为你在 Web3 世界的进一步探索打下坚实基础。无论你是刚入门的 Solidity 开发者,还是想快速搭建代币实验环境的开发者,这篇教程都将为你提供实用的参考。
一、环境准备
本电脑用的是node22的环境
hardhat3的版本
官网地址
https://hardhat.org/docs/getting-started
二、项目创建
1.创建项目文件夹
mkdir hardhat-example
cd hardhat-example
2.初始化项目框架
npx hardhat --init
选择hardhat版本,
(本教程选择的是最新的版本)
选择需要的框架语法
(本教程选择的是最新的Runner and Viem)
下面的都直接回车让他执行完成即可。
完成后我们会得到如上的一个项目架构。
其中主要的包
- contracts:就是编写合约代码的地方
- test:编写测试合约代码的地方
- ignition:部署合约代码编写的地方
hardhat.config.tscontracts
├── Counter.sol
└── Counter.t.soltest
└── Counter.tsignition
└── modules└── Counter.tsscripts
└── send-op-tx.ts
三、ERC20功能实现
合约代码,主要编写了ERC20的标准功能(balanceOf,transfer,approve)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";// ERC20 提供标准ERC20功能 (balanceOf,transfer,approve)/// @title MyToken - Simple ERC20 with owner mint + public burn
contract MyToken is ERC20, Ownable {constructor(string memory name_, string memory symbol_, uint256 initialSupply) ERC20(name_, symbol_) Ownable(msg.sender){// 初试供应铸给部署者_mint(msg.sender, initialSupply);}// @notice 只有合约owner 可以铸造币function mint(address to, uint256 amount) external onlyOwner {_mint(to,amount);}// @notice 持有者可以销毁自己的代币function burn(uint256 amount) external {_burn(msg.sender, amount);}
}
编写完成之后执行如下命令,进行合约的编译
npx hardhat compile
看到这个提示证明合约已经编译成功了
合约测试
import assert from "node:assert/strict";
import { describe, it } from "node:test";
import { network } from "hardhat";describe("MyToken (Hardhat v3 + viem)", async () => {const { viem } = await network.connect();const publicClient = await viem.getPublicClient();const [owner, alice] = await viem.getWalletClients();it("should deploy with initial supply to owner", async () => {const initialSupply = 1000n * 10n ** 18n;const token = await viem.deployContract("MyToken", ["MyToken","MTK",initialSupply,]);const ownerBalance = await token.read.balanceOf([owner.account.address]);assert.equal(ownerBalance, initialSupply);});it("should allow only owner to mint", async () => {const initialSupply = 1000n * 10n ** 18n;const token = await viem.deployContract("MyToken", ["MyToken","MTK",initialSupply,]);// owner 给 alice mintawait token.write.mint([alice.account.address, initialSupply]);const aliceBalance = await token.read.balanceOf([alice.account.address]);assert.equal(aliceBalance, initialSupply);// 非 owner mint -> 应该 revertawait assert.rejects(token.write.mint([alice.account.address, 1n], { account: alice.account }),);});it("should allow holder to burn", async () => {const initialSupply = 1000n * 10n ** 18n;const token = await viem.deployContract("MyToken", ["MyToken","MTK",initialSupply,]);// owner 给 alice mintawait token.write.mint([alice.account.address, initialSupply]);// alice 销毁 10await token.write.burn([10n], { account: alice.account });const balanceAfter = await token.read.balanceOf([alice.account.address]);assert.equal(balanceAfter, initialSupply - 10n);});
});
执行如下命令进行合约的测试
npx hardhat test
看到这个证明合约测试成功
合约部署
import { buildModule } from "@nomicfoundation/hardhat-ignition/modules";export default buildModule("MyTokenModule", (m) => {// 构造函数参数const initialSupply = 1000n * 10n ** 18n;// 部署合约并传入构造参数const token = m.contract("MyToken", ["MyToken", "MTK", initialSupply]);// 部署完成后,给一个固定地址 mint 100 个代币(示范用)// 你可以换成 m.getAccount(1) 来获取测试账户m.call(token, "mint", ["0x0000000000000000000000000000000000000001", 100n * 10n ** 18n]);return { token };
});
执行如下命令进行合约的部署
npx hardhat ignition deploy ignition/modules/MyToken.ts
证明合约部署成功
总结
本文介绍了如何使用Hardhat v3框架从零实现一个功能完整的ERC20代币合约。主要内容包括:1)环境准备,使用Node22和Hardhat3;2)项目创建,通过命令行初始化项目结构;3)ERC20功能实现,编写支持mint、burn和transfer功能的合约代码;4)合约测试,验证代币铸造、销毁和转账功能;5)合约部署,在本地环境部署合约。整个项目展示了ERC20代币的核心逻辑和开发流程,为Web3开发者提供了实用参考。