OpenZeppelin Contracts v3.0 final release candidate

We’re excited to announce the last release candidate of OpenZeppelin Contracts v3.0 :sparkles:

This means we’re close the v3.0 final release, the main goal in our Q1 roadmap. Stay tuned for our upcoming plans for the next quarter!

Among other things, this release features the migration to Solidity v0.6, as well as a revamped access control system, streamlined token contracts, and new libraries for enumerable mappings.

To install the release candidate, run:

npm install --save-dev @openzeppelin/contracts@next

What’s New

  • All contracts were migrated to Solidity v0.6.
  • AccessControl was designed with help from the community and has replaced Roles contracts (such as MinterRole and PauserRole), which were removed.
  • Crowdsales were removed: we’ll continue to provide support for security issues on the v2.5 release, but will not bring them over to v3.0.
  • We’ve added hooks, a new feature of the library that will make extending it easier than ever. Read more below!
  • ERC20 and ERC721 were simplified and streamlined, including all optional parts of the standard by default, and simplifying some of our own custom extensions.
  • Support for better mapping types that let you efficiently iterate over all keys using EnumerableSet and EnumerableMap
  • Many, many breaking changes with small improvements. We’ve also moved some contracts around (e.g. Ownable is now found under the access directory) and deleted some that were not being used. Head to our changelog to see the full list.

Compiling v0.6 Contracts

You can use the OpenZeppelin CLI to compile any Solidity v0.6 contract: just update the pragma statement on your source code and you’ll be good to go!

pragma solidity ^0.6.0;

Note that you will need to use the recent v2.7 release of the CLI to have Solidity v0.6 support. For detailed information about using the CLI compiler, head to its documenation.

Revamped Access Control

One of our most widely-used contracts is Ownable, providing a simple authorization scheme. However, this fell short in complex systems with multiple permissions.

The v3.0 release introduces AccessControl, a one-stop-shop for all authorization needs. It lets you easily define multiple roles with different permissions, as well as which accounts are allowed to grant and revoke each role. It also boosts transparency by enabling enumeration of all privileged accounts in a system.

AccessControl was designed with a security-first mindset, receiving input from a wide array of users and incorporating best practices in the field. Head to our Access Control guide for more information!

Deploy Ready Contracts

OpenZeppelin Contracts shine when as a library to develop custom smart contracts, but that’s not all they can do! We’ve added Deploy Ready variants for ERC20 and ERC721 tokens: contracts you can deploy as-is to get your tokens out there quickly without having to write any Solidity code. Check out their documentation!

Migrating From OpenZeppelin Contracts v2.5

Other than the contract removals mentioned above, the library API is pretty much the same as in the v2.5 release, so the migration should be straightforward. For instructions on how to update your Solidity v0.5 contracts to v0.6, refer to the official documentation.

If you’re using the ERC20 or ERC721 tokens however, you’ll have to remove all references to optional extensions (ERC20Detailed, ERC721Enumerable, etc.) - these have been included in the base contracts.

The other exception to this are contracts that use the Gas Station Network (GSN): if you’re inheriting from GSNRecipient or one of the other GSN contracts, you’ll need to add the following snippet to your contracts:

function _msgSender() internal view override(Context, GSNRecipient) returns (address payable) {
    return GSNRecipient._msgSender();

function _msgData() internal view override(Context, GSNRecipient) returns (bytes memory) {
    return GSNRecipient._msgData();

Using Hooks

To improve library flexibility, we’re introducing hooks: functions that are called at specific moments during a contract’s operation that you can use to hook into the internals and extend as you wish.

For example, the _beforeTokenTransfer hook in ERC20, ERC721 and ERC777 makes it very easy to add additional checks or actions to execute whenever tokens are transferred, minted or burned, regardless of what prompted it.

// Tokens can only be transferred, minted or burned if the contract is not paused
contract ERC20Pausable is ERC20, Pausable {
    function _beforeTokenTransfer(address from, address to, uint256 amount) 
        internal virtual override 
        super._beforeTokenTransfer(from, to, amount);

        require(!paused(), "ERC20Pausable: token transfer while paused");

As an additional benefit, using hooks will allow you to side-step some of the edge-cases product of the new override keyword.

Next Steps

As with all release candidates, the final release will follow one or two weeks later. This is so that community members get a chance to share their thoughts on the upcoming changes before they are made final.

So give this release candidate a try, upgrade your project to Solidity v0.6, and tell us what you think!

1 Like

Awesome work @nventuro :pray:


Is tokenUri going to be made virtual in 3.0 ?

This would allow automatic token URI

Deploy Ready ERC721

It would be great to have a deploy ready ERC721 that includes meta data (with automatic token URI

I would :heart: to hear from the community on what they would like to see in a deploy ready ERC721.

Something like the following:


pragma solidity ^0.6.0;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
import "@openzeppelin/contracts/utils/Counters.sol";

contract MyERC721 is Context, AccessControl, ERC721 {
    bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
    bytes32 public constant BASEURI_SETTER_ROLE = keccak256(

    using Counters for Counters.Counter;
    Counters.Counter private _tokenIds;

    constructor(string memory name, string memory symbol, string memory baseURI) public ERC721(name, symbol) {
        _setupRole(DEFAULT_ADMIN_ROLE, _msgSender());

        _setupRole(MINTER_ROLE, _msgSender());
        _setupRole(BASEURI_SETTER_ROLE, _msgSender());


    function mint(address to) public {
            hasRole(MINTER_ROLE, msg.sender),
            "MyERC721: account does not have minter role"

        uint256 newTokenId = _tokenIds.current();
        _mint(to, newTokenId);

    function tokenURI(uint256 tokenId) public view override returns (string memory) {
        require(_exists(tokenId), "MyERC721: URI query for nonexistent token");

        return string(abi.encodePacked(baseURI(), Strings.fromUint256(tokenId)));

    function setBaseURI(string memory baseURI) public {
            hasRole(BASEURI_SETTER_ROLE, msg.sender),
            "MyERC721: account does not have setter role"

Deploy Ready Fixed Supply ERC20

Should there also be a simple ERC20 with a fixed supply in Deploy Ready?
Equivalent of SimpleToken in Contracts 2.5:

Hi mate.
Any reason why the crowdsale contract was removed?

Are there intentions to replace it by any other similar contract?

Thank you.

1 Like

Hi @Chxpz,

Welcome to the community :wave:

Please see the documentation on why Crowdsales were removed:

1 Like

Solidity 0.6.0 became more explicit on functions overriding, requires specification linearity of multiple inheritance. This broken everything.

1 Like

Hi team! I also noticed the Pausable contract is not available anymore in this new release. I have to implement a Pausable smart contract in 0.6 which path do you suggest to follow? Thanks!

1 Like

Pausable is still available: it was moved into the utils directory.

1 Like

OpenZeppelin Contracts v3.0 is released :sparkles: