ERC-4524: 更安全的 ERC-20
使用 ERC165 扩展 ERC-20 并添加 safeTransfer (类似于 ERC-721 和 ERC-1155)
Authors | William Schwab (@wschwab) |
---|---|
Created | 2021-12-05 |
Discussion Link | https://ethereum-magicians.org/t/why-isnt-there-an-erc-for-safetransfer-for-erc20/7604 |
Requires | EIP-20, EIP-165 |
摘要
本标准使用 EIP-165 扩展 ERC-20 代币,并添加来自 ERC-721 和 ERC-1155 的熟悉函数,确保接收合约已实现正确的功能。
动机
EIP-165 增加了(除其他外)判断目标接收者是否明确表示与 ERC 兼容的能力。这已经用于 NFT 的 EIP 中,即 ERC-721 和 ERC-1155。此外,EIP-165 是在流行的标准上扩展以表示实现的宝贵构建块,我们在许多 NFT 扩展中都看到了这种趋势。本 EIP 旨在将这些创新带回 ERC-20。
对于希望与 ERC-20 或 ERC-721 等通用标准集成,同时集成构建在这些标准之上的更新创新的应用程序开发人员来说,EIP-165 的重要性可能最为明显。一个简单的例子是代币许可,它允许一次性交易批准和转移。这已经在使用 ERC-2612 标准或类似标准的许多流行的 ERC-20 代币中实现。集成 ERC-20 代币的平台无法轻易判断特定代币是否已实现代币许可。(截至撰写本文时,ERC-2612 不需要 EIP-165。)借助 EIP-165,应用程序(或合约)可以查询 supportsInterface
以查看是否已注册特定 EIP 的 interfaceId
(在本例中为 ERC-2612),从而可以更轻松、更模块化的函数与 ERC-20 合约交互。在 NFT 扩展中,包含带有标准的 EIP-165 接口已经很常见,我们认为这至少部分是由于底层的 ERC-721 和 ERC-1155 标准集成了 EIP-165。我们希望对 ERC-20 的这种扩展也能通过使其更易于集成来帮助未来的扩展。
规范
本文档中使用的关键词“必须 (MUST)”,“禁止 (MUST NOT)”,“需要 (REQUIRED)”,“将会 (SHALL)”,“不应 (SHALL NOT)”,“应该 (SHOULD)”,“不应该 (SHOULD NOT)”,“推荐 (RECOMMENDED)”,“可以 (MAY)”,以及“可选 (OPTIONAL)”应按照 RFC 2119 中的描述进行解释。
为了符合此 EIP,符合 ERC-20 的合约还必须实现以下函数:
pragma solidity 0.8.10;
import './IERC20.sol';
import './IERC165.sol';
// the EIP-165 interfaceId for this interface is 0x534f5876
interface SaferERC-20 is IERC20, IERC165 {
function safeTransfer(address to, uint256 amount) external returns(bool);
function safeTransfer(address to, uint256 amount, bytes memory data) external returns(bool);
function safeTransferFrom(address from, address to, uint256 amount) external returns(bool);
function safeTransferFrom(address from, address to, uint256 amount, bytes memory data) external returns(bool);
}
safeTransfer
和 safeTransferFrom
必须按预期转移到 EOA 地址,以及转移到实现 ERC20Receiver
并在调用时返回函数选择器 (0x4fc35859
) 的合约,并且在转移到未实现 ERC20Receiver
或未返回函数选择器的合约时必须回退调用。
此外,如果合约希望接受安全转移,则必须实现以下内容,并且必须返回函数选择器 (0x4fc35859
):
pragma solidity 0.8.10;
import './IERC165.sol';
interface ERC20Receiver is IERC165 {
function onERC20Received(
address _operator,
address _from,
uint256 _amount,
bytes _data
) external returns(bytes4);
}
理由
此 EIP 旨在保持最小化和直接。将 EIP-165 添加到 ERC-20 对于许多应用程序非常有用,而且除了少量增加合约大小的代码外,没有任何缺点。safeTransfer
和 safeTransferFrom
函数在 ERC-721 和 ERC-1155 中得到广泛认可,因此保持相同的命名约定是合理的,并且在转移之前能够检查实现的好处对于 ERC-20 代币与对于 ERC-721 和 ERC-1155 同样有用。
从 EIP721 和 EIP1155 中另一个容易移植的功能可能是包含代币的元数据 URI,从而允许它们轻松引用徽标和其他详细信息。这没有被包括在内,既是为了使此 EIP 尽可能保持最小,也是因为它已由 EIP-1046 充分カバー。
向后兼容性
此 EIP 中不存在向后兼容性问题,因为 ERC-20 函数的完整套件未更改。
测试用例
测试用例已在实现存储库 此处 提供。
参考实现
已创建演示此 EIP 实现的示例存储库 此处。(截至撰写本文时)它位于 Dapptools 环境中,有关安装和运行 Dapptools 的详细信息,请参阅 Dapptools 存储库。
安全考虑
onERC20Received
是一个回调函数。回调函数过去曾被用作重入向量,应注意确保实现不受攻击。
版权
通过 CC0 免除版权和相关权利。
Citation
Please cite this document as:
William Schwab (@wschwab), "ERC-4524: 更安全的 ERC-20 [DRAFT]," Ethereum Improvement Proposals, no. 4524, December 2021. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-4524.