只需一台电脑、一小时、一杯咖啡,你就能把一份全新代币的合约送到以太坊主网。
为什么要 DIY 一份 ERC20
无论是为社区发放治理通证,还是做项目众筹,ERC20 都是「数字资产原型机」。它标准化、可扩展、兼容主流钱包和交易所,让你专注于商业逻辑而非底层移植问题。
在本文中,我们将从写作能力要求最低的代码模板出发,边讲边练,实战完成:
- 核心关键词:ERC20 代币、智能合约开发、ICO(首次代币发行)、Gas 优化、Hardhat 部署、Solidity 安全、代币经济学、合约升级、Goerli 测试网
基础回顾:ERC20 做了什么
ERC20 只规定6 个必要函数 + 2 个事件。理解它们,你就能读懂 90% 代币合约:
totalSupply()— 当前发行总量balanceOf(address)— 某地址余额transfer(to, amount)— 普通转账allowance(owner, spender)— 查询授权余额approve(spender, amount)— 授权第三方transferFrom(from, to, amount)— 受授权转账
事件:Transfer、Approval 负责给区块链浏览器发送提示,让钱包立即索引变动。
任何额外功能——增发、销毁、暂停、快照——都是对以上接口的扩展,不会破坏兼容性。
五步速成:ERC20 代币合约
1. 环境初始化
npm init -y
npm install --save-dev hardhat @nomicfoundation/hardhat-toolbox
npx hardhat init选择「Create a JavaScript project」,一路 Enter 即可。生成的目录包含 contracts、scripts、test,后续全在这里写。
2. 引入 OpenZeppelin 库
npm install @openzeppelin/contractsSolidity 世界人人都在用 OpenZeppelin,它提供经审计、Gas 友好且社区验证的函数库,可避免重复造轮子。
3. 撰写代币合约
contracts/MyToken.sol:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Capped.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
contract MyToken is ERC20Capped, AccessControl {
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
uint8 private _decimals;
constructor(
string memory name,
string memory symbol,
uint8 decimals_,
uint256 cap_
) ERC20(name, symbol) ERC20Capped(cap_) {
_decimals = decimals_;
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
_grantRole(MINTER_ROLE, msg.sender);
}
function decimals() public view override returns (uint8) {
return _decimals;
}
function mint(address to, uint256 amount) public onlyRole(MINTER_ROLE) {
_mint(to, amount);
}
}亮点拆解
- ERC20Capped:一键加硬顶,避免无上限通胀。
- AccessControl:角色分级,
MINTER_ROLE、ADMIN_ROLE清晰可鉴。 - 自定义小数位:别小看
decimals(),决定 1 个币是 1.000 还是 1.000000。
4. 配置 Hardhat 网络
hardhat.config.js:
require("@nomicfoundation/hardhat-toolbox");
module.exports = {
solidity: "0.8.20",
networks: {
goerli: {
url: process.env.ALCHEMY_GOERLI_URL,
accounts: [process.env.PRIVATE_KEY],
},
},
};将 Alchemy 或 Infura 的 Goerli RPC 地址粘进 .env;本地测试可用 npx hardhat node 起一条 Ganache 私链。
5. Gas 优化小招
- 打包编译时开启
optimizer,默认runs: 200足以。 - 多用
immutable与constant让变量常驻字节码而非存储。 - 对每次迭代中的中间结果,用
memory而非storage临时存放。
编译、测试、部署 ➜ 一条龙
本地测试
创建 test/MyToken.js:
const { expect } = require("chai");
describe("MyToken", function () {
it("Should mint with correct cap", async function () {
const [owner] = await ethers.getSigners();
const Token = await ethers.getContractFactory("MyToken");
const token = await Token.deploy("MyToken", "MT", 18, ethers.parseEther("1000000"));
await token.waitForDeployment();
await token.mint(owner.address, ethers.parseEther("100"));
expect(await token.totalSupply()).to.equal(ethers.parseEther("100"));
});
});运行:
npx hardhat test部署脚本
scripts/deploy.js:
async function main() {
const [deployer] = await ethers.getSigners();
console.log("Deployer:", deployer.address);
const Token = await ethers.getContractFactory("MyToken");
const token = await Token.deploy(
"Tutorial Token", "TUT", 18, ethers.parseEther("1000000")
);
await token.waitForDeployment();
console.log("Token deployed to:", await token.getAddress());
}
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});Goerli 部署:
npx hardhat run scripts/deploy.js --network goerli生产环境验证
合约地址生成后,立刻到 Goerli Etherscan 上
- 开源码(Flatten 合约 + 填构造函数 ABI)
- 烧掉 1 TUT 测试 burn 逻辑
- 验证角色授权,确认 MINTER_ROLE 仅在你手中
ICO 上市的全流程清单
一旦合约稳定,下一关就是发币与吸引社区。
| 步骤 | 关键动作 |
|---|---|
| 1. 品牌设计 | 统一视觉识别(Logo、网址、社交头像) |
| 2. 白皮书 | 5000–8000 字,阐明代币经济学与技术路标 |
| 3. 法律合规 | 如果面向美国、加拿大用户,需 Reg D 申请或限制销售 |
| 4. KYC 平台 | 选 CoinList、Tokensoft 等一键 KYC/AML 通道 |
| 5. 逐步解锁 | 投资人份额分批释放,遏制即刻砸盘 |
👉 查看顶级 IDO 筹备时间线,比竞品早 2 周起跑不是梦
常见问题 FAQ
Q1:ERC20、ERC777、ERC1155 到底怎么选?
A:
- ERC20:生态系统最健全,钱包、CEX、DeFi 全支持。
- ERC777:向下兼容 ERC20,额外带「钩子」功能,能让接收方自动回调,但对合约质量要求更高。
- ERC1155:单合约里同时发行多种「同质化 + 非同质化」资产,适用于游戏 NFT。
绝大多数众筹场景仍是 ERC20。
Q2:Gas 仍旧太贵,有没有 Layer2 可以部署?
A:Optimism、Arbitrum 已原生支持 OZ OpenZeppelin 合约。部署时仅需把 networks 指向对应 RPC,手续费可降 90% 以上,钱包地址也与主网一致。
Q3:能不能让代币「一键升级」?
A:使用「代理合约 + 逻辑实现」的 UUPS 或 Transparent Proxy 模式。OZ 已封装 ERC1967Proxy,配合 Hardhat-Upgrades 插件一行命令搞定。注意:代理仅用于修复漏洞和新增功能,不能滥用做无上限增发。
Q4:为什么有的代币地址是小写,有的是大小写混合?
A:EIP-55 引入的校验和格式,既美观又防手抖。Truffle、Hardhat 会自动输出 checksum 地址,无需手动操作。
Q5:如何防止「蜜罐」陷阱?
A:
- 用 Slither、MythX 做静态分析,排除隐藏后门。
- 开源 + 形式化验证,社群交叉审计。
- 禁止 owner 权限过大,例如确保黑名单、暂停、增发都由 DAO 投票。
Q6:代币已上线,怎么分发空投?
A:可写 Merkle-Distributor 合约:提前在链下计算含地址 + 数量 的 Merkle 根,合约上链后用户自己申领,Gas 可省 7–10 倍。Avalanche、Optimism 空投均用该方案。
结语 & 下一步行动
当你把本流程跑通后,真正难的就不再是写代码,而是定义价值捕获与社区共识建设。
接下来:
- 设计锁仓与投票模块 → 打开 DeFi 治理
- 接入 Uniswap V3 流动性 → 实现 即刻交易
- 开启质押挖矿 → 新增 收益场景
区块链开发永远没有终点,但用 ERC20 标准迈出第一步,你已领先 99% 的观望者。祝你挖矿愉快、发币顺利!