EIP-20ERC代币标准Final(2015-11-19)可替代代币标准
同质化代币的最小接口:6 个函数 + 2 个事件。稳定币、治理币、LP 代币、质押凭证几乎都由它派生。
适用链:全部 EVM 链 + 各 L2
为什么重要:因为接口统一,钱包、交易所、区块浏览器、DEX 才能「一套代码对接所有代币」。看懂 ERC-20 是看懂整个 DeFi 的前置条件:approve 与 transferFrom 的机制就是后来一切授权钓鱼的根源。
函数签名与选择器
选择器是签名的 keccak256 前 4 字节;事件则是完整的 32 字节 topic0。 点一下即可复制。
| 签名 / 字段 | 选择器 / topic0 | 说明 |
|---|---|---|
| totalSupply() | 当前流通总量。若支持增发/销毁则是动态值。 | |
| balanceOf(address) | 查询某地址余额。注意它链上没有隐私性。 | |
| transfer(address,uint256) | 从调用者转出。返回 bool,但不少老币不返回或永远返回 true。 | |
| approve(address,uint256) | 授权 spender 可动用不超过 value 的额度,是覆盖而非累加。 | |
| allowance(address,address) | 查询剩余授权额度,撤销授权的检查依据。 | |
| transferFrom(address,address,uint256) | 代扣:从 from 转给 to,消耗调用者的授权额度。 | |
| event Transfer(address,address,uint256)事件 | 前两个参数 indexed,铸造用 from = address(0),销毁用 to = address(0)。 | |
| event Approval(address,address,uint256)事件 | owner 授权 spender。索引器靠它重建授权清单。 |
代码模板
最小可用实现(零依赖,可直接编译部署)
最小可用实现(零依赖,可直接编译部署)Solidity
decimals 必须是常量且为 18 之外的值时要在文档里写明(USDC 是 6)。前端硬编码 18 会把 1 USDC 显示成 0.000001。
用 ethers v6 读余额与授权
用 ethers v6 读余额与授权JavaScript
实现与使用时的常见陷阱
- ✕approve 是覆盖写,不是累加。把 100 覆盖成 50 之前,老代码里「先置 0 再设值」的双交易写法是为了绕过某些老币的竞态保护。
- ✕兼容非标准代币:有些币(BNB 早期的 BEP-20 实现)transfer 不返回 bool,直接 require(token.transfer()) 会失败。要判断返回数据长度。
- ✕不要用 transfer 给合约地址转账后指望它有回调——ERC-20 没有钩子,转进去就是永久锁死。
- ✕无限授权是最大的安全隐患。定期用区块浏览器或授权管理工具检查并撤销。
- ✕不要依赖 decimals() 的调用结果做链下硬编码以外的假设,代币不会在同一交易里改它,但代理合约理论上可以。
相关标准
同属「代币标准」的其他标准