OpenZeppelin Contracts 5.0 is the first major release of the Solidity library since 2021, allowing the team to modernize the library and improve efficiency while keeping state-of-the-art security practices.
As the most widely adopted Solidity library for Ethereum and other EVM blockchains, the 5.0 version of OpenZeppelin Contracts remains steadfast in its commitment to equipping developers with the tools necessary to build secure, efficient, and future-proof smart contract systems. With the release of version 5.0, we believe this commitment is stronger than ever.
- Modern best practices work out-of-the-box, including namespaced storage
- Simplified codebase for ever-improving security
- Efficiency improvements, including reduced gas consumption
- Modernizing access control with AccessManager
- More advanced testing, including new fuzzing and formal verification rules
A Modernized Contracts 5.0
From compiler features to newer standardized practices, the smart contract development landscape has evolved significantly since Contracts 4.0, our last major release. Contracts 5.0 includes a modernized set of features that improve security, efficiency, and developer experience.
In 5.0, token hooks were removed from ERC20, ERC721, and ERC1155, favoring a single `_update` function. This can also be overridden for custom behaviors in any `mint`, `transfer`, or `burn` operation.As additional simplifications, Ownable now accepts a custom owner argument during construction, and Governor supports voting with bytes-formatted signatures and has Account Abstraction support by implementing ERC-1271.
For efficiency, simplification, and security purposes, we’ve removed certain functions and contracts, some of which may be reintroduced in future versions with better support. Removals in 5.0 include:
- TokenTimelock (in favor of VestingWallet)
- All cross-chain contracts (including AccessControlCrossChain)
- All presets in favor of OpenZeppelin Contracts Wizard
Namespaced Storage for better upgrades security
Motivated by the risks and annoyances of dealing with storage layout changes in complex upgradeable contracts, the team has proposed ERC-7201: Namespaced Storage Layout. This is inspired by the diamond storage pattern but standardized in a way that enables our tooling to integrate safety checks while reducing potential security risks.
This Namespaced Storage pattern is used in this new version as a way to avoid one of the most common and easy-to-miss security issues when dealing with upgrades: storage layout collisions between implementation versions.
Previously, upgradeable contracts used to have a `__gap` variable in storage between inherited contracts in order to reserve space for supporting new variables added between upgrades. But, in this new version storage locations are namespaced using ERC-7201 so that variables can be added without compromising previously stored variables.
By scoping variables by namespace, each inherited contract will keep its own storage pointer that can easily hold more values after a subsequent upgrade.
Leveraging new Solidity compiler additions
The library has been updated to Solidity 0.8.20, allowing us to incorporate custom errors and explicit imports, as well as smaller additions to the language such as `abi.encodeCall` for improved type checking.
Applications and wallets have historically relied on reading plain strings from reverts (e.g. revert(“Unauthorized”)) to consume error information. However, custom errors are now available in OpenZeppelin Contracts, following standard practices for constructing errors. The addition was inspired by community input and the ERC-6093 specification.
Custom errors give developers more efficient and standardized ways of reporting errors in their smart contracts that may also include dynamic argumentsIn 5.0, we are also introducing explicit imports to avoid populating the global scope and to make it easier for the developers to follow import paths.
Along with changes to our core library, we have also released updates to Upgrades Plugins and OpenZeppelin Contracts Wizard. In addition to updating our support for Hardhat, we anticipate adding upgrades support for Foundry later this year.
The Contracts library is also natively integrated with the OpenZeppelin Defender security platform. Defender expands the open source contract standards with additional security, performance, and support features, including:
- Secure Code: maximize the security of your code and ensure dependencies are up to date.
- Secure Deploy: deploy with automatic checks on your storage layout to prevent upgrade collisions.
- Monitor, Respond, and Operate: monitor your live applications with built-in templates for implemented standards and instantly respond to threats.
Gas-efficiency without compromising Security
We have reduced both deployment and runtime costs as a result of optimizations made across the library, balancing readability and efficiency. These gas cost reductions accounted for a 9.63% average reduction in the top 10 optimized methods and a 27.11% average deployment cost cutback amongst the top 10 reduced contracts.
Replacing revert strings with custom errors
With the introduction of custom errors to the library, the deployment cost has dropped 12.84% on average across the library. These reductions in deployment costs are mainly due to the impact of the revert strings in the bytecode size, which aren’t stored within the contract bytecode anymore and accounted for over 20% in contracts with heavy use of long revert strings such as AccessControl.
Removing duplicated SLOADs and adding immutable variables
Storage reads are one of the most expensive operations in runtime, and 5.0 saves gas by avoiding duplicate SLOADs where possible (such as in the updated ERC271 implementation).
Analogously, more immutable variables are used across the library to avoid such unnecessary storage reads. Some examples of how this pattern was applied can be seen in TransparentUpgradeableProxy and BeaconProxy where the admin or beacon is now stored in an immutable variable, saving reads on every call to such proxies.
Packing variables in storage
Contracts 5.0 reorganizes some of the most-used data structures and variables to minimize storage use, reducing the gas costs of both reading and writing such variables.
An example of this strategy can be found in the updated Governor proposal structure, which used to be stored in 3 slots with multiple storage gaps added for backward compatibility. Its new structure only uses 2 slots and variables that are commonly used together share the same slot, reducing unnecessary storage reads and improving gas consumption.Flexible and Transparent Access Management
As the industry matures, smart contracts systems are becoming more powerful and more complex, including at the permissions and role management level. Complex systems are often coordinated through multiple contracts via multisigs, DAOs, timelocks and EOAs, which have stretched the capacity of previous access management mechanisms such as AccessControl and Ownable. For these complex scenarios, we’ve observed an increasing need for a single source of truth when it comes to access management.
Redefining Access Control through AccessManager
As an alternative for more sophisticated access control setups in decentralized protocols, OpenZeppelin Contracts 5.0 introduces the AccessManager: a modern and efficient solution for role management across contracts. Instead of managing each contract separately, AccessManager allows you to manage permissions from a single contract, making your system easier to audit and control.
AccessManager scopes permissions so that each specific function of a contract can be restricted to a single role. These roles work similarly to the current AccessControl implementation where multiple addresses can be granted a role or set of roles. Each address granted a role can either have immediate or delayed execution, allowing you to time-lock operations out of the box without the need for additional contracts. Finally, existing access control systems and DAOs using Governor can be migrated to use the AccessManager without any upgrades. In practice, we expect these changes to meaningfully improve transparency and flexibility throughout the secure development lifecycle.
AccessManager support is coming soon to OpenZeppelin Defender. Please reach out if you are interested in testing once it is available.
Best-in-class Audit & Testing Practices
OpenZeppelin Contracts continues to maintain ~99% unit test coverage. In 5.0 we’ve added more fuzzing tests and additional formal verification rules, including formally verifying the new Access Manager implementation. We also underwent an extensive audit of Contracts 5.0. Details have been posted on our Contracts Security Center.
A structured process around audit delivery and review was essential given the scope and complexity involved. In preparing 5.0, we were able to use the OpenZeppelin Defender Audit module to streamline the review process and ensure all changes were tracked and resolved effectively.
The Release Candidate was introduced to the public on September 19th with bug bounty awards temporarily increased by 50%. Our bug bounty program remains open and we continue to encourage interested developers to help us find and fix potential vulnerabilities.
We are able to develop and maintain rigorous audit practices thanks in large part to community contributions and public goods funding. In the recent Optimism RetroPGF Round 2, OpenZeppelin received the most votes out of all submissions in the Tooling and Utilities section.
Our gratitude extends to everyone involved in making open-source software development sustainable and high-quality, and we plan to continue our industry leadership in 5.1 and beyond. In upcoming releases, we will continue to emphasize advanced testing methods such as formal verification, as well as building stronger integrations with the wider ecosystem including popular development tools and security platforms such as Hardhat, Foundry, and OpenZeppelin Defender.
If you are starting a new project, OpenZeppelin Contracts v5.0.0 is available for both Hardhat and Foundry environments, as well as in OpenZeppelin Wizard. Existing projects can visit our upgrade guide, where we advise using OpenZeppelin Defender’s code module to ensure your dependencies are up to date.