Skip to content

Commit 4ad0f04

Browse files
committed
Add study notes for 2025-08-21
1 parent cf72c40 commit 4ad0f04

1 file changed

Lines changed: 79 additions & 0 deletions

File tree

zhenghaoailimiao.md

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,85 @@ timezone: UTC+8
1515
## Notes
1616

1717
<!-- Content_START -->
18+
# 2025-08-21
19+
20+
### ERC-20
21+
#### 1.可选函数
22+
ERC-20标准接口中有三个可选函数,主要是返回代币的基本信息,所以也可以称为元数据。其智能合约中的代码如下:
23+
``` javascript
24+
// IERC20Metadata.sol
25+
// SPDX-License-Identifier: MIT
26+
pragma solidity ^0.8.0;
27+
28+
import "./IERC20.sol";
29+
30+
interface IERC20Metadata is IERC20 {
31+
32+
function name() external view returns (string memory);
33+
function symbol() external view returns (string memory);
34+
function decimals() external view returns (uint8);
35+
}
36+
```
37+
- *name()*:返回的是代币的名称,例如:MyToken
38+
- *symbol()*:返回的是代币的代号,例如:MTK
39+
- *decimals()*:返回的是代币的使用的小数位数,例如8(意味着将代币总量除以100000000来获取表现的形式)
40+
#### 2.必要函数
41+
智能合约中标准定义的ERC20的必要函数如下:
42+
``` javascript
43+
// IERC20.sol
44+
// SPDX-License-Identifier: MIT
45+
46+
pragma solidity ^0.8.0;
47+
48+
interface IERC20 {
49+
50+
function totalSupply() external view returns (uint256);
51+
function balanceOf(address account) external view returns (uint256);
52+
function transfer(address recipient, uint256 amount) external returns (bool);
53+
function allowance(address owner, address spender) external view returns (uint256);
54+
function approve(address spender, uint256 amount) external returns (bool);
55+
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
56+
event Transfer(address indexed from, address indexed to, uint256 value);
57+
event Approval(address indexed owner, address indexed spender, uint256 value);
58+
}
59+
```
60+
- *totalSupply()*:返回该ERC20代币在区块链上创建的总数量。
61+
- *balanceOf(address account)*:返回地址拥有的代币数量。
62+
- *transfer(address recipient, uint256 amount)*:将代币数量amount从调用者地址(msg.sender)转移到接收者地址,函数必须触发事件Transfer。
63+
- *allowance(address owner, address spender)*:查询owner授权给spender的额度。
64+
- *approve(address spender, uint256 amount)*:允许spender地址可以最多转移的代币数量为amount。
65+
- *transferFrom(address sender, address recipient, uint256 amount)*:从sender向recipient地址转移amount数量的代币,函数必须触发事件Transfer。
66+
- *Transfer*:当有代币转移时,必须触发Transfer事件。
67+
- *Approval*:approve()函数成功执行时,必须触发Approval事件。
68+
#### 3.避免与USDT合约交互陷阱
69+
#### 3.1 现象:
70+
有个业务场景,需要用户将ERC20版的USDT转入一个合约,然后满足一定条件时通过该合约将转入的USDT转回给用户。
71+
在测试网上测试,一切正常。合约审查,完全没问题。顺利主网上线!
72+
测试用户将USDT转入合约,满足条件后等待合约将USDT转回。这时候问题出现了,转入的USDT竟然转不出来了,转不出来了!
73+
#### 3.2 原因:
74+
ERC20 标准接口的 transfer 方法,都是有返回值定义的,**returns (bool)**;
75+
比如前面提到的:
76+
``` javascript
77+
function transfer(address to, uint256 value) external returns (bool);
78+
function transferFrom(address from, address to, uint256 value) external returns (bool);
79+
```
80+
但是USDT合约对transfer方法的具体实现,是**没有返回值**的。虽然代码里还写了两个return语句,实际上这两个return后面的方法调用都是没有定义返回结果的,否则编译器会报错,不可能部署成功。
81+
USDT合约transfer方法如下:
82+
``` javascript
83+
function transfer(address _to, uint _value) public whenNotPaused {
84+
require(!isBlackListed[msg.sender]);
85+
if (deprecated) {
86+
return UpgradedStandardToken(upgradedAddress).transferByLegacy(msg.sender, _to, _value);
87+
} else {
88+
return super.transfer(_to, _value);
89+
}
90+
}
91+
```
92+
#### 3.3 解决方法:
93+
1.在自己合约代码里引用的ERC20接口中transfer方法中的返回值定义去掉。
94+
95+
2.使用SafeERC20接口调用SafeTransfer方法。
96+
1897
# 2025-08-20
1998
2099
## Uniswap v2里的swap操作

0 commit comments

Comments
 (0)