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 are a few core contracts that implement the behavior specified in the EIP:
-
IERC20: the interface all ERC20 implementations should conform to. -
IERC20Metadata: the extended ERC20 interface including thename,symbolanddecimalsfunctions. -
ERC20: the implementation of the ERC20 interface, including thename,symbolanddecimalsoptional standard extension to the base interface.
Additionally there are multiple custom extensions, including:
-
ERC20Burnable: destruction of own tokens. -
ERC20Capped: enforcement of a cap to the total supply when minting tokens. -
ERC20Pausable: ability to pause token transfers. -
ERC20Permit: gasless approval of tokens (standardized as ERC2612). -
ERC20FlashMint: token level support for flash loans through the minting and burning of ephemeral tokens (standardized as ERC3156). -
ERC20Votes: support for voting and vote delegation. -
ERC20Wrapper: wrapper to create an ERC20 backed by another ERC20, with deposit and withdraw methods. Useful in conjunction withERC20Votes. -
ERC4626: tokenized vault that manages shares (represented as ERC20) that are backed by assets (another ERC20).
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.
Other utilities that support ERC20 assets can be found in codebase:
-
ERC20 tokens can be timelocked (held tokens for a beneficiary until a specified time) or vested (released following a given schedule) using a
VestingWallet.
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.
|
Core
IERC20
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
Interface of the ERC20 standard as defined in the EIP.
transfer(address to, uint256 value) → bool external
Moves a value amount of tokens from the caller’s account to to.
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 value) → bool external
Sets a value amount of tokens 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 from, address to, uint256 value) → bool external
Moves a value amount of tokens from from to to using the
allowance mechanism. value is then deducted from the caller’s
allowance.
Returns a boolean value indicating whether the operation succeeded.
Emits a transfer event.
Transfer(address indexed from, address indexed 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 indexed owner, address indexed 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.
IERC20Metadata
import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
Interface for the optional metadata functions from the ERC20 standard.
ERC20
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
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 detailed writeup see our guide How to implement supply mechanisms. |
The default value of decimals is 18. To change this, you should override
this function so it returns a different value.
We have followed general OpenZeppelin Contracts guidelines: functions revert
instead 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_) internal
All two 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 default value returned by this function, unless it’s overridden.
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 to, uint256 value) → bool public
See IERC20.transfer.
Requirements:
-
tocannot be the zero address. -
the caller must have a balance of at least
value.
allowance(address owner, address spender) → uint256 public
See IERC20.allowance.
approve(address spender, uint256 value) → bool public
See IERC20.approve.
If value is the maximum uint256, the allowance is not updated on
transferFrom. This is semantically equivalent to an infinite approval.
|
Requirements:
-
spendercannot be the zero address.
transferFrom(address from, address to, uint256 value) → 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.
Does not update the allowance if the current allowance
is the maximum uint256.
|
Requirements:
-
fromandtocannot be the zero address. -
frommust have a balance of at leastvalue. -
the caller must have allowance for
from's tokens of at leastvalue.
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:
-
spendercannot be the zero address.
decreaseAllowance(address spender, uint256 requestedDecrease) → 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:
-
spendercannot be the zero address. -
spendermust have allowance for the caller of at leastrequestedDecrease.
Although this function is designed to avoid double spending with Approval,
it can still be frontrunned, preventing any attempt of allowance reduction.
|
_transfer(address from, address to, uint256 value) internal
Moves a value amount of tokens from from to to.
This internal function is equivalent to transfer, and can be used to
e.g. implement automatic token fees, slashing mechanisms, etc.
Emits a transfer event.
This function is not virtual, _update should be overridden instead.
|
_update(address from, address to, uint256 value) internal
Transfers a value amount of tokens from from to to, or alternatively mints (or burns) if from (or to) is
the zero address. All customizations to transfers, mints, and burns should be done by overriding this function.
Emits a transfer event.
_mint(address account, uint256 value) internal
Creates a value amount of tokens and assigns them to account, by transferring it from address(0).
Relies on the _update mechanism
Emits a transfer event with from set to the zero address.
This function is not virtual, _update should be overridden instead.
|
_burn(address account, uint256 value) internal
Destroys a value amount of tokens from account, by transferring it to address(0).
Relies on the _update mechanism.
Emits a transfer event with to set to the zero address.
This function is not virtual, _update should be overridden instead
|
_approve(address owner, address spender, uint256 value) internal
Sets value 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:
-
ownercannot be the zero address. -
spendercannot be the zero address.
_approve(address owner, address spender, uint256 value, bool emitEvent) internal
Alternative version of _approve with an optional flag that can enable or disable the Approval event.
By default (when calling _approve) the flag is set to true. On the other hand, approval changes made by
_spendAllowance during the transferFrom operation set the flag to false. This saves gas by not emitting any
Approval event during transferFrom operations.
Anyone who wishes to continue emitting Approval events on the`transferFrom` operation can force the flag to true
using the following override:
function _approve(address owner, address spender, uint256 value, bool) internal virtual override {
super._approve(owner, spender, value, true);
}
Requirements are the same as _approve.
_spendAllowance(address owner, address spender, uint256 value) internal
Updates owner s allowance for spender based on spent value.
Does not update the allowance value in case of infinite allowance. Revert if not enough allowance is available.
Might emit an Approval event.
Extensions
ERC20Burnable
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
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 value) public
Destroys a value amount of 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 leastvalue.
ERC20Capped
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Capped.sol";
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.
_update(address from, address to, uint256 value) internal
See ERC20._update.
ERC20Pausable
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol";
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.
This contract does not include public pause and unpause functions. In
addition to inheriting this contract, you must define both functions, invoking the
Pausable._pause and Pausable._unpause internal functions, with appropriate
access control, e.g. using AccessControl or Ownable. Not doing so will
make the contract pause mechanism of the contract unreachable, and thus unusable.
|
_update(address from, address to, uint256 value) internal
See ERC20._update.
Requirements:
-
the contract must not be paused.
ERC20Permit
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";
Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in EIP-2612.
Adds the permit method, which can be used to change an account’s ERC20 allowance (see IERC20.allowance) by
presenting a message signed by the account. By not relying on , the token holder account doesn’t
need to send a transaction, and thus is not required to hold Ether at all.IERC20.approve
constructor(string name) internal
Initializes the EIP712 domain separator using the name parameter, and setting version to "1".
It’s a good idea to use the same name that is defined as the ERC20 token name.
permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public
See IERC20Permit.permit.
nonces(address owner) → uint256 public
See IERC20Permit.nonces.
ERC20Votes
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol";
Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound’s, and supports token supply up to 2224 - 1, while COMP is limited to 296 - 1.
| This contract does not provide interface compatibility with Compound’s COMP token. |
This extension keeps a history (checkpoints) of each account’s vote power. Vote power can be delegated either by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting power can be queried through the public accessors {getVotes} and {getPastVotes}.
By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked.
_update(address from, address to, uint256 value) internal
Move voting power when tokens are transferred.
Emits a IVotes.DelegateVotesChanged event.
ERC20Wrapper
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Wrapper.sol";
Extension of the ERC20 token contract to support token wrapping.
Users can deposit and withdraw "underlying tokens" and receive a matching number of "wrapped tokens". This is useful
in conjunction with other modules. For example, combining this wrapping mechanism with ERC20Votes will allow the
wrapping of an existing "basic" ERC20 into a governance token.
decimals() → uint8 public
See ERC20.decimals.
underlying() → contract IERC20 public
Returns the address of the underlying ERC-20 token that is being wrapped.
depositFor(address account, uint256 value) → bool public
Allow a user to deposit underlying tokens and mint the corresponding number of wrapped tokens.
ERC20FlashMint
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20FlashMint.sol";
Implementation of the ERC3156 Flash loans extension, as defined in ERC-3156.
Adds the flashLoan method, which provides flash loan support at the token
level. By default there is no fee, but this can be changed by overriding flashFee.
When this extension is used along with the ERC20Capped or ERC20Votes extensions,
maxFlashLoan will not correctly reflect the maximum that can be flash minted. We recommend
overriding maxFlashLoan so that it correctly reflects the supply cap.
|
maxFlashLoan(address token) → uint256 public
Returns the maximum amount of tokens available for loan.
flashFee(address token, uint256 value) → uint256 public
Returns the fee applied when doing flash loans. This function calls
the _flashFee function which returns the fee applied when doing flash
loans.
_flashFee(address token, uint256 value) → uint256 internal
Returns the fee applied when doing flash loans. By default this implementation has 0 fees. This function can be overloaded to make the flash loan mechanism deflationary.
_flashFeeReceiver() → address internal
Returns the receiver address of the flash fee. By default this implementation returns the address(0) which means the fee amount will be burnt. This function can be overloaded to change the fee receiver.
flashLoan(contract IERC3156FlashBorrower receiver, address token, uint256 value, bytes data) → bool public
Performs a flash loan. New tokens are minted and sent to the
receiver, who is required to implement the IERC3156FlashBorrower
interface. By the end of the flash loan, the receiver is expected to own
value + fee tokens and have them approved back to the token contract itself so
they can be burned.
ERC4626
import "@openzeppelin/contracts/token/ERC20/extensions/ERC4626.sol";
Implementation of the ERC4626 "Tokenized Vault Standard" as defined in EIP-4626.
This extension allows the minting and burning of "shares" (represented using the ERC20 inheritance) in exchange for
underlying "assets" through standardized deposit, mint, redeem and burn workflows. This contract extends
the ERC20 standard. Any additional extensions included along it would affect the "shares" token represented by this
contract and not the "assets" token which is an independent contract.
|
In empty (or nearly empty) ERC-4626 vaults, deposits are at high risk of being stolen through frontrunning with a "donation" to the vault that inflates the price of a share. This is variously known as a donation or inflation attack and is essentially a problem of slippage. Vault deployers can protect against this attack by making an initial deposit of a non-trivial amount of the asset, such that price manipulation becomes infeasible. Withdrawals may similarly be affected by slippage. Users can protect against this attack as well as unexpected slippage in general by verifying the amount received is as expected, using a wrapper that performs these checks such as ERC4626Router. Since v4.9, this implementation uses virtual assets and shares to mitigate that risk. The The drawback of this approach is that the virtual shares do capture (a very small) part of the value being accrued
to the vault. Also, if the vault experiences losses, the users try to exit the vault, the virtual shares and assets
will cause the first user to exit to experience reduced losses in detriment to the last users that will experience
bigger losses. Developers willing to revert back to the pre-v4.9 behavior just need to override the
To learn more, check out our ERC-4626 guide. |
constructor(contract IERC20 asset_) internal
Set the underlying asset contract. This must be an ERC20-compatible contract (ERC20 or ERC777).
decimals() → uint8 public
Decimals are computed by adding the decimal offset on top of the underlying asset’s decimals. This "original" value is cached during construction of the vault contract. If this read operation fails (e.g., the asset has not been created yet), a default of 18 is used to represent the underlying asset’s decimals.
asset() → address public
See IERC4626.asset.
totalAssets() → uint256 public
See IERC4626.totalAssets.
maxDeposit(address) → uint256 public
See IERC4626.maxDeposit.
maxMint(address) → uint256 public
See IERC4626.maxMint.
maxWithdraw(address owner) → uint256 public
See IERC4626.maxWithdraw.
maxRedeem(address owner) → uint256 public
See IERC4626.maxRedeem.
previewMint(uint256 shares) → uint256 public
See IERC4626.previewMint.
deposit(uint256 assets, address receiver) → uint256 public
See IERC4626.deposit.
mint(uint256 shares, address receiver) → uint256 public
See IERC4626.mint.
As opposed to deposit, minting is allowed even if the vault is in a state where the price of a share is zero.
In this case, the shares will be minted without requiring any assets to be deposited.
withdraw(uint256 assets, address receiver, address owner) → uint256 public
See IERC4626.withdraw.
redeem(uint256 shares, address receiver, address owner) → uint256 public
See IERC4626.redeem.
_convertToShares(uint256 assets, enum Math.Rounding rounding) → uint256 internal
Internal conversion function (from assets to shares) with support for rounding direction.
_convertToAssets(uint256 shares, enum Math.Rounding rounding) → uint256 internal
Internal conversion function (from shares to assets) with support for rounding direction.
_deposit(address caller, address receiver, uint256 assets, uint256 shares) internal
Deposit/mint common workflow.
Utilities
SafeERC20
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
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
Transfer value amount of token from the calling contract to to. If token returns no value,
non-reverting calls are assumed to be successful.
safeTransferFrom(contract IERC20 token, address from, address to, uint256 value) internal
Transfer value amount of token from from to to, spending the approval given by from to the
calling contract. If token returns no value, non-reverting calls are assumed to be successful.
safeIncreaseAllowance(contract IERC20 token, address spender, uint256 value) internal
Increase the calling contract’s allowance toward spender by value. If token returns no value,
non-reverting calls are assumed to be successful.
safeDecreaseAllowance(contract IERC20 token, address spender, uint256 requestedDecrease) internal
Decrease the calling contract’s allowance toward spender by requestedDecrease. If token returns no value,
non-reverting calls are assumed to be successful.
forceApprove(contract IERC20 token, address spender, uint256 value) internal
Set the calling contract’s allowance toward spender to value. If token returns no value,
non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
to be set to zero before setting it to a non-zero value, such as USDT.