Contracts in this category should be considered unstable. They are as thoroughly reviewed as everything else in OpenZeppelin Contracts, but we have doubts about their API so we don’t commit to backwards compatibility. This means these contracts can receive breaking changes in a minor version, so you should pay special attention to the changelog when upgrading. For anything that is outside of this category you can read more about API Stability.

This page is incomplete. We’re working to improve it for the next release. Stay tuned!

ERC 20


This contract can be used to migrate an ERC20 token from one contract to another, where each token holder has to opt-in to the migration. To opt-in, users must approve for this contract the number of tokens they want to migrate. Once the allowance is set up, anyone can trigger the migration to the new token contract. In this way, token holders "turn in" their old balance and will be minted an equal amount in the new token. The new token contract must be mintable. For the precise interface refer to OpenZeppelin’s ERC20Mintable, but the only functions that are needed are MinterRole.isMinter and ERC20Mintable.mint. The migrator will check that it is a minter for the token. The balance from the legacy token will be transferred to the migrator, as it is migrated, and remain there forever. Although this contract can be used in many different scenarios, the main motivation was to provide a way to migrate ERC20 tokens into an upgradeable version of it using ZeppelinOS. To read more about how this can be done using this implementation, please follow the official documentation site of ZeppelinOS: https://docs.zeppelinos.org/docs/erc20_onboarding.html

Example of usage:

const migrator = await ERC20Migrator.new(legacyToken.address);
await newToken.addMinter(migrator.address);
await migrator.beginMigration(newToken.address);

constructor(contract IERC20 legacyToken) public

legacyToken() → contract IERC20 public

Returns the legacy token that is being migrated.

newToken() → contract IERC20 public

Returns the new token to which we are migrating.

beginMigration(contract ERC20Mintable newToken_) public

Begins the migration by setting which is the new token that will be minted. This contract must be a minter for the new token.

migrate(address account, uint256 amount) public

Transfers part of an account’s balance in the old token to this contract, and mints the same amount of new tokens for that account.

migrateAll(address account) public

Transfers all of an account’s allowed balance in the old token to this contract, and mints the same amount of new tokens for that account.


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 public

Creates a new snapshot and returns its snapshot id.

Emits a Snapshot event that contains the same id.

Since Snapshot is public, it can be called by anyone. However, there is some potential for abuse by attackers. We made this decision initially because we consider the risks to be low. In version 3.0 we have decided to make this function internal so that each project can decide whether to take on those risks or not. If you are stuck using version 2.x, it is possible to override this public function in a derived contract and add a require clause so that only one or a set of accounts can call it.

A public function could 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.

_transfer(address from, address to, uint256 value) internal

_mint(address account, uint256 value) internal

_burn(address account, uint256 value) internal

Snapshot(uint256 id) event

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


A token holder contract that can release its token balance gradually like a typical vesting scheme, with a cliff and vesting period. Optionally revocable by the owner.


constructor(address beneficiary, uint256 start, uint256 cliffDuration, uint256 duration, bool revocable) public

Creates a vesting contract that vests its balance of any ERC20 token to the beneficiary, gradually in a linear fashion until start + duration. By then all of the balance will have vested.

beneficiary() → address public

cliff() → uint256 public

start() → uint256 public

duration() → uint256 public

revocable() → bool public

released(address token) → uint256 public

revoked(address token) → bool public

release(contract IERC20 token) public

revoke(contract IERC20 token) public

TokensReleased(address token, uint256 amount) event

TokenVestingRevoked(address token) event



Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number of elements in a mapping, issuing ERC721 ids, or counting request ids.

Include with using Counters for Counters.Counter; Since it is not possible to overflow a 256 bit integer with increments of one, increment can skip the SafeMath overflow check, thereby saving gas. This does assume however correct usage, in that the underlying _value is never directly accessed.

current(struct Counters.Counter counter) → uint256 internal

increment(struct Counters.Counter counter) internal

decrement(struct Counters.Counter counter) internal


Signed math operations with safety checks that revert on error.

mul(int256 a, int256 b) → int256 internal

Multiplies two signed integers, reverts on overflow.

div(int256 a, int256 b) → int256 internal

Integer division of two signed integers truncating the quotient, reverts on division by zero.

sub(int256 a, int256 b) → int256 internal

Subtracts two signed integers, reverts on overflow.

add(int256 a, int256 b) → int256 internal

Adds two signed integers, reverts on overflow.

ERC 1046