以太坊作为全球领先的智能合约平台,不仅支撑着去中心化金融(DeFi)、NFT等生态的繁荣,也使得创建自定义代币变得前所未有的简单,ERC20是以太坊上最著名、应用最广泛的代币标准,它定义了一套规则和接口,确保了不同代币之间的互操作性和兼容性,本文将带你从零开始,详细解析以太坊ERC20代币的开发过程,包括核心概念、开发环境搭建、智能合约编写、测试、部署以及后续管理。
什么是ERC20代币?
ERC20(Ethereum Request for Comments 20)不是一个协议或法律框架,而是一个技术标准,由以太坊社区提出并在2017年正式标准化,它规定了以太坊上代币合约必须实现的一套基本接口和事件,使得代币能够在以太坊生态中的钱包、交易所、DApp等无缝流转。
ERC20代币的核心特性包括:

- 可替代性 (Fungibility):每个代币都是完全相同的,可以互换,就像比特币或法定货币一样。
- 可分割性 (Divisibility):代币可以分割到小数点后18位(默认)。
- 可转移性 (Transferable):代币可以轻松地在以太坊地址之间转移。
- 总供应量 (Total Supply):代币的总供应量是固定且可查询的。
ERC20核心接口与事件
ERC20标准定义了以下必须实现的接口(函数)和事件:
必须实现的接口:
name() public view returns (string):返回代币名称,"MyToken"。symbol() public view returns (string):返回代币符号,"MTK"。decimals() public view returns (uint8):返回代币的小数位数,通常为18。totalSupply() public view returns (uint256):返回代币的总供应量。balanceOf(address _owner) public view returns (uint256):返回指定地址的代币余额。transfer(address _to, uint256 _value) public returns (bool):调用者向指定地址转移指定数量的代币。transferFrom(address _from, address _to, uint256 _value) public returns (bool):允许被授权者从指定地址转移指定数量的代币(需要先通过approve授权)。approve(address _spender, uint256 _value) public returns (bool):授权指定地址可以调用者名义转移的代币数量。allowance(address _owner, address _spender) public view returns (uint256):返回指定地址被授权转移的代币数量。
必须实现的事件:
Transfer(address indexed from, address indexed to, uint256 value):当代币被转移时触发(包括铸造和销毁,from或to可以为0x0地址)。Approval(address indexed owner, address indexed spender, uint256 value):当授权额度被设置或修改时触发。
开发环境搭建
在开始编写智能合约之前,我们需要搭建好开发环境:

- 安装Node.js和npm:Node.js是运行JavaScript运行时环境,npm是Node.js的包管理器,从Node.js官网下载并安装最新LTS版本。
- 安装Truffle:Truffle是以太坊最受欢迎的智能合约开发框架之一,提供了开发、测试、部署等全套工具。
npm install -g truffle
- 安装Ganache:Ganache是一个个人以太坊区块链,可以让你在本地快速创建和测试智能合约,它会提供一系列预设的测试账户和以太币。
- 可以下载桌面版:Ganache Desktop
- 或通过npm安装命令行版:
npm install -g ganache-cli
- 安装MetaMask:MetaMask是一款浏览器插件钱包,用于与以太坊区块链交互,包括管理账户、发送交易、连接DApp等,从MetaMask官网安装并设置好钱包。
- 项目初始化:创建一个新的项目目录,并初始化Truffle项目。
mkdir my-erc20-token cd my-erc20-token truffle init
这会生成一些基本目录结构,如
contracts/(存放智能合约)、migrations/(部署脚本)、test/(测试文件)等。
编写ERC20代币智能合约
我们将使用OpenZeppelin库来编写ERC20代币合约,OpenZeppelin提供了经过审计的安全可靠的智能合约实现,是开发ERC20代币的首选。
- 安装OpenZeppelin Contracts:
npm install @openzeppelin/contracts
- 编写代币合约:在
contracts/目录下创建一个新的合约文件,例如MyToken.sol。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
/**MyToken
* @dev 一个简单的ERC20代币,继承自OpenZeppelin的ERC20,并添加了所有者权限。
*/
contract MyToken is ERC20, Ownable {
/**
* @dev 构造函数
* @param name_ 代币名称
* @param symbol_ 代币符号
*/
constructor(string memory name_, string memory symbol_) ERC20(name_, symbol_) {
// 在部署时铸造100万个代币给合约部署者(msg.sender)
_mint(msg.sender, 1000000 * 10**decimals());
}
/**
* @dev 只有合约所有者可以铸造新的代币
* @param to 接收代币的地址
* @param amount 铸造的代币数量(已考虑小数位数)
*/
function mint(address to, uint256 amount) public onlyOwner {
_mint(to, amount);
}
/**
* @dev 只有合约所有者可以销毁代币
* @param from 拥有代币的地址
* @param amount 销毁的代币数量(已考虑小数位数)
*/
function burn(address from, uint256 amount) public onlyOwner {
_burn(from, amount);
}
}
代码解释:
SPDX-License-Identifier和pragma solidity是Solidity合约的标准开头。import导入了OpenZeppelin的ERC20基础合约和Ownable权限管理合约。contract MyToken is ERC20, Ownable表示MyToken合约继承自ERC20和Ownable,从而获得了ERC20代币的所有功能和所有者权限。constructor是合约的构造函数,在部署时执行,这里我们调用了父合约ERC20的构造函数来设置代币名称和符号,并使用_mint函数向部署者(msg.sender)铸造初始供应量(100万代币,乘以10**decimals()是因为ERC20标准要求数量已考虑小数位数)。mint函数允许合约所有者铸造新的代币,并标记为onlyOwner,意味着只有合约所有者可以调用。burn函数允许合约所有者销毁指定地址的代币。
编写部署脚本
Truffle使用migrations目录下的脚本来部署合约。

在migrations/目录下创建一个新的文件,例如2_deploy_contracts.js:
const MyToken = artifacts.require("MyToken");
module.exports = function (deployer) {
// 部署MyToken合约,可以在这里传入构造函数的参数
deployer.deploy(MyToken, "My Awesome Token", "MAT");
};
编译与测试
-
编译合约:在项目根目录下运行:
truffle compile
如果成功,
build/contracts/目录下会生成编译后的ABI(应用程序二进制接口)和字节码文件。 -
启动本地区块链:打开一个新的终端,启动Ganache:
ganache --port 8545 # 默认端口,如果使用桌面版则无需此命令
确保Ganache显示的RPC地址(如
HTTP://127.0.0.1:7545)与Truffle配置文件中的匹配(默认truffle-config.js中是development网络的host和port)。 -
运行测试:在
test/目录下编写测试脚本(例如使用JavaScript
