跳转至主要内容

了解 ERC-20 代币智能合约

智能合同
通证
Solidity
erc-20
初学者
jdourlens
2020年4月5日
6 分钟阅读

以太坊上最重要的智能合约标准之一是 ERC-20,它已成为以太坊区块链上所有用于实现同质化代币的智能合约的技术标准。

ERC-20 定义了一套通用规则,所有同质化以太坊代币都应遵守。 因此,该代币标准使所有类型的开发者能够准确预测新代币在更大的以太坊系统中将如何运作。 这简化并减轻了开发者的任务,因为他们可以继续工作,并且知道只要代币遵循规则,就无需在每次发布新代币时重做每个新项目。

这里以接口的形式介绍了 ERC-20 必须实现的函数。 如果你不确定什么是接口,请查看我们关于 Solidity 面向对象编程opens in a new tab 的文章。

1pragma solidity ^0.6.0;
2
3interface IERC20 {
4
5 function totalSupply() external view returns (uint256);
6 function balanceOf(address account) external view returns (uint256);
7 function allowance(address owner, address spender) external view returns (uint256);
8
9 function transfer(address recipient, uint256 amount) external returns (bool);
10 function approve(address spender, uint256 amount) external returns (bool);
11 function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
12
13
14 event Transfer(address indexed from, address indexed to, uint256 value);
15 event Approval(address indexed owner, address indexed spender, uint256 value);
16}
显示全部

下面逐行解释每个函数的用途。 在这之后,我们将展示一个 ERC-20 代币的简单实现。

读取函数

1function totalSupply() external view returns (uint256);

返回存在的代币数量。 此函数是一个取值器,不会修改合约的状态。 请记住,Solidity 中没有浮点数。 因此,大多数代币都采用 18 位小数,总供应量及其他结果会以整数形式返回,例如 1 个代币会表示为 1000000000000000000。 并非每个代币都有 18 位小数,在处理代币时需要特别注意这一点。

1function balanceOf(address account) external view returns (uint256);

返回某个地址 (account) 拥有的代币数量。 此函数是一个取值器,不会修改合约的状态。

1function allowance(address owner, address spender) external view returns (uint256);

ERC-20 标准允许一个地址向另一个地址授予额度,以便后者能够从前者提取代币。 此取值器返回 spender 将被允许代表 owner 花费的剩余代币数量。 此函数是一个取值器,不会修改合约的状态,默认应返回 0。

函数

1function transfer(address recipient, uint256 amount) external returns (bool);

amount 数量的代币从函数调用者地址(msg.sender)移动到接收者地址。 此函数会触发稍后定义的 Transfer 事件。 如果可以转账,则返回 true。

1function approve(address spender, uint256 amount) external returns (bool);

设置 spender 可从函数调用者(msg.sender)余额中转账的 allowance(授权额度)。 此函数会触发 Approval 事件。 该函数返回是否成功设置了授权额度。

1function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);

使用授权额度机制将 amount 数量的代币从 sender 移动到 recipient。 然后从调用者的授权额度中扣除 amount。 此函数会触发 Transfer 事件。

事件

1event Transfer(address indexed from, address indexed to, uint256 value);

当一定数量(value)的代币从 from 地址发送到 to 地址时,会触发此事件。

在铸造新代币时,转账通常从 from 0x00..0000 地址进行,而在销毁代币时,转账则转 to 0x00..0000 地址。

1event Approval(address indexed owner, address indexed spender, uint256 value);

owner 批准 spender 使用一定数量(value)的代币时,会触发此事件。

ERC-20 代币的基本实现

以下是最简单的 ERC-20 代币基础代码:

1pragma solidity ^0.8.0;
2
3interface IERC20 {
4
5 function totalSupply() external view returns (uint256);
6 function balanceOf(address account) external view returns (uint256);
7 function allowance(address owner, address spender) external view returns (uint256);
8
9 function transfer(address recipient, uint256 amount) external returns (bool);
10 function approve(address spender, uint256 amount) external returns (bool);
11 function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
12
13
14 event Transfer(address indexed from, address indexed to, uint256 value);
15 event Approval(address indexed owner, address indexed spender, uint256 value);
16}
17
18
19contract ERC20Basic is IERC20 {
20
21 string public constant name = "ERC20Basic";
22 string public constant symbol = "ERC";
23 uint8 public constant decimals = 18;
24
25
26 mapping(address => uint256) balances;
27
28 mapping(address => mapping (address => uint256)) allowed;
29
30 uint256 totalSupply_ = 10 ether;
31
32
33 constructor() {
34 balances[msg.sender] = totalSupply_;
35 }
36
37 function totalSupply() public override view returns (uint256) {
38 return totalSupply_;
39 }
40
41 function balanceOf(address tokenOwner) public override view returns (uint256) {
42 return balances[tokenOwner];
43 }
44
45 function transfer(address receiver, uint256 numTokens) public override returns (bool) {
46 require(numTokens <= balances[msg.sender]);
47 balances[msg.sender] = balances[msg.sender]-numTokens;
48 balances[receiver] = balances[receiver]+numTokens;
49 emit Transfer(msg.sender, receiver, numTokens);
50 return true;
51 }
52
53 function approve(address delegate, uint256 numTokens) public override returns (bool) {
54 allowed[msg.sender][delegate] = numTokens;
55 emit Approval(msg.sender, delegate, numTokens);
56 return true;
57 }
58
59 function allowance(address owner, address delegate) public override view returns (uint) {
60 return allowed[owner][delegate];
61 }
62
63 function transferFrom(address owner, address buyer, uint256 numTokens) public override returns (bool) {
64 require(numTokens <= balances[owner]);
65 require(numTokens <= allowed[owner][msg.sender]);
66
67 balances[owner] = balances[owner]-numTokens;
68 allowed[owner][msg.sender] = allowed[owner][msg.sender]-numTokens;
69 balances[buyer] = balances[buyer]+numTokens;
70 emit Transfer(owner, buyer, numTokens);
71 return true;
72 }
73}
显示全部

ERC-20 代币标准的另一个优秀实现是 OpenZeppelin ERC-20 实现opens in a new tab

页面最后更新: 2025年8月21日

本教程对你有帮助吗?