ERC-20 代币标准
文章目录
- 一、什么是 ERC-20?
-
- 核心价值:
-
- 互操作性
- 简化开发
- 生态基石
- 二、ERC-20 的六大核心功能
-
- 基础功能
- 授权与代理转账
- 事件通知
- 三、ERC-20 代币的典型应用场景
- 四、ERC-20 的技术优势与局限性
-
- 优势:
- 局限性:
- 五、ERC-20 代币的创建步骤
-
- 编写智能合约
- 部署合约
- 验证与审计
- python 示例
- 六、ERC-20 与其他代币标准的对比
- 七、ERC-20 的安全风险与历史事件
一、什么是 ERC-20?
ERC-20(Ethereum Request for Comments 20)是以太坊区块链上最广泛使用的代币标准,定义了智能合约发行可互换代币(Fungible Token)的通用规则。通过标准化接口,ERC-20 确保不同代币在钱包、交易所和 DeFi 协议中无缝交互。
核心价值:
互操作性
所有 ERC-20 代币兼容以太坊生态工具(如 MetaMask、Uniswap)。
简化开发
开发者无需从零设计代币逻辑,降低开发成本。
生态基石
支撑了 90% 以上的以太坊代币(如 USDT、UNI、LINK)。
二、ERC-20 的六大核心功能
ERC-20 标准要求代币合约必须实现以下接口:
基础功能
totalSupply():返回代币总供应量。
balanceOf(address):查询指定地址的余额。
transfer(address, uint256):向目标地址转账代币。
授权与代理转账
approve(address, uint256):授权第三方地址使用一定数量的代币。
transferFrom(address, address, uint256):被授权地址代理转账(如交易所提币)。
事件通知
Transfer(address, address, uint256):代币转账时触发。
Approval(address, address, uint256):授权操作时触发。
三、ERC-20 代币的典型应用场景
四、ERC-20 的技术优势与局限性
优势:
标准化兼容:钱包和交易所无需为每种代币单独开发支持逻辑。
低成本发行:使用模板(如 OpenZeppelin 库)可在 10 分钟内创建代币。
灵活扩展:可通过继承 ERC-20 合约添加功能(如代币销毁、分红机制)。
局限性:
转账安全性问题:
若向合约地址误转 ERC-20 代币(未实现 tokensReceived 的回调),代币将永久丢失(ERC-223 已修复此问题)。
无元数据支持:
代币名称、符号等需硬编码在合约中,ERC-20 未强制要求(导致部分代币显示异常)。
批量操作低效:
批量转账需多次调用 transfer,消耗更多 Gas(ERC-1155 优化了此问题)。
五、ERC-20 代币的创建步骤
编写智能合约
使用 Solidity 继承 OpenZeppelin 的 ERC-20 模板:
<SOLIDITY>// SPDX-License-Identifier: MITpragma solidity ^0.8.0;import \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";contract MyToken is ERC20 { constructor(uint256 initialSupply) ERC20(\"MyToken\", \"MTK\") { _mint(msg.sender, initialSupply); }}
部署合约
通过 Remix IDE 或 Hardhat 部署到以太坊网络(主网或测试网)。
验证与审计
在 Etherscan 验证合约源码。
进行安全审计(尤其涉及代币增发、权限控制逻辑)。
python 示例
==参考:https://ethereum.org/zh/developers/docs/standards/tokens/erc-20/#web3py-example
让我们看看如此重要的一个标准是如何使我们能够简单地检查以太坊上的任何 ERC-20 代币合约。 我们只需要合约的应用程序二进制接口 (ABI) 来创造一个 ERC-20 代币界面。 下面我们将使用一个简化的应用程序二进制接口,让例子变得更为简单。
from web3 import Web3w3 = Web3(Web3.HTTPProvider(\"https://cloudflare-eth.com\"))dai_token_addr = \"0x6B175474E89094C44Da98b954EedeAC495271d0F\" # DAIweth_token_addr = \"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2\" # Wrapped ether (WETH)acc_address = \"0xA478c2975Ab1Ea89e8196811F51A7B7Ade33eB11\" # Uniswap V2: DAI 2# This is a simplified Contract Application Binary Interface (ABI) of an ERC-20 Token Contract.# It will expose only the methods: balanceOf(address), decimals(), symbol() and totalSupply()simplified_abi = [ { \'inputs\': [{\'internalType\': \'address\', \'name\': \'account\', \'type\': \'address\'}], \'name\': \'balanceOf\', \'outputs\': [{\'internalType\': \'uint256\', \'name\': \'\', \'type\': \'uint256\'}], \'stateMutability\': \'view\', \'type\': \'function\', \'constant\': True }, { \'inputs\': [], \'name\': \'decimals\', \'outputs\': [{\'internalType\': \'uint8\', \'name\': \'\', \'type\': \'uint8\'}], \'stateMutability\': \'view\', \'type\': \'function\', \'constant\': True }, { \'inputs\': [], \'name\': \'symbol\', \'outputs\': [{\'internalType\': \'string\', \'name\': \'\', \'type\': \'string\'}], \'stateMutability\': \'view\', \'type\': \'function\', \'constant\': True }, { \'inputs\': [], \'name\': \'totalSupply\', \'outputs\': [{\'internalType\': \'uint256\', \'name\': \'\', \'type\': \'uint256\'}], \'stateMutability\': \'view\', \'type\': \'function\', \'constant\': True }]dai_contract = w3.eth.contract(address=w3.to_checksum_address(dai_token_addr), abi=simplified_abi)symbol = dai_contract.functions.symbol().call()decimals = dai_contract.functions.decimals().call()totalSupply = dai_contract.functions.totalSupply().call() / 10**decimalsaddr_balance = dai_contract.functions.balanceOf(acc_address).call() / 10**decimals# DAIprint(\"===== %s =====\" % symbol)print(\"Total Supply:\", totalSupply)print(\"Addr Balance:\", addr_balance)weth_contract = w3.eth.contract(address=w3.to_checksum_address(weth_token_addr), abi=simplified_abi)symbol = weth_contract.functions.symbol().call()decimals = weth_contract.functions.decimals().call()totalSupply = weth_contract.functions.totalSupply().call() / 10**decimalsaddr_balance = weth_contract.functions.balanceOf(acc_address).call() / 10**decimals# WETHprint(\"===== %s =====\" % symbol)print(\"Total Supply:\", totalSupply)print(\"Addr Balance:\", addr_balance)
六、ERC-20 与其他代币标准的对比
七、ERC-20 的安全风险与历史事件
批量转账漏洞
案例:2017 年 Parity 多重签名钱包漏洞导致 1.5 亿美元 ETH 被冻结。
教训:代币合约需严格限制权限(如禁用 approve 后门)。
假代币骗局
手法:骗子部署同名 ERC-20 合约(如虚假 USDT),诱导用户充值。
防御:交易前需在 Etherscan 验证合约地址和代码。
重入攻击
案例:2016 年 The DAO 事件(非 ERC-20 但影响生态)。
防护:使用 Checks-Effects-Interactions 模式编写合约逻辑。