Solidity 合约分析:4. ERC20
介绍
你好,我是 Pluveto。我发现多数 Solidity 的教程都是从语法开始讲起,但是我觉得这样不够直观,而且很消耗耐心。这是一个系列文章,我会在这个系列里分析一些简单的 Solidity 合约。在例子中学习。
希望你能学到东西,让我们开始吧!
代码
ERC20 | Solidity by Example | 0.8.20
1// SPDX-License-Identifier: MIT
2pragma solidity ^0.8.20;
3
4// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.0.0/contracts/token/ERC20/IERC20.sol
5interface IERC20 {
6 function totalSupply() external view returns (uint);
7
8 function balanceOf(address account) external view returns (uint);
9
10 function transfer(address recipient, uint amount) external returns (bool);
11
12 function allowance(address owner, address spender) external view returns (uint);
13
14 function approve(address spender, uint amount) external returns (bool);
15
16 function transferFrom(
17 address sender,
18 address recipient,
19 uint amount
20 ) external returns (bool);
21
22 event Transfer(address indexed from, address indexed to, uint value);
23 event Approval(address indexed owner, address indexed spender, uint value);
24}
1// SPDX-License-Identifier: MIT
2pragma solidity ^0.8.20;
3
4import "./IERC20.sol";
5
6contract ERC20 is IERC20 {
7 uint public totalSupply;
8 mapping(address => uint) public balanceOf;
9 mapping(address => mapping(address => uint)) public allowance;
10 string public name = "Solidity by Example";
11 string public symbol = "SOLBYEX";
12 uint8 public decimals = 18;
13
14 function transfer(address recipient, uint amount) external returns (bool) {
15 balanceOf[msg.sender] -= amount;
16 balanceOf[recipient] += amount;
17 emit Transfer(msg.sender, recipient, amount);
18 return true;
19 }
20
21 function approve(address spender, uint amount) external returns (bool) {
22 allowance[msg.sender][spender] = amount;
23 emit Approval(msg.sender, spender, amount);
24 return true;
25 }
26
27 function transferFrom(
28 address sender,
29 address recipient,
30 uint amount
31 ) external returns (bool) {
32 allowance[sender][msg.sender] -= amount;
33 balanceOf[sender] -= amount;
34 balanceOf[recipient] += amount;
35 emit Transfer(sender, recipient, amount);
36 return true;
37 }
38
39 function mint(uint amount) external {
40 balanceOf[msg.sender] += amount;
41 totalSupply += amount;
42 emit Transfer(address(0), msg.sender, amount);
43 }
44
45 function burn(uint amount) external {
46 balanceOf[msg.sender] -= amount;
47 totalSupply -= amount;
48 emit Transfer(msg.sender, address(0), amount);
49 }
50}
ERC20 让每个人都能创建和转移代币。
interface 关键字在 Solidity 中定义接口合约。
接口合约主要为了标识合约应该实现的功能,区别于 library 和 contract:
-
使用 interface 定义接口合约。
-
接口合约只能定义函数签名,不可以定义实现函数体。
-
接口合约中的函数都是外部函数,默认是 public 的。
-
普通合约可以实现一个或多个接口,需要实现接口声明的所有函数。
interface IERC20 要求实现以下函数:
-
totalSupply() 返回代币总量。
-
balanceOf(address account) 返回指定账户的代币余额。
-
transfer(address recipient, uint amount) 转移代币到指定账户。
-
allowance(address owner, address spender) 返回 owner 授权给 spender 的代币数量。
-
approve(address spender, uint amount) 授权 spender 可以转移 amount 个代币。
-
transferFrom(address sender, address recipient, uint amount) 从 sender 转移 amount 个代币到 recipient。
同时,还定义了两个事件:
-
Transfer 代币转移事件。
-
Approval 授权事件。
然后我们来看具体实现。
-
transfer:直接更新余额,然后触发 Transfer 事件。由于 balance 是 uint 类型,所以不需要考虑溢出。
-
approve 直接通过更新 allowance 实现,然后触发 Approval 事件。
-
transferFrom:先更新 allowance,然后更新余额,最后触发 Transfer 事件。
-
mint:增发代币,然后触发 Transfer 事件。
-
burn:销毁代币,然后触发 Transfer 事件。
其他方法示例里没有完全实现。