ERC 20
This document is better viewed at https://docs.openzeppelin.com/contracts/api/token/erc20 |
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:
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.
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
To select a different value for decimals
, use _setupDecimals
.
All three of these values are immutable: they can only be set once during construction.
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
See IERC20.totalSupply
.
balanceOf(address account) → uint256
public
See IERC20.balanceOf
.
transfer(address recipient, uint256 amount) → bool
public
See IERC20.Transfer
.
Requirements:
-
recipient
cannot be the zero address. -
the caller must have a balance of at least
amount
.
allowance(address owner, address spender) → uint256
public
See IERC20.allowance
.
approve(address spender, uint256 amount) → bool
public
See IERC20.approve
.
Requirements:
-
spender
cannot be the zero address.
transferFrom(address sender, address recipient, uint256 amount) → bool
public
See IERC20.transferFrom
.
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
andrecipient
cannot be the zero address. -
sender
must have a balance of at leastamount
. -
the caller must have allowance for
sender
's tokens of at leastamount
.
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 leastsubtractedValue
.
_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 leastamount
.
_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 leastamount
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
andto
are both non-zero,amount
offrom
's tokens will be to transferred toto
. -
when
from
is zero,amount
tokens will be minted forto
. -
when
to
is zero,amount
offrom
's tokens will be burned. -
from
andto
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 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.
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.
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).
burnFrom(address account, uint256 amount)
public
Destroys amount
tokens from account
, deducting from the caller’s
allowance.
See ERC20._burn
and ERC20.allowance
.
Requirements:
-
the caller must have allowance for
accounts
's tokens of at leastamount
.
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.
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.
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.