ERC 20

This set of interfaces, contracts, and utilities are all related to the ERC20 Token Standard.

For an overview of ERC20 tokens and a walk through on how to create a token contract read our ERC20 guide.

There a few core contracts that implement the behavior specified in the EIP:

  • IERC20: the interface all ERC20 implementations should conform to.

  • ERC20: the implementation of the ERC20 interface, including the name, symbol and decimals optional standard extension to the base interface.

Additionally there are multiple custom extensions, including:

  • ERC20Permit: gasless approval of tokens.

  • ERC20Snapshot: efficient storage of past token balances to be later queried at any point in time.

  • ERC20Burnable: destruction of own tokens.

  • ERC20Capped: enforcement of a cap to the total supply when minting tokens.

  • ERC20Pausable: ability to pause token transfers.

Finally, there are some utilities to interact with ERC20 contracts in various ways.

  • SafeERC20: a wrapper around the interface that eliminates the need to handle boolean return values.

  • TokenTimelock: hold tokens for a beneficiary until a specified time.

The following related EIPs are in draft status and can be found in the drafts directory.

This core set of contracts is designed to be unopinionated, allowing developers to access the internal functions in ERC20 (such as _mint) and expose them as external functions in the way they prefer. On the other hand, ERC20 Presets (such as ERC20PresetMinterPauser) are designed using opinionated patterns to provide developers with ready to use, deployable contracts.

Core

IERC20

Interface of the ERC20 standard as defined in the EIP.

totalSupply() → uint256 external

Returns the amount of tokens in existence.

balanceOf(address account) → uint256 external

Returns the amount of tokens owned by account.

transfer(address recipient, uint256 amount) → bool external

Moves amount tokens from the caller’s account to recipient.

Returns a boolean value indicating whether the operation succeeded.

Emits a Transfer event.

allowance(address owner, address spender) → uint256 external

Returns the remaining number of tokens that spender will be allowed to spend on behalf of owner through transferFrom. This is zero by default.

This value changes when approve or transferFrom are called.

approve(address spender, uint256 amount) → bool external

Sets amount as the allowance of spender over the caller’s tokens.

Returns a boolean value indicating whether the operation succeeded.

Beware that changing an allowance with this method brings the risk that someone may use both the old and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this race condition is to first reduce the spender’s allowance to 0 and set the desired value afterwards: https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729

Emits an Approval event.

transferFrom(address sender, address recipient, uint256 amount) → bool external

Moves amount tokens from sender to recipient using the allowance mechanism. amount is then deducted from the caller’s allowance.

Returns a boolean value indicating whether the operation succeeded.

Emits a Transfer event.

Transfer(address from, address to, uint256 value) event

Emitted when value tokens are moved from one account (from) to another (to).

Note that value may be zero.

Approval(address owner, address spender, uint256 value) event

Emitted when the allowance of a spender for an owner is set by a call to approve. value is the new allowance.

ERC20

Implementation of the IERC20 interface.

This implementation is agnostic to the way tokens are created. This means that a supply mechanism has to be added in a derived contract using _mint. For a generic mechanism see ERC20PresetMinterPauser.

For a detailed writeup see our guide How to implement supply mechanisms.

We have followed general OpenZeppelin guidelines: functions revert instead of returning false on failure. This behavior is nonetheless conventional and does not conflict with the expectations of ERC20 applications.

Additionally, an Approval event is emitted on calls to transferFrom. This allows applications to reconstruct the allowance for all accounts just by listening to said events. Other implementations of the EIP may not emit these events, as it isn’t required by the specification.

Finally, the non-standard decreaseAllowance and increaseAllowance functions have been added to mitigate the well-known issues around setting allowances. See IERC20.approve.

constructor(string name_, string symbol_) public

Sets the values for name and symbol, initializes decimals with a default value of 18.

To select a different value for decimals, use _setupDecimals.

All three of these values are immutable: they can only be set once during construction.

name() → string public

Returns the name of the token.

symbol() → string public

Returns the symbol of the token, usually a shorter version of the name.

decimals() → uint8 public

Returns the number of decimals used to get its user representation. For example, if decimals equals 2, a balance of 505 tokens should be displayed to a user as 5,05 (505 / 10 ** 2).

Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value ERC20 uses, unless _setupDecimals is called.

This information is only used for display purposes: it in no way affects any of the arithmetic of the contract, including IERC20.balanceOf and IERC20.Transfer.

totalSupply() → uint256 public

balanceOf(address account) → uint256 public

transfer(address recipient, uint256 amount) → bool public

Requirements:

  • recipient cannot be the zero address.

  • the caller must have a balance of at least amount.

allowance(address owner, address spender) → uint256 public

approve(address spender, uint256 amount) → bool public

Requirements:

  • spender cannot be the zero address.

transferFrom(address sender, address recipient, uint256 amount) → bool public

Emits an Approval event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of ERC20.

Requirements:

  • sender and recipient cannot be the zero address.

  • sender must have a balance of at least amount.

  • the caller must have allowance for sender's tokens of at least amount.

increaseAllowance(address spender, uint256 addedValue) → bool public

Atomically increases the allowance granted to spender by the caller.

This is an alternative to approve that can be used as a mitigation for problems described in IERC20.approve.

Emits an Approval event indicating the updated allowance.

Requirements:

  • spender cannot be the zero address.

decreaseAllowance(address spender, uint256 subtractedValue) → bool public

Atomically decreases the allowance granted to spender by the caller.

This is an alternative to approve that can be used as a mitigation for problems described in IERC20.approve.

Emits an Approval event indicating the updated allowance.

Requirements:

  • spender cannot be the zero address.

  • spender must have allowance for the caller of at least subtractedValue.

_transfer(address sender, address recipient, uint256 amount) internal

Moves tokens amount from sender to recipient.

This is internal function is equivalent to transfer, and can be used to e.g. implement automatic token fees, slashing mechanisms, etc.

Emits a transfer event.

Requirements:

  • sender cannot be the zero address.

  • recipient cannot be the zero address.

  • sender must have a balance of at least amount.

_mint(address account, uint256 amount) internal

Creates amount tokens and assigns them to account, increasing the total supply.

Emits a transfer event with from set to the zero address.

Requirements:

  • to cannot be the zero address.

_burn(address account, uint256 amount) internal

Destroys amount tokens from account, reducing the total supply.

Emits a transfer event with to set to the zero address.

Requirements:

  • account cannot be the zero address.

  • account must have at least amount tokens.

_approve(address owner, address spender, uint256 amount) internal

Sets amount as the allowance of spender over the owner s tokens.

This internal function is equivalent to approve, and can be used to e.g. set automatic allowances for certain subsystems, etc.

Emits an Approval event.

Requirements:

  • owner cannot be the zero address.

  • spender cannot be the zero address.

_setupDecimals(uint8 decimals_) internal

Sets decimals to a value other than the default one of 18.

This function should only be called from the constructor. Most applications that interact with token contracts will not expect decimals to ever change, and may work incorrectly if it does.

_beforeTokenTransfer(address from, address to, uint256 amount) internal

Hook that is called before any transfer of tokens. This includes minting and burning.

Calling conditions:

  • when from and to are both non-zero, amount of from's tokens will be to transferred to to.

  • when from is zero, amount tokens will be minted for to.

  • when to is zero, amount of from's tokens will be burned.

  • from and to are never both zero.

To learn more about hooks, head to Using Hooks.

Extensions

ERC20Snapshot

This contract extends an ERC20 token with a snapshot mechanism. When a snapshot is created, the balances and total supply at the time are recorded for later access.

This can be used to safely create mechanisms based on token balances such as trustless dividends or weighted voting. In naive implementations it’s possible to perform a "double spend" attack by reusing the same balance from different accounts. By using snapshots to calculate dividends or voting power, those attacks no longer apply. It can also be used to create an efficient ERC20 forking mechanism.

Snapshots are created by the internal _snapshot function, which will emit the Snapshot event and return a snapshot id. To get the total supply at the time of a snapshot, call the function totalSupplyAt with the snapshot id. To get the balance of an account at the time of a snapshot, call the balanceOfAt function with the snapshot id and the account address.

Gas Costs

Snapshots are efficient. Snapshot creation is O(1). Retrieval of balances or total supply from a snapshot is O(log n) in the number of snapshots that have been created, although n for a specific account will generally be much smaller since identical balances in subsequent snapshots are stored as a single entry.

There is a constant overhead for normal ERC20 transfers due to the additional snapshot bookkeeping. This overhead is only significant for the first transfer that immediately follows a snapshot for a particular account. Subsequent transfers will have normal cost until the next snapshot, and so on.

_snapshot() → uint256 internal

Creates a new snapshot and returns its snapshot id.

Emits a Snapshot event that contains the same id.

_snapshot is internal and you have to decide how to expose it externally. Its usage may be restricted to a set of accounts, for example using AccessControl, or it may be open to the public.

While an open way of calling _snapshot is required for certain trust minimization mechanisms such as forking, you must consider that it can potentially be used by attackers in two ways.

First, it can be used to increase the cost of retrieval of values from snapshots, although it will grow logarithmically thus rendering this attack ineffective in the long term. Second, it can be used to target specific accounts and increase the cost of ERC20 transfers for them, in the ways specified in the Gas Costs section above.

We haven’t measured the actual numbers; if this is something you’re interested in please reach out to us.

balanceOfAt(address account, uint256 snapshotId) → uint256 public

Retrieves the balance of account at the time snapshotId was created.

totalSupplyAt(uint256 snapshotId) → uint256 public

Retrieves the total supply at the time snapshotId was created.

_beforeTokenTransfer(address from, address to, uint256 amount) internal

Snapshot(uint256 id) event

Emitted by _snapshot when a snapshot identified by id is created.

ERC20Pausable

ERC20 token with pausable token transfers, minting and burning.

Useful for scenarios such as preventing trades until the end of an evaluation period, or having an emergency switch for freezing all token transfers in the event of a large bug.

_beforeTokenTransfer(address from, address to, uint256 amount) internal

Requirements:

  • the contract must not be paused.

ERC20Burnable

Extension of ERC20 that allows token holders to destroy both their own tokens and those that they have an allowance for, in a way that can be recognized off-chain (via event analysis).

burn(uint256 amount) public

Destroys amount tokens from the caller.

burnFrom(address account, uint256 amount) public

Destroys amount tokens from account, deducting from the caller’s allowance.

Requirements:

  • the caller must have allowance for accounts's tokens of at least amount.

ERC20Capped

Extension of ERC20 that adds a cap to the supply of tokens.

constructor(uint256 cap_) internal

Sets the value of the cap. This value is immutable, it can only be set once during construction.

cap() → uint256 public

Returns the cap on the token’s total supply.

_beforeTokenTransfer(address from, address to, uint256 amount) internal

Requirements:

  • minted tokens must not cause the total supply to go over the cap.

Utilities

SafeERC20

Wrappers around ERC20 operations that throw on failure (when the token contract returns false). Tokens that return no value (and instead revert or throw on failure) are also supported, non-reverting calls are assumed to be successful. To use this library you can add a using SafeERC20 for IERC20; statement to your contract, which allows you to call the safe operations as token.safeTransfer(…​), etc.

safeTransfer(contract IERC20 token, address to, uint256 value) internal

safeTransferFrom(contract IERC20 token, address from, address to, uint256 value) internal

safeApprove(contract IERC20 token, address spender, uint256 value) internal

Deprecated. This function has issues similar to the ones found in IERC20.approve, and its usage is discouraged.

Whenever possible, use safeIncreaseAllowance and safeDecreaseAllowance instead.

safeIncreaseAllowance(contract IERC20 token, address spender, uint256 value) internal

safeDecreaseAllowance(contract IERC20 token, address spender, uint256 value) internal

TokenTimelock

A token holder contract that will allow a beneficiary to extract the tokens after a given release time.

Useful for simple vesting schedules like "advisors get all of their tokens after 1 year".

constructor(contract IERC20 token_, address beneficiary_, uint256 releaseTime_) public

token() → contract IERC20 public

beneficiary() → address public

releaseTime() → uint256 public

release() public