本文档介绍了 OpenZeppelin Contracts 库中与 ERC20 代币标准相关的接口、合约和实用程序。
你当前阅读的不是此文档的最新版本。5.x 是当前版本。
| 在 https://docs.openzeppelin.com/contracts/api/token/erc20 查看本文档效果更佳 |
这组接口、合约和实用程序都与 ERC20 Token Standard 相关。
| 有关 ERC20 token 的概述以及如何创建 token 合约的演练,请阅读我们的 ERC20 指南。 |
有一些核心合约实现了 EIP 中指定的行为:
此外,还有多个自定义扩展,包括:
ERC20Permit: token 的 gasless approval。
ERC20Snapshot: 有效存储过去的 token 余额,以便以后在任何时间点查询。
ERC20Burnable: 销毁自己的 token 。
ERC20Capped: 在铸造 token 时强制对总供应量设置上限。
ERC20Pausable: 暂停 token 转移的能力。
最后,有一些实用程序可以以各种方式与 ERC20 合约交互。
SafeERC20: 接口的包装器,无需处理布尔返回值。
TokenTimelock: 为受益人持有 token ,直到指定时间。
以下相关 EIP 处于草案状态,可以在草案目录中找到。
这组核心合约旨在保持公正,允许开发人员访问 ERC20 中的内部函数(例如 _mint),并以他们喜欢的方式将它们公开为外部函数。另一方面,ERC20 Presets(例如 ERC20PresetMinterPauser)使用固定的模式进行设计,以便为开发人员提供现成的、可部署的合约。 |
IERC20EIP 中定义的 ERC20 标准接口。
函数
事件
totalSupply() → uint256 external返回现有 token 的数量。
balanceOf(address account) → uint256 external返回 account 拥有的 token 数量。
transfer(address recipient, uint256 amount) → bool external将 amount 个 token 从调用者的帐户转移到 recipient。
返回一个布尔值,指示操作是否成功。
发出一个 Transfer 事件。
allowance(address owner, address spender) → uint256 external返回 spender 将被允许代表 owner 通过 transferFrom 支配的剩余 token 数量。 默认为零。
当调用 approve 或 transferFrom 时,此值会发生变化。
approve(address spender, uint256 amount) → bool external设置 amount 作为 spender 对调用者 token 的津贴。
返回一个布尔值,指示操作是否成功。
| 请注意,使用此方法更改津贴会带来风险,即有人可能会通过不幸的交易排序来同时使用旧津贴和新津贴。一种可能的解决方案是首先将消费者的津贴减少到 0,然后设置所需的值:https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 |
发出一个 Approval 事件。
transferFrom(address sender, address recipient, uint256 amount) → bool external使用授权机制将 amount 个 token 从 sender 转移到 recipient。 然后从调用者的授信额度中扣除 amount。
返回一个布尔值,指示操作是否成功。
发出一个 Transfer 事件。
Transfer(address from, address to, uint256 value) event当 value 个 token 从一个帐户(from)转移到另一个帐户(to)时发出。
请注意,value 可能为零。
Approval(address owner, address spender, uint256 value) event当通过调用 approve 设置 spender 对 owner 的授权时发出。 value 是新的授权。
ERC20IERC20 接口的实现。
此实现与 token 的创建方式无关。 这意味着必须在使用 _mint 的派生合约中添加供应机制。
有关通用机制,请参见 ERC20PresetMinterPauser。
| 有关详细的撰写,请参见我们的指南如何实现供应机制。 |
我们遵循了通用的 OpenZeppelin 指南:函数在失败时恢复,而不是返回 false。 尽管如此,此行为是常规的,并且不与 ERC20 应用程序的期望相冲突。
此外,在调用 transferFrom 时会发出 Approval 事件。
这允许应用程序仅通过侦听所述事件来重建所有帐户的授权。 EIP 的其他实现可能不会发出这些事件,因为规范中没有要求。
最后,添加了非标准的 decreaseAllowance 和 increaseAllowance 函数,以缓解围绕设置授权的众所周知的问题。 请参见 IERC20.approve。
函数
事件
IERC20
constructor(string name_, string symbol_) public为 name 和 symbol 设置值,使用默认值 18 初始化 decimals 。
要为 decimals 选择其他值,请使用 _setupDecimals。
所有这三个值都是不可变的:它们只能在构造期间设置一次。
name() → string public返回 token 的名称。
symbol() → string public返回 token 的符号,通常是名称的简短版本。
decimals() → uint8 public返回用于获取其用户表示形式的小数位数。 例如,如果 decimals 等于 2,则应向用户将 505 个 token 的余额显示为 5,05(505 / 10 ** 2)。
token 通常选择值 18,以模仿以太币和 Wei 之间的关系。 这是 ERC20 使用的值,除非调用 _setupDecimals。
此信息仅用于 显示 目的:它绝不影响合约的任何算术,包括 IERC20.balanceOf 和 IERC20.Transfer。 |
totalSupply() → uint256 public请参见 IERC20.totalSupply。
balanceOf(address account) → uint256 public请参见 IERC20.balanceOf。
transfer(address recipient, uint256 amount) → bool public请参见 IERC20.Transfer。
要求:
recipient 不能是零地址。
调用者必须至少具有 amount 的余额。
allowance(address owner, address spender) → uint256 public请参见 IERC20.allowance。
approve(address spender, uint256 amount) → bool public请参见 IERC20.approve。
要求:
spender 不能是零地址。transferFrom(address sender, address recipient, uint256 amount) → bool public请参见 IERC20.transferFrom。
发出 Approval 事件,指示已更新的津贴。 EIP 中没有对此要求。 请参见 ERC20 开头的注释。
要求:
sender 和 recipient 不能为零地址。
sender 必须至少具有 amount 的余额。
调用者必须至少具有 sender 的 amount token 的津贴。
increaseAllowance(address spender, uint256 addedValue) → bool public以原子方式将授予 spender 的津贴增加调用者。
这是 approve 的替代方法,可以用作 IERC20.approve 中描述的问题的缓解措施。
发出 Approval 事件,指示已更新的津贴。
要求:
spender 不能是零地址。decreaseAllowance(address spender, uint256 subtractedValue) → bool public以原子方式将授予 spender 的津贴减少调用者。
这是 approve 的替代方法,可以用作 IERC20.approve 中描述的问题的缓解措施。
发出 Approval 事件,指示已更新的津贴。
要求:
spender 不能是零地址。
spender 必须至少具有 subtractedValue 的调用者的津贴。
_transfer(address sender, address recipient, uint256 amount) internal将 amount 个 token 从 sender 转移到 recipient。
此内部函数等效于 transfer,可用于例如实施自动 token 费用、削减机制等。
发出一个 transfer 事件。
要求:
sender 不能是零地址。
recipient 不能是零地址。
sender 必须至少具有 amount 的余额。
_mint(address account, uint256 amount) internal创建 amount 个 token 并将它们分配给 account,从而增加总供应量。
发出一个 transfer 事件,其中将 from 设置为零地址。
要求:
to 不能是零地址。_burn(address account, uint256 amount) internal从 account 销毁 amount 个 token,从而减少总供应量。
发出一个 transfer 事件,其中将 to 设置为零地址。
要求:
account 不能是零地址。
account 必须至少具有 amount 个 token。
_approve(address owner, address spender, uint256 amount) internal设置 amount 作为 spender 对 owner 的 token 的津贴。
此内部函数等效于 approve,可用于例如为某些子系统设置自动津贴等。
发出一个 Approval 事件。
要求:
owner 不能是零地址。
spender 不能是零地址。
_setupDecimals(uint8 decimals_) internal将 decimals 设置为默认值 18 以外的值。
此函数应仅从构造函数中调用。 与 token 合约交互的大多数应用程序都不会期望 decimals 发生更改,如果更改可能会导致错误。 |
_beforeTokenTransfer(address from, address to, uint256 amount) internal在任何 token 转移之前调用的Hook。 这包括铸造和销毁。
调用条件:
当 from 和 to 均为非零值时,from 的 amount 个 token 将被转移到 to。
当 from 为零时,将为 to 铸造 amount 个 token。
当 to 为零时,将销毁 from 的 amount 个 token。
from 和 to 永远不会都为零。
要了解有关Hook的更多信息,请转到 Using Hooks。
ERC20Snapshot此合约使用快照机制扩展了 ERC20 token。 创建快照后,将记录当时的点余额和总供应量,以供以后访问。
这可用于安全地创建基于 token 余额的机制,例如免信任股息或加权投票。 在简单的实现中,可以通过重用来自不同帐户的相同余额来执行“双重支出”攻击。 通过使用快照来计算股息或投票权,这些攻击不再适用。 它也可以用于创建有效的 ERC20 分叉机制。
快照由内部 _snapshot 函数创建,该函数将发出 Snapshot 事件并返回快照 id。 要获取创建快照时的总供应量,请使用快照 id 调用函数 totalSupplyAt。 要获取创建快照时的帐户余额,请使用快照 id 和帐户地址调用 balanceOfAt 函数。
快照是高效的。 快照创建是 O(1)。 从快照中检索余额或总供应量在已创建的快照数量中为 O(log_n),尽管特定帐户的 n 通常会小得多,因为后续快照中的相同余额存储为单个条目。
由于额外的快照记帐,普通 ERC20 转移存在恒定的开销。 对于特定帐户紧随快照之后的第一次传输,此开销仅是显着的。 后续传输将具有正常成本,直到下一个快照,依此类推。
函数
ERC20
事件
IERC20
_snapshot() → uint256 internal创建一个新快照并返回其快照 ID。
发出一个 Snapshot 事件,其中包含相同的 ID。
_snapshot 是 internal,你必须决定如何将其外部公开。 它的使用可能仅限于一组帐户,例如使用 AccessControl,或者可能对公众开放。
虽然某些信任最小化机制(例如分叉)需要一种开放的调用 _snapshot 的方法,但你必须考虑到攻击者可能会以两种方式使用它。首先,它可以用于增加从快照中检索值的成本,尽管它会以对数方式增长,从而使此攻击长期无效。 其次,它可以用于定位特定帐户并增加 ERC20 转移的成本,如上面的“Gas Costs”部分中所述。我们尚未衡量实际数字; 如果你对此感兴趣,请与我们联系。 |
balanceOfAt(address account, uint256 snapshotId) → uint256 public检索创建 snapshotId 时的 account 余额。
totalSupplyAt(uint256 snapshotId) → uint256 public检索创建 snapshotId 时的总供应量。
_beforeTokenTransfer(address from, address to, uint256 amount) internalSnapshot(uint256 id) event当创建由 id 标识的快照时,由 _snapshot 发出。
ERC20Pausable具有可暂停的 token 转移、铸造和销毁的 ERC20 token。
适用于诸如在评估期结束之前阻止交易,或具有紧急开关以在出现重大错误时冻结所有 token 转移的情况。
函数
Pausable
事件
Pausable
IERC20
_beforeTokenTransfer(address from, address to, uint256 amount) internal查看 ERC20._beforeTokenTransfer.
要求:
ERC20BurnableERC20 的扩展,允许 token 持有者销毁他们自己的
token 以及他们拥有授权的 token,这种方式可以通过链下方式识别(通过事件分析)。
函数
ERC20
事件
IERC20
burn(uint256 amount) public从调用者处销毁 amount 数量的 token。
查看 ERC20._burn。
burnFrom(address account, uint256 amount) public从 account 处销毁 amount 数量的 token,从调用者的授权中扣除。
查看 ERC20._burn 和 ERC20.allowance。
要求:
amount 数量的 accounts 的 token 授权。ERC20CappedERC20 的扩展,增加了 token 供应量的上限。
函数
ERC20
事件
IERC20
constructor(uint256 cap_) internal设置 cap 的值。这个值是不可变的,只能在构造期间设置一次。
cap() → uint256 public返回 token 总供应量的上限。
_beforeTokenTransfer(address from, address to, uint256 amount) internal查看 ERC20._beforeTokenTransfer。
要求:
SafeERC20ERC20 操作的包装器,在失败时抛出异常(当 token
合约返回 false 时)。也支持不返回值(而是在失败时恢复或抛出异常)的 Token,假定非恢复调用是成功的。
要使用此库,你可以将 using SafeERC20 for IERC20; 语句添加到你的合约中,
这允许你将安全操作称为 token.safeTransfer(…) 等。
函数
safeTransfer(contract IERC20 token, address to, uint256 value) internalsafeTransferFrom(contract IERC20 token, address from, address to, uint256 value) internalsafeApprove(contract IERC20 token, address spender, uint256 value) internal已弃用。此函数存在与 IERC20.approve 中发现的问题类似的问题,不鼓励使用。
如果可能,请改用 safeIncreaseAllowance 和
safeDecreaseAllowance。
safeIncreaseAllowance(contract IERC20 token, address spender, uint256 value) internalsafeDecreaseAllowance(contract IERC20 token, address spender, uint256 value) internalTokenTimelock一个 token 持有者合约,它将允许受益人在给定的释放时间后提取 token。
适用于简单的归属计划,例如“顾问在 1 年后获得他们所有的 token”。
函数
constructor(contract IERC20 token_, address beneficiary_, uint256 releaseTime_) publictoken() → contract IERC20 publicbeneficiary() → address publicreleaseTime() → uint256 publicrelease() public
- 原文链接: docs.openzeppelin.com/co...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!