ERC20 代币合约跟踪可替代代币:任何一个代币都完全等于任何其他代币;没有代币具有与之相关的特殊权利或行为。这使得ERC20令牌的东西就像一个有用的兑换货币的媒介投票权跑马圈地,等等。

OpenZeppelin Contracts 提供了许多与 ERC20 相关的合约。

构建 ERC20 代币合约

使用合约,我们可以轻松创建我们自己的 ERC20 代币合约,该合约将用于跟踪黄金(GLD),一种假设游戏中的内部货币。

这是我们的 GLD 代币可能的样子。

// contracts/GLDToken.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract GLDToken is ERC20 {
    constructor(uint256 initialSupply) ERC20("Gold", "GLD") {
        _mint(msg.sender, initialSupply);
    }
}

我们的契约经常通过继承来使用,这里我们重用ERC20了基本的标准实现和namesymbol, 和decimals可选的扩展。此外,我们正在创建一个initialSupplyof 令牌,它将被分配到部署合约的地址。

有几个核心合约实现了 EIP 中指定的行为:

  • IERC20:所有 ERC20 实现都应符合的接口。
  • IERC20Metadata:扩展的 ERC20 接口,包括namesymboldecimals功能。
  • ERC20:所述ERC20接口的实现,包括namesymboldecimals可选的标准扩展的基本接口。

此外,还有多个自定义扩展,包括:

  • ERC20Burnable: 销毁自己的代币。
  • ERC20Capped:在铸造代币时对总供应量实施上限。
  • ERC20Pausable:暂停令牌传输的能力。
  • ERC20Snapshot:有效存储过去的代币余额,以便以后随时查询。
  • ERC20Permit:代币的无气体批准(标准化为 ERC2612)。
  • ERC20FlashMint:通过铸造和燃烧临时代币(标准化为 ERC3156)为闪电贷提供代币级别的支持。
  • ERC20Votes: 支持投票和投票委托。
  • ERC20VotesComp: 支持投票和投票委托(兼容 Compound 的 token,有 uint96 限制)。
  • ERC20Wrapper:包装器以创建由另一个 ERC20 支持的 ERC20,具有存款和取款方法。与 结合使用很有用ERC20Votes

最后,还有一些实用程序可以以各种方式与 ERC20 合约进行交互。

  • SafeERC20:接口的包装器,无需处理布尔返回值。
  • TokenTimelock:为受益人持有代币直到指定时间。

以下相关 EIP 处于草案状态。

  • ERC20Permit
这组核心合约被设计为无主见,允许开发人员访问 ERC20 中的内部功能(例如_mint),并以他们喜欢的方式将它们公开为外部功能。另一方面,ERC20 Presets(例如ERC20PresetMinterPauser)是使用自以为是的模式设计的,为开发人员提供即用型、可部署的合约。

核心代码

IERC20

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

EIP 中定义的 ERC20 标准的接口。

FUNCTIONS
totalSupply()
//返回存在的代币数量。

balanceOf(account)
//返回account拥有的代币数量。 

transfer(recipient, amount) 
//将amount令牌从调用者的帐户移动到recipient。 
//返回一个布尔值,指示操作是否成功。 
//发出一个Transfer事件。 

allowance(owner, spender) 
//返回spender允许代表ownerthrough花费的剩余代币数transferFrom。 
//默认情况下为零。这个值在approve或transferFrom被调用时改变。 

approve(spender, amount) 
//设置amount为对spender调用者令牌的允许。 
//返回一个布尔值,指示操作是否成功。 

transferFrom(sender, recipient, amount) 
//使用许可机制将amount代币从移动sender到recipient。amount然后从来电者的津贴中扣除。 
//返回一个布尔值,指示操作是否成功。 
//发出一个Transfer事件。

 

EVENTS

Transfer(from, to, value)
//当代value币从一个账户 ( from) 移动到另一个 ( to) 时发出。 请注意,value可能为零。

Approval(owner, spender, value)
//当调用aspender为 anowner设置允许时发出approve。value是新的津贴。

IERC20Metadata

import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";

ERC20 标准中可选元数据功能的接口。

从 v4.1 开始可用。

FUNCTIONS
name()
//返回令牌的名称。

symbol()
//返回令牌的符号。

decimals()
//返回令牌的小数位。

IERC20
totalSupply()

balanceOf(account)

transfer(recipient, amount)

allowance(owner, spender)

approve(spender, amount)

transferFrom(sender, recipient, amount)

ERC20

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

IERC20接口的实现。

此实现与创建令牌的方式无关。这意味着必须使用_mint. 有关通用机制,请参阅ERC20PresetMinterPauser

我们遵循了 OpenZeppelin 合同的一般准则:函数false在失败时恢复而不是返回。尽管如此,这种行为是传统的,并且与 ERC20 应用程序的期望没有冲突。

此外,Approval在调用transferFrom. 这允许应用程序仅通过侦听所述事件来重建所有帐户的限额。EIP 的其他实现可能不会发出这些事件,因为规范没有要求。

最后,增加了非标准decreaseAllowanceincreaseAllowance 功能,以缓解围绕设置配额的众所周知的问题。见IERC20.approve

FUNCTIONS
constructor(name_, symbol_)
//设置的数值name和symbol。 decimals默认值为18。要为decimals您选择不同的值, 应重载它。 所有这两个值都是不可变的:它们只能在构造过程中设置一次。

name()
//返回令牌的名称。

symbol()
//返回令牌的符号,通常是名称的较短版本。

decimals()
//返回用于获取其用户表示的小数位数。例如,如果decimals等于2,505则应向用户显示代币余额为5.05( 505 / 10 ** 2)。 代币通常选择值 18,模仿 Ether 和 Wei 之间的关系。这是ERC20使用的值,除非该函数被覆盖

totalSupply()

balanceOf(account)

transfer(recipient, amount)

allowance(owner, spender)

approve(spender, amount)

transferFrom(sender, recipient, amount)
//发出一个Approval事件,指示更新的限额。这不是 EIP 所要求的。见开头的注释ERC20。 要求: sender并且recipient不能是零地址。 sender必须至少有余额amount。 调用者必须sender至少拥有 amount.

increaseAllowance(spender, addedValue)
//原地址增加spender调用者授予的津贴。 
//这是一种替代方法approve,可用作 中描述的问题的缓解措施IERC20.approve。 
//发出一个Approval事件,指示更新的限额。 
//要求: spender 不能是零地址。

decreaseAllowance(spender, subtractedValue)
//原地址减少spender调用者授予的津贴。 
//这是一种替代方法approve,可用作 中描述的问题的缓解措施IERC20.approve。 
//发出一个Approval事件,指示更新的限额。 
//要求: spender 不能是零地址。 

_transfer(sender, recipient, amount)
//amount令牌从sender到 的移动recipient。 
//这个内部函数等价于transfer,可以用来实现自动代币费用、slashing 机制等。 
//发出一个transfer事件。 要求: sender 不能是零地址。 
//recipient 不能是零地址。 
//sender必须至少有余额amount。

_mint(account, amount)
//创建amount代币并将它们分配给account,从而增加总供应量。  
//要求: account 不能是零地址。

_burn(account, amount)
//amount从销毁代币account,减少总供应量。 
//要求: account 不能是零地址。 account必须至少有amount令牌。

_approve(owner, spender, amount)
//设置amount为spender超过owners 个令牌的津贴。 
//此内部函数等效于approve,可用于例如设置某些子系统的自动余量等。 
//发出一个Approval事件。 
//要求: owner 不能是零地址。 spender 不能是零地址。

_beforeTokenTransfer(from, to, amount)
//在任何代币转移之前调用的钩子。这包括铸造和燃烧。 
//调用条件: 当from和to都非零时,amountoffrom的代币将被转移到to。 当from为零时,amount将为 铸造代币to。 当to为零时,amountoffrom的代币将被烧毁。 from并且to永远不会都为零。

_afterTokenTransfer(from, to, amount)
//在任何代币转移后调用的钩子。这包括铸造和燃烧。
//调用条件:当from和to都非零时,amountoffrom的令牌已转移到to。当from为零时,amount代币已被铸造为to。当to为零时,amountoffrom的令牌已被烧毁。from并且to永远不会都为零。

 

ERC20Burnable

import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";

其扩展ERC20允许代币持有者以一种可以在链外识别的方式(通过事件分析)销毁他们自己的代币和他们允许的代币。


FUNCTIONS
burn(amount)
//销毁amount来自调用者的令牌。 

burnFrom(account, amount) 
//amount从 中销毁令牌account,从调用者的津贴中扣除。 
//见ERC20._burn和ERC20.allowance。 
//要求: 调用者必须accounts至少拥有 amount. 

ERC20 
constructor(name_, symbol_) 
name() 

symbol() 

decimals() 

totalSupply() 

balanceOf(account) 

transfer(recipient, amount) 

allowance(owner, spender) 

approve(spender, amount) 

transferFrom(sender, recipient, amount) 

increaseAllowance(spender, addedValue) 

decreaseAllowance(spender, subtractedValue) 

_transfer(sender, recipient, amount) 

_mint(account, amount) 

_burn(account, amount) 

_approve(owner, spender, amount) 

_beforeTokenTransfer(from, to, amount) 

_afterTokenTransfer(from, to, amount) 

ERC20Capped

import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Capped.sol";

其扩展ERC20增加了代币供应的上限。

FUNCTIONS
constructor(cap_)
//设置 cap 的值。这个值是不可变的,它只能在构造过程中设置一次。 

cap()
//返回代币总供应量的上限。 

_mint(account, amount) 

ERC20 
name() 

symbol() 

decimals() 

totalSupply() 

balanceOf(account) 

transfer(recipient, amount) 

allowance(owner, spender) 

approve(spender, amount) 

transferFrom(sender, recipient, amount) 

increaseAllowance(spender, addedValue) 

decreaseAllowance(spender, subtractedValue) 

_transfer(sender, recipient, amount) 

_burn(account, amount)
 
_approve(owner, spender, amount)
 
_beforeTokenTransfer(from, to, amount) 

_afterTokenTransfer(from, to, amount)
 

ERC20Pausable

import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol";

ERC20 代币,可暂停代币转移、铸造和燃烧。

适用于诸如在评估期结束前阻止交易,或在出现大错误时使用紧急开关冻结所有代币转移等场景。

FUNCTIONS
_beforeTokenTransfer(from, to, amount)

PAUSABLE
constructor()

paused()

_pause()

_unpause()

ERC20
name()

symbol()

decimals()

totalSupply()

balanceOf(account)

transfer(recipient, amount)

allowance(owner, spender)

approve(spender, amount)

transferFrom(sender, recipient, amount)

increaseAllowance(spender, addedValue)

decreaseAllowance(spender, subtractedValue)

_transfer(sender, recipient, amount)

_mint(account, amount)

_burn(account, amount)

_approve(owner, spender, amount)

_afterTokenTransfer(from, to, amount)

发表评论

后才能评论