ERC20
Smart contract ERC20 utilities and implementations
Outdated Version
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
,symbol
anddecimals
functions.ERC20
: the implementation of the ERC20 interface, including thename
,symbol
anddecimals
optional standard extension to the base interface.
Additionally there are multiple custom extensions, including:
ERC20Permit
: gasless approval of tokens (standardized as ERC2612).ERC20Burnable
: destruction of own tokens.ERC20Capped
: enforcement of a cap to the total supply when minting tokens.ERC20Pausable
: ability to pause token transfers.ERC20Snapshot
: efficient storage of past token balances to be later queried at any point in time.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.ERC20VotesComp
: support for voting and vote delegation (compatible with Compound’s token, with uint96 restrictions).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.TokenTimelock
: hold tokens for a beneficiary until a specified time.
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
Extensions
Presets
These contracts are preconfigured combinations of the above features. They can be used through inheritance or as models to copy and paste their source code.
Utilities
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 ERC1155._mint
.
For a generic mechanism see ERC20PresetMinterPauser
.
TIP: For a detailed writeup see our guide How to implement supply mechanisms.
The default value of ERC20.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 IERC20.Approval
event is emitted on calls to ERC20.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 ERC20.decreaseAllowance
and ERC20.increaseAllowance
functions have been added to mitigate the well-known issues around setting
allowances. See IERC20.approve
.
Functions
- constructor(name_, symbol_)
- name()
- symbol()
- decimals()
- totalSupply()
- balanceOf(account)
- transfer(to, amount)
- allowance(owner, spender)
- approve(spender, amount)
- transferFrom(from, to, amount)
- increaseAllowance(spender, addedValue)
- decreaseAllowance(spender, subtractedValue)
- _transfer(from, to, amount)
- _mint(account, amount)
- _burn(account, amount)
- _approve(owner, spender, amount)
- _spendAllowance(owner, spender, amount)
- _beforeTokenTransfer(from, to, amount)
- _afterTokenTransfer(from, to, amount)
IERC20Metadata
IERC20
constructor(string name_, string symbol_)
public
#Sets the values for Governor.name
and ERC20.symbol
.
All two 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 default value returned by this function, unless it's overridden.
NOTE: 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 amount) → bool
public
#See IERC20.transfer
.
Requirements:
to
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
.
NOTE: If amount
is the maximum uint256
, the allowance is not updated on
transferFrom
. This is semantically equivalent to an infinite approval.
Requirements:
spender
cannot be the zero address.
transferFrom(address from, address to, uint256 amount) → bool
public
#See IERC20.transferFrom
.
Emits an IERC20.Approval
event indicating the updated allowance. This is not
required by the EIP. See the note at the beginning of ERC20
.
NOTE: Does not update the allowance if the current allowance
is the maximum uint256
.
Requirements:
from
andto
cannot be the zero address.from
must have a balance of at leastamount
.- the caller must have allowance for
from
'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 ERC20.approve
that can be used as a mitigation for
problems described in IERC20.approve
.
Emits an IERC20.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 ERC20.approve
that can be used as a mitigation for
problems described in IERC20.approve
.
Emits an IERC20.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 from, address to, uint256 amount)
internal
#Moves amount
of tokens from from
to to
.
This internal function is equivalent to ERC20.transfer
, and can be used to
e.g. implement automatic token fees, slashing mechanisms, etc.
Emits a IERC20.Transfer
event.
Requirements:
from
cannot be the zero address.to
cannot be the zero address.from
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 IERC20.Transfer
event with from
set to the zero address.
Requirements:
account
cannot be the zero address.
_burn(address account, uint256 amount)
internal
#Destroys amount
tokens from account
, reducing the
total supply.
Emits a IERC20.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 IERC20.Approval
event.
Requirements:
owner
cannot be the zero address.spender
cannot be the zero address.
_spendAllowance(address owner, address spender, uint256 amount)
internal
#Updates owner
s allowance for spender
based on spent amount
.
Does not update the allowance amount in case of infinite allowance. Revert if not enough allowance is available.
Might emit an IERC20.Approval
event.
_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 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 xref:ROOT:extending-contracts#using-hooks[Using Hooks].
_afterTokenTransfer(address from, address to, uint256 amount)
internal
#Hook that is called after any transfer of tokens. This includes minting and burning.
Calling conditions:
- when
from
andto
are both non-zero,amount
offrom
's tokens has been transferred toto
. - when
from
is zero,amount
tokens have been minted forto
. - when
to
is zero,amount
offrom
's tokens have been burned. from
andto
are never both zero.
To learn more about hooks, head to xref:ROOT:extending-contracts#using-hooks[Using Hooks].
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
Interface of the ERC20 standard as defined in the EIP.
Functions
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 to, uint256 amount) → bool
external
#Moves amount
tokens from the caller's account to to
.
Returns a boolean value indicating whether the operation succeeded.
Emits a IERC20.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 ERC20.transferFrom
. This is
zero by default.
This value changes when ERC20.approve
or ERC20.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 IERC20.Approval
event.
transferFrom(address from, address to, uint256 amount) → bool
external
#Moves amount
tokens from from
to to
using the
allowance mechanism. amount
is then deducted from the caller's
allowance.
Returns a boolean value indicating whether the operation succeeded.
Emits a IERC20.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 ERC20.approve
. value
is the new allowance.
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).
Functions
ERC20
- name()
- symbol()
- decimals()
- totalSupply()
- balanceOf(account)
- transfer(to, amount)
- allowance(owner, spender)
- approve(spender, amount)
- transferFrom(from, to, amount)
- increaseAllowance(spender, addedValue)
- decreaseAllowance(spender, subtractedValue)
- _transfer(from, to, amount)
- _mint(account, amount)
- _burn(account, amount)
- _approve(owner, spender, amount)
- _spendAllowance(owner, spender, amount)
- _beforeTokenTransfer(from, to, amount)
- _afterTokenTransfer(from, to, amount)
IERC20Metadata
IERC20
burn(uint256 amount)
public
#Destroys amount
tokens from the caller.
See ERC20._burn
.
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
.
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Capped.sol";
Extension of ERC20
that adds a cap to the supply of tokens.
Functions
ERC20
- name()
- symbol()
- decimals()
- totalSupply()
- balanceOf(account)
- transfer(to, amount)
- allowance(owner, spender)
- approve(spender, amount)
- transferFrom(from, to, amount)
- increaseAllowance(spender, addedValue)
- decreaseAllowance(spender, subtractedValue)
- _transfer(from, to, amount)
- _burn(account, amount)
- _approve(owner, spender, amount)
- _spendAllowance(owner, spender, amount)
- _beforeTokenTransfer(from, to, amount)
- _afterTokenTransfer(from, to, amount)
IERC20Metadata
IERC20
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.
_mint(address account, uint256 amount)
internal
#See ERC20._mint
.
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20FlashMint.sol";
Implementation of the ERC3156 Flash loans extension, as defined in ERC-3156.
Adds the IERC3156FlashLender.flashLoan
method, which provides flash loan support at the token
level. By default there is no fee, but this can be changed by overriding IERC3156FlashLender.flashFee
.
Available since v4.1.
Functions
- maxFlashLoan(token)
- flashFee(token, amount)
- _flashFee(token, amount)
- _flashFeeReceiver()
- flashLoan(receiver, token, amount, data)
IERC3156FlashLender
ERC20
- name()
- symbol()
- decimals()
- totalSupply()
- balanceOf(account)
- transfer(to, amount)
- allowance(owner, spender)
- approve(spender, amount)
- transferFrom(from, to, amount)
- increaseAllowance(spender, addedValue)
- decreaseAllowance(spender, subtractedValue)
- _transfer(from, to, amount)
- _mint(account, amount)
- _burn(account, amount)
- _approve(owner, spender, amount)
- _spendAllowance(owner, spender, amount)
- _beforeTokenTransfer(from, to, amount)
- _afterTokenTransfer(from, to, amount)
IERC20Metadata
IERC20
Events
maxFlashLoan(address token) → uint256
public
#Returns the maximum amount of tokens available for loan.
flashFee(address token, uint256 amount) → uint256
public
#Returns the fee applied when doing flash loans. This function calls
the ERC20FlashMint._flashFee
function which returns the fee applied when doing flash
loans.
_flashFee(address token, uint256 amount) → 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 amount, 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
amount + fee tokens and have them approved back to the token contract itself so
they can be burned.
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 unpausable.
Functions
Pausable
ERC20
- name()
- symbol()
- decimals()
- totalSupply()
- balanceOf(account)
- transfer(to, amount)
- allowance(owner, spender)
- approve(spender, amount)
- transferFrom(from, to, amount)
- increaseAllowance(spender, addedValue)
- decreaseAllowance(spender, subtractedValue)
- _transfer(from, to, amount)
- _mint(account, amount)
- _burn(account, amount)
- _approve(owner, spender, amount)
- _spendAllowance(owner, spender, amount)
- _afterTokenTransfer(from, to, amount)
IERC20Metadata
IERC20
Events
_beforeTokenTransfer(address from, address to, uint256 amount)
internal
#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 ERC20Permit.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 [
IERC20.approve](#IERC20-approve-address-uint256-)
, the token holder account doesn't
need to send a transaction, and thus is not required to hold Ether at all.
Available since v3.4.
Functions
- constructor(name)
- permit(owner, spender, value, deadline, v, r, s)
- nonces(owner)
- DOMAIN_SEPARATOR()
- _useNonce(owner)
EIP712
IERC5267
IERC20Permit
ERC20
- name()
- symbol()
- decimals()
- totalSupply()
- balanceOf(account)
- transfer(to, amount)
- allowance(owner, spender)
- approve(spender, amount)
- transferFrom(from, to, amount)
- increaseAllowance(spender, addedValue)
- decreaseAllowance(spender, subtractedValue)
- _transfer(from, to, amount)
- _mint(account, amount)
- _burn(account, amount)
- _approve(owner, spender, amount)
- _spendAllowance(owner, spender, amount)
- _beforeTokenTransfer(from, to, amount)
- _afterTokenTransfer(from, to, amount)
IERC20Metadata
IERC20
Events
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
#Sets value
as the allowance of spender
over owner
's tokens,
given owner
's signed approval.
The same issues IERC20.approve
has related to transaction
ordering also apply here.
Emits an IERC20.Approval
event.
Requirements:
spender
cannot be the zero address.deadline
must be a timestamp in the future.v
,r
ands
must be a validsecp256k1
signature fromowner
over the EIP712-formatted function arguments.- the signature must use
owner
's current nonce (seeVotes.nonces
).
For more information on the signature format, see the relevant EIP section.
CAUTION: See Security Considerations above.
nonces(address owner) → uint256
public
#Returns the current nonce for owner
. This value must be
included whenever a signature is generated for ERC20Permit.permit
.
Every successful call to ERC20Permit.permit
increases owner
's nonce by one. This
prevents a signature from being used multiple times.
DOMAIN_SEPARATOR() → bytes32
external
#Returns the domain separator used in the encoding of the signature for ERC20Permit.permit
, as defined by EIP712
.
_useNonce(address owner) → uint256 current
internal
#"Consume a nonce": return the current value and increment.
Available since v4.1.
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Snapshot.sol";
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 ERC20Snapshot._snapshot
function, which will emit the ERC20Snapshot.Snapshot
event and return a
snapshot id. To get the total supply at the time of a snapshot, call the function ERC20Snapshot.totalSupplyAt
with the snapshot
id. To get the balance of an account at the time of a snapshot, call the ERC20Snapshot.balanceOfAt
function with the snapshot id
and the account address.
NOTE: Snapshot policy can be customized by overriding the ERC20Snapshot._getCurrentSnapshotId
method. For example, having it
return block.number
will trigger the creation of snapshot at the beginning of each new block. When overriding this
function, be careful about the monotonicity of its result. Non-monotonic snapshot ids will break the contract.
Implementing snapshots for every block using this method will incur significant gas costs. For a gas-efficient
alternative consider ERC20Votes
.
==== 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.
Functions
- _snapshot()
- _getCurrentSnapshotId()
- balanceOfAt(account, snapshotId)
- totalSupplyAt(snapshotId)
- _beforeTokenTransfer(from, to, amount)
ERC20
- name()
- symbol()
- decimals()
- totalSupply()
- balanceOf(account)
- transfer(to, amount)
- allowance(owner, spender)
- approve(spender, amount)
- transferFrom(from, to, amount)
- increaseAllowance(spender, addedValue)
- decreaseAllowance(spender, subtractedValue)
- _transfer(from, to, amount)
- _mint(account, amount)
- _burn(account, amount)
- _approve(owner, spender, amount)
- _spendAllowance(owner, spender, amount)
- _afterTokenTransfer(from, to, amount)
IERC20Metadata
IERC20
Events
_snapshot() → uint256
internal
#Creates a new snapshot and returns its snapshot id.
Emits a ERC20Snapshot.Snapshot
event that contains the same id.
ERC20Snapshot._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.
[WARNING]
While an open way of calling ERC20Snapshot._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.
_getCurrentSnapshotId() → uint256
internal
#Get the current snapshotId
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
#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 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 xref:ROOT:extending-contracts#using-hooks[Using Hooks].
Snapshot(uint256 id)
event
#Emitted by ERC20Snapshot._snapshot
when a snapshot identified by id
is created.
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 2^224^ - 1, while COMP is limited to 2^96^ - 1.
NOTE: If exact COMP compatibility is required, use the ERC20VotesComp
variant of this module.
This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either
by calling the IVotes.delegate
function directly, or by providing a signature to be used with IVotes.delegateBySig
. Voting
power can be queried through the public accessors Governor.getVotes
and IVotes.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.
Available since v4.2.
Functions
- clock()
- CLOCK_MODE()
- checkpoints(account, pos)
- numCheckpoints(account)
- delegates(account)
- getVotes(account)
- getPastVotes(account, timepoint)
- getPastTotalSupply(timepoint)
- delegate(delegatee)
- delegateBySig(delegatee, nonce, expiry, v, r, s)
- _maxSupply()
- _mint(account, amount)
- _burn(account, amount)
- _afterTokenTransfer(from, to, amount)
- _delegate(delegator, delegatee)
IERC5805
IVotes
IERC6372
ERC20Permit
EIP712
IERC5267
IERC20Permit
ERC20
- name()
- symbol()
- decimals()
- totalSupply()
- balanceOf(account)
- transfer(to, amount)
- allowance(owner, spender)
- approve(spender, amount)
- transferFrom(from, to, amount)
- increaseAllowance(spender, addedValue)
- decreaseAllowance(spender, subtractedValue)
- _transfer(from, to, amount)
- _approve(owner, spender, amount)
- _spendAllowance(owner, spender, amount)
- _beforeTokenTransfer(from, to, amount)
IERC20Metadata
IERC20
Events
clock() → uint48
public
#Clock used for flagging checkpoints. Can be overridden to implement timestamp based checkpoints (and voting).
CLOCK_MODE() → string
public
#Description of the clock
checkpoints(address account, uint32 pos) → struct ERC20Votes.Checkpoint
public
#Get the pos
-th checkpoint for account
.
numCheckpoints(address account) → uint32
public
#Get number of checkpoints for account
.
delegates(address account) → address
public
#Get the address account
is currently delegating to.
getVotes(address account) → uint256
public
#Gets the current votes balance for account
getPastVotes(address account, uint256 timepoint) → uint256
public
#Retrieve the number of votes for account
at the end of timepoint
.
Requirements:
timepoint
must be in the past
getPastTotalSupply(uint256 timepoint) → uint256
public
#Retrieve the totalSupply
at the end of timepoint
. Note, this value is the sum of all balances.
It is NOT the sum of all the delegated votes!
Requirements:
timepoint
must be in the past
delegate(address delegatee)
public
#Delegate votes from the sender to delegatee
.
delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s)
public
#Delegates votes from signer to delegatee
_maxSupply() → uint224
internal
#Maximum token supply. Defaults to type(uint224).max
(2^224^ - 1).
_mint(address account, uint256 amount)
internal
#Snapshots the totalSupply after it has been increased.
_burn(address account, uint256 amount)
internal
#Snapshots the totalSupply after it has been decreased.
_afterTokenTransfer(address from, address to, uint256 amount)
internal
#Move voting power when tokens are transferred.
Emits a IVotes.DelegateVotesChanged
event.
_delegate(address delegator, address delegatee)
internal
#Change delegation for delegator
to delegatee
.
Emits events IVotes.DelegateChanged
and IVotes.DelegateVotesChanged
.
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20VotesComp.sol";
Extension of ERC20 to support Compound's voting and delegation. This version exactly matches Compound's interface, with the drawback of only supporting supply up to (2^96^ - 1).
NOTE: You should use this contract if you need exact compatibility with COMP (for example in order to use your token
with Governor Alpha or Bravo) and if you are sure the supply cap of 2^96^ is enough for you. Otherwise, use the
ERC20Votes
variant of this module.
This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either
by calling the IVotes.delegate
function directly, or by providing a signature to be used with IVotes.delegateBySig
. Voting
power can be queried through the public accessors ERC20VotesComp.getCurrentVotes
and ERC20VotesComp.getPriorVotes
.
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.
Available since v4.2.
Functions
ERC20Votes
- clock()
- CLOCK_MODE()
- checkpoints(account, pos)
- numCheckpoints(account)
- delegates(account)
- getVotes(account)
- getPastVotes(account, timepoint)
- getPastTotalSupply(timepoint)
- delegate(delegatee)
- delegateBySig(delegatee, nonce, expiry, v, r, s)
- _mint(account, amount)
- _burn(account, amount)
- _afterTokenTransfer(from, to, amount)
- _delegate(delegator, delegatee)
IERC5805
IVotes
IERC6372
ERC20Permit
EIP712
IERC5267
IERC20Permit
ERC20
- name()
- symbol()
- decimals()
- totalSupply()
- balanceOf(account)
- transfer(to, amount)
- allowance(owner, spender)
- approve(spender, amount)
- transferFrom(from, to, amount)
- increaseAllowance(spender, addedValue)
- decreaseAllowance(spender, subtractedValue)
- _transfer(from, to, amount)
- _approve(owner, spender, amount)
- _spendAllowance(owner, spender, amount)
- _beforeTokenTransfer(from, to, amount)
IERC20Metadata
IERC20
Events
getCurrentVotes(address account) → uint96
external
#Comp version of the Governor.getVotes
accessor, with uint96
return type.
getPriorVotes(address account, uint256 blockNumber) → uint96
external
#Comp version of the IVotes.getPastVotes
accessor, with uint96
return type.
_maxSupply() → uint224
internal
#Maximum token supply. Reduced to type(uint96).max
(2^96^ - 1) to fit COMP interface.
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.
Available since v4.2.
Functions
- constructor(underlyingToken)
- decimals()
- underlying()
- depositFor(account, amount)
- withdrawTo(account, amount)
- _recover(account)
ERC20
- name()
- symbol()
- totalSupply()
- balanceOf(account)
- transfer(to, amount)
- allowance(owner, spender)
- approve(spender, amount)
- transferFrom(from, to, amount)
- increaseAllowance(spender, addedValue)
- decreaseAllowance(spender, subtractedValue)
- _transfer(from, to, amount)
- _mint(account, amount)
- _burn(account, amount)
- _approve(owner, spender, amount)
- _spendAllowance(owner, spender, amount)
- _beforeTokenTransfer(from, to, amount)
- _afterTokenTransfer(from, to, amount)
IERC20Metadata
IERC20
constructor(contract IERC20 underlyingToken)
internal
#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 amount) → bool
public
#Allow a user to deposit underlying tokens and mint the corresponding number of wrapped tokens.
withdrawTo(address account, uint256 amount) → bool
public
#Allow a user to burn a number of wrapped tokens and withdraw the corresponding number of underlying tokens.
_recover(address account) → uint256
internal
#Mint wrapped token to cover any underlyingTokens that would have been transferred by mistake. Internal function that can be exposed with access control if desired.
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 IERC4626.deposit
, IERC4626.mint
, IERC4626.redeem
and ERC1155Burnable.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.
[CAUTION]
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 _decimalsOffset()
corresponds to an offset in the decimal representation between the underlying asset's decimals and the vault
decimals. This offset also determines the rate of virtual shares to virtual assets in the vault, which itself
determines the initial exchange rate. While not fully preventing the attack, analysis shows that the default offset
(0) makes it non-profitable, as a result of the value being captured by the virtual shares (out of the attacker's
donation) matching the attacker's expected gains. With a larger offset, the attack becomes orders of magnitude more
expensive than it is profitable. More details about the underlying math can be found
xref:erc4626#inflation-attack[here].
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
_convertToShares
and _convertToAssets
functions.
To learn more, check out our xref:ROOT:erc4626[ERC-4626 guide].
Available since v4.7.
Functions
- constructor(asset_)
- decimals()
- asset()
- totalAssets()
- convertToShares(assets)
- convertToAssets(shares)
- maxDeposit()
- maxMint()
- maxWithdraw(owner)
- maxRedeem(owner)
- previewDeposit(assets)
- previewMint(shares)
- previewWithdraw(assets)
- previewRedeem(shares)
- deposit(assets, receiver)
- mint(shares, receiver)
- withdraw(assets, receiver, owner)
- redeem(shares, receiver, owner)
- _convertToShares(assets, rounding)
- _convertToAssets(shares, rounding)
- _deposit(caller, receiver, assets, shares)
- _withdraw(caller, receiver, owner, assets, shares)
- _decimalsOffset()
IERC4626
ERC20
- name()
- symbol()
- totalSupply()
- balanceOf(account)
- transfer(to, amount)
- allowance(owner, spender)
- approve(spender, amount)
- transferFrom(from, to, amount)
- increaseAllowance(spender, addedValue)
- decreaseAllowance(spender, subtractedValue)
- _transfer(from, to, amount)
- _mint(account, amount)
- _burn(account, amount)
- _approve(owner, spender, amount)
- _spendAllowance(owner, spender, amount)
- _beforeTokenTransfer(from, to, amount)
- _afterTokenTransfer(from, to, amount)
IERC20Metadata
IERC20
Events
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
.
convertToShares(uint256 assets) → uint256
public
#convertToAssets(uint256 shares) → uint256
public
#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
.
previewDeposit(uint256 assets) → uint256
public
#previewMint(uint256 shares) → uint256
public
#See IERC4626.previewMint
.
previewWithdraw(uint256 assets) → uint256
public
#previewRedeem(uint256 shares) → uint256
public
#deposit(uint256 assets, address receiver) → uint256
public
#See IERC4626.deposit
.
mint(uint256 shares, address receiver) → uint256
public
#See IERC4626.mint
.
As opposed to IERC4626.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.
_withdraw(address caller, address receiver, address owner, uint256 assets, uint256 shares)
internal
#Withdraw/redeem common workflow.
_decimalsOffset() → uint8
internal
#import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
Interface for the optional metadata functions from the ERC20 standard.
Available since v4.1.
Functions
name() → string
external
#Returns the name of the token.
symbol() → string
external
#Returns the symbol of the token.
decimals() → uint8
external
#Returns the decimals places of the token.
import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol";
Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in EIP-2612.
Adds the ERC20Permit.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 IERC20.approve
, the token holder account doesn't
need to send a transaction, and thus is not required to hold Ether at all.
==== Security Considerations
There are two important considerations concerning the use of permit
. The first is that a valid permit signature
expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be
considered as an intention to spend the allowance in any specific way. The second is that because permits have
built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should
take this into consideration and allow a permit
call to fail. Combining these two aspects, a pattern that may be
generally recommended is:
function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {
try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}
doThing(..., value);
}
function doThing(..., uint256 value) public {
token.safeTransferFrom(msg.sender, address(this), value);
...
}
Observe that: 1) msg.sender
is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of
try/catch
allows the permit to fail and makes the code tolerant to frontrunning. (See also
SafeERC20.safeTransferFrom
).
Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so contracts should have entry points that don't rely on permit.
permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)
external
#Sets value
as the allowance of spender
over owner
's tokens,
given owner
's signed approval.
The same issues IERC20.approve
has related to transaction
ordering also apply here.
Emits an IERC20.Approval
event.
Requirements:
spender
cannot be the zero address.deadline
must be a timestamp in the future.v
,r
ands
must be a validsecp256k1
signature fromowner
over the EIP712-formatted function arguments.- the signature must use
owner
's current nonce (seeVotes.nonces
).
For more information on the signature format, see the relevant EIP section.
CAUTION: See Security Considerations above.
nonces(address owner) → uint256
external
#Returns the current nonce for owner
. This value must be
included whenever a signature is generated for ERC20Permit.permit
.
Every successful call to ERC20Permit.permit
increases owner
's nonce by one. This
prevents a signature from being used multiple times.
DOMAIN_SEPARATOR() → bytes32
external
#Returns the domain separator used in the encoding of the signature for ERC20Permit.permit
, as defined by EIP712
.
import "@openzeppelin/contracts/token/ERC20/presets/ERC20PresetFixedSupply.sol";
ERC20
token, including:
- Preminted initial supply
- Ability for holders to burn (destroy) their tokens
- No access control mechanism (for minting/pausing) and hence no governance
This contract uses ERC20Burnable
to include burn capabilities - head to
its documentation for details.
Available since v3.4.
Deprecated in favor of Contracts Wizard.
Functions
ERC20Burnable
ERC20
- name()
- symbol()
- decimals()
- totalSupply()
- balanceOf(account)
- transfer(to, amount)
- allowance(owner, spender)
- approve(spender, amount)
- transferFrom(from, to, amount)
- increaseAllowance(spender, addedValue)
- decreaseAllowance(spender, subtractedValue)
- _transfer(from, to, amount)
- _mint(account, amount)
- _burn(account, amount)
- _approve(owner, spender, amount)
- _spendAllowance(owner, spender, amount)
- _beforeTokenTransfer(from, to, amount)
- _afterTokenTransfer(from, to, amount)
IERC20Metadata
IERC20
Events
constructor(string name, string symbol, uint256 initialSupply, address owner)
public
#Mints initialSupply
amount of token and transfers them to owner
.
See ERC20.constructor
.
import "@openzeppelin/contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol";
ERC20
token, including:
- ability for holders to burn (destroy) their tokens
- a minter role that allows for token minting (creation)
- a pauser role that allows to stop all token transfers
This contract uses AccessControl
to lock permissioned functions using the
different roles - head to its documentation for details.
The account that deploys the contract will be granted the minter and pauser roles, as well as the default admin role, which will let it grant both minter and pauser roles to other accounts.
Deprecated in favor of Contracts Wizard.
Functions
- constructor(name, symbol)
- mint(to, amount)
- pause()
- unpause()
- _beforeTokenTransfer(from, to, amount)
- MINTER_ROLE()
- PAUSER_ROLE()
ERC20Pausable
Pausable
ERC20Burnable
ERC20
- name()
- symbol()
- decimals()
- totalSupply()
- balanceOf(account)
- transfer(to, amount)
- allowance(owner, spender)
- approve(spender, amount)
- transferFrom(from, to, amount)
- increaseAllowance(spender, addedValue)
- decreaseAllowance(spender, subtractedValue)
- _transfer(from, to, amount)
- _mint(account, amount)
- _burn(account, amount)
- _approve(owner, spender, amount)
- _spendAllowance(owner, spender, amount)
- _afterTokenTransfer(from, to, amount)
IERC20Metadata
IERC20
AccessControlEnumerable
- supportsInterface(interfaceId)
- getRoleMember(role, index)
- getRoleMemberCount(role)
- _grantRole(role, account)
- _revokeRole(role, account)
AccessControl
- hasRole(role, account)
- _checkRole(role)
- _checkRole(role, account)
- getRoleAdmin(role)
- grantRole(role, account)
- revokeRole(role, account)
- renounceRole(role, account)
- _setupRole(role, account)
- _setRoleAdmin(role, adminRole)
- DEFAULT_ADMIN_ROLE()
ERC165
IERC165
IAccessControlEnumerable
IAccessControl
Events
constructor(string name, string symbol)
public
#Grants DEFAULT_ADMIN_ROLE
, MINTER_ROLE
and PAUSER_ROLE
to the
account that deploys the contract.
See ERC20.constructor
.
mint(address to, uint256 amount)
public
#Creates amount
new tokens for to
.
See ERC20._mint
.
Requirements:
- the caller must have the
MINTER_ROLE
.
pause()
public
#Pauses all token transfers.
See ERC20Pausable
and Pausable._pause
.
Requirements:
- the caller must have the
PAUSER_ROLE
.
unpause()
public
#Unpauses all token transfers.
See ERC20Pausable
and Pausable._unpause
.
Requirements:
- the caller must have the
PAUSER_ROLE
.
_beforeTokenTransfer(address from, address to, uint256 amount)
internal
#MINTER_ROLE() → bytes32
public
#PAUSER_ROLE() → bytes32
public
#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.
Functions
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.
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 SafeERC20.safeIncreaseAllowance
and
SafeERC20.safeDecreaseAllowance
instead.
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 value)
internal
#Decrease the calling contract's allowance toward spender
by value
. 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.
safePermit(contract IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)
internal
#Use a ERC-2612 signature to set the owner
approval toward spender
on token
.
Revert on invalid signature.
import "@openzeppelin/contracts/token/ERC20/utils/TokenTimelock.sol";
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".
Functions
constructor(contract IERC20 token_, address beneficiary_, uint256 releaseTime_)
public
#Deploys a timelock instance that is able to hold the token specified, and will only release it to
beneficiary_
when PaymentSplitter.release
is invoked after releaseTime_
. The release time is specified as a Unix timestamp
(in seconds).
token() → contract IERC20
public
#Returns the token being held.
beneficiary() → address
public
#Returns the beneficiary that will receive the tokens.
releaseTime() → uint256
public
#Returns the time when the tokens are released in seconds since Unix epoch (i.e. Unix timestamp).
release()
public
#Transfers tokens held by the timelock to the beneficiary. Will only succeed if invoked after the release time.