Frequently Asked Questions - OpenZeppelin Docs (2024)

Can I change Solidity compiler versions when upgrading?

Yes. The Solidity team guarantees that the compiler will preserve the storage layout across versions.

Why am I getting the error "Cannot call fallback function from the proxy admin"?

This is due to the Transparent Proxy Pattern. You shouldn’t get this error when using the OpenZeppelin Upgrades Plugins, since it uses the ProxyAdmin contract for managing your proxies.

However, if you are using OpenZeppelin Contracts proxies programmatically you could potentially run into such error. The solution is to always interact with your proxies from an account that is not the admin of the proxy, unless you want to specifically call the functions of the proxy itself.

What does it mean for a contract to be upgrade safe?

When deploying a proxy for a contract, there are some limitations to the contract code. In particular, the contract cannot have a constructor, and should not use the selfdestruct or delegatecall operations for security reasons.

As a replacement for the constructor, it is common to set up an initialize function to take care of the contract’s initialization. You can use the Initializable base contract to have access to an initializer modifier that ensures the function is only called once.

import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";contract MyContract is Initializable { uint256 value; function initialize(uint256 initialValue) public initializer { value = initialValue; }}

Both plugins will validate that the contract you are trying to deploy complies with these rules. You can read more about how to write upgrade safe contracts here.

How can I disable some of the checks?

Deployment and upgrade related functions come with an optional opts object, which includes an unsafeAllow option. This can be set to disable any check performed by the plugin. The list of checks that can individually be disabled is:

  • state-variable-assignment

  • state-variable-immutable

  • external-library-linking

  • struct-definition

  • enum-definition

  • constructor

  • delegatecall

  • selfdestruct

  • missing-public-upgradeto

  • internal-function-storage

This function is a generalized version of the original unsafeAllowCustomTypes and unsafeAllowLinkedLibraries allowing any check to be manually disabled.

For example, in order to upgrade to an implementation that contains a delegate call, you would call:

await upgradeProxy(proxyAddress, implementationFactory, { unsafeAllow: ['delegatecall'] });

Additionally, it is possible to precisely disable checks directly from the Solidity source code using NatSpec comments. This requires Solidity >=0.8.2.

contract SomeContract { function some_dangerous_function() public { ... /// @custom:oz-upgrades-unsafe-allow delegatecall (bool success, bytes memory returndata) = msg.sender.delegatecall(""); ... }}

This syntax can be used with the following errors:

  • /// @custom:oz-upgrades-unsafe-allow state-variable-immutable

  • /// @custom:oz-upgrades-unsafe-allow state-variable-assignment

  • /// @custom:oz-upgrades-unsafe-allow external-library-linking

  • /// @custom:oz-upgrades-unsafe-allow constructor

  • /// @custom:oz-upgrades-unsafe-allow delegatecall

  • /// @custom:oz-upgrades-unsafe-allow selfdestruct

In some cases you may want to allow multiple errors in a single line.

/// @custom:oz-upgrades-unsafe-allow constructor state-variable-immutablecontract SomeOtherContract { uint256 immutable x; constructor() { x = block.number; }}

You can also use the following to allow specific errors in reachable code, which includes any referenced contracts, functions, and libraries:

  • /// @custom:oz-upgrades-unsafe-allow-reachable delegatecall

  • /// @custom:oz-upgrades-unsafe-allow-reachable selfdestruct

Can I safely use delegatecall and selfdestruct?

This is an advanced technique and can put funds at risk of permanent loss.

It may be possible to safely use delegatecall and selfdestruct if they are guarded so that they can only be triggered through proxies and not on the implementation contract itself. A way to achieve this in Solidity is as follows.

abstract contract OnlyDelegateCall { /// @custom:oz-upgrades-unsafe-allow state-variable-immutable address private immutable self = address(this); function checkDelegateCall() private view { require(address(this) != self); } modifier onlyDelegateCall() { checkDelegateCall(); _; }}
contract UsesUnsafeOperations is OnlyDelegateCall { /// @custom:oz-upgrades-unsafe-allow selfdestruct function destroyProxy() onlyDelegateCall { selfdestruct(msg.sender); }}

What does it mean for an implementation to be compatible?

When upgrading a proxy from one implementation to another, the storage layout of both implementations must be compatible. This means that, even though you can completely change the code of the implementation, you cannot modify the existing contract state variables. The only operation allowed is to append new state variables after the ones already declared.

Both plugins will validate that the new implementation contract is compatible with the previous one.

You can read more about how to make storage-compatible changes to an implementation contract here.

What is a proxy admin?

A ProxyAdmin is an intermediary contract that acts as the upgrader of a transparent proxy. Each ProxyAdmin is owned by the deployer address, or by the initialOwner address when deploying a transparent proxy from OpenZeppelin Contracts 5.0 or above. You can transfer the ownership of a proxy admin by calling transferOwnership.

What is an implementation contract?

Upgradeable deployments require at least two contracts: a proxy and an implementation. The proxy contract is the instance you and your users will interact with, and the implementation is the contract that holds the code. If you call deployProxy several times for the same implementation contract, several proxies will be deployed, but only one implementation contract will be used.

When you upgrade a proxy to a new version, a new implementation contract is deployed if needed, and the proxy is set to use the new implementation contract. You can read more about the proxy upgrade pattern here.

What is a proxy?

A proxy is a contract that delegates all of its calls to a second contract, named an implementation contract. All state and funds are held in the proxy, but the code actually executed is that of the implementation. A proxy can be upgraded by its admin to use a different implementation contract.

You can read more about the proxy upgrade pattern here.

Why can’t I use immutable variables?

Solidity 0.6.5 introduced the immutable keyword to declare a variable that can be assigned only once during construction and can be read only after construction. It does so by calculating its value during contract creation and storing its value directly into the bytecode.

Notice that this behavior is incompatible with the way upgradeable contracts work for two reasons:

  1. Upgradeable contracts have no constructors but initializers, therefore they can’t handle immutable variables.

  2. Since the immutable variable value is stored in the bytecode its value would be shared among all proxies pointing to a given contract instead of each proxy’s storage.

In some cases immutable variables are upgrade safe. The plugins cannot currently detect these cases automatically so they will point it out as an error anyway. You can manually disable the check using the option unsafeAllow: ['state-variable-immutable'], or in Solidity >=0.8.2 placing the comment /// @custom:oz-upgrades-unsafe-allow state-variable-immutable before the variable declaration.

Why can’t I use external libraries?

At the moment, the plugins only have partial support for upgradeable contracts linked to external libraries. This is because it’s not known at compile time what implementation is going to be linked, thus making it very difficult to guarantee the safety of the upgrade operation.

There are plans to add this functionality in the near future with certain constraints that make the issue easier to address like assuming that the external library’s source code is either present in the codebase or that it’s been deployed and mined so it can be fetched from the blockchain for analysis.

In the meantime, you can deploy upgradeable contracts linked to external libraries by setting the unsafeAllowLinkedLibraries flag to true in the deployProxy or upgradeProxy calls, or including 'external-library-linking' in the unsafeAllow array. Keep in mind the plugins will not verify that the linked libraries are upgrade safe. This has to be done manually for now until the full support for external libraries is implemented.

You can follow or contribute to this issue in GitHub.

Why do I need a public upgradeTo or upgradeToAndCall function?

When using UUPS proxies (through the kind: 'uups' option), the implementation contract must include one or both of the public functions upgradeTo(address newImplementation) or upgradeToAndCall(address newImplementation, bytes memory data). This is because in the UUPS pattern the proxy does not contain an upgrading function itself, and the entire upgradeability mechanism lives on the implementation side. Thus, on every deploy and upgrade we have to make sure to include it, otherwise we may permanently disable the upgradeability of the contract.

The recommended way to include one or both of these functions is by inheriting the UUPSUpgradeable contract provided in OpenZeppelin Contracts, as shown below. This contract adds the required function(s), but also contains a built-in mechanism that will check on-chain, at the time of an upgrade, that the new implementation proposed also inherits UUPSUpgradeable or implements the same interface. In this way, when using the Upgrades Plugins there are two layers of mitigations to prevent accidentally disabling upgradeability: an off-chain check by the plugins, and an on-chain fallback in the contract itself.

import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";contract MyContract is Initializable, ..., UUPSUpgradeable { ...}

Read more about the differences with the Transparent Proxy Pattern in Transparent vs UUPS.

Can I use custom types like structs and enums?

Past versions of the plugins did not support upgradeable contracts that used custom types like structs or enums in their code or linked libraries. This is no longer the case for current versions of the plugins, and structs and enums will be automatically checked for compatibility when upgrading a contract.

Some users who have already deployed proxies with structs and/or enums and who need to upgrade those proxies may need to use the override flag unsafeAllowCustomTypes for their next upgrade, after which it will no longer be necessary. If the project contains the source code for the implementation currently in use by the proxy, the plugin will attempt to recover the metadata that it needs before the upgrade, falling back to the override flag if this is not possible.

How can I rename a variable, or change its type?

Renaming a variable is disallowed by default because there is a chance that a renaming is actually an accidental reordering. For example, if variables uint a; uint b; are upgraded to uint b; uint a;, if renaming was simply allowed this would not be seen as a mistake, but it could have been an accident, especially when multiple inheritance is involved.

It is possible to disable this check by passing the option unsafeAllowRenames: true. A more granular approach is to use a docstring comment /// @custom:oz-renamed-from <previous name> right above the variable that is being renamed, for example:

contract V1 { uint x;}contract V2 { /// @custom:oz-renamed-from x uint y;}

Changing the type of a variable is not allowed either, even in cases where the types have the same size and alignment, for the similar reason explained above. As long as we can guarantee that the rest of the layout is not affected by this type change, it is also possible to override this check by placing a docstring comment /// @custom:oz-retyped-from <previous type>.

contract V1 { bool x;}contract V2 { /// @custom:oz-retyped-from bool uint8 x;}

Docstring comments don’t yet work for struct members, due to a current Solidity limitation.

How can I use internal functions in storage variables?

Internal functions in storage variables are code pointers which will no longer be valid after an upgrade, because the code will move around and the pointer would change. To avoid this issue, you can declare those functions as external, or avoid code pointers in storage altogether and define an enum that you will use with a dispatcher function to select from the list of available functions. If you must use internal functions, those internal functions need to be reassigned during each upgrade.

For example, the messageFunction variable in the following contract is not upgrade safe. Attempting to call showMessage() after an upgrade would likely result in a revert.

import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";contract V1 is Initializable { function() internal pure returns (string memory) messageFunction; function initialize() initializer public { messageFunction = hello; } function hello() internal pure returns (string memory) { return "Hello, World!"; } function showMessage() public view returns (string memory) { return messageFunction(); } ...}

To allow the above contract to be deployed by the Upgrades Plugins, you can disable the internal-function-storage check according to How can I disable some of the checks?, but ensure you follow the steps below to reassign the internal function during upgrades.

In new versions of this contract, assign the internal function in the storage variable again, for example by using a reinitializer:

import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";import "./V1.sol";contract V2 is V1 { function initializeV2() reinitializer(2) public { messageFunction = hello; } ...}

Then when upgrading, call the reinitializer function as part of the upgrade process, for example in Hardhat:

await upgrades.upgradeProxy(PROXY_ADDRESS, ContractFactoryV2, { call: 'initializeV2', unsafeAllow: ['internal-function-storage']});

or in Foundry:

Upgrades.upgradeProxy( PROXY_ADDRESS, "V2.sol", abi.encodeCall(V2.initializeV2, ()));

← Proxy Upgrade Pattern

Hardhat Upgrades API →

Frequently Asked Questions - OpenZeppelin Docs (2024)

FAQs

Frequently Asked Questions - OpenZeppelin Docs? ›

OpenZeppelin Contracts helps you minimize risk by using battle-tested libraries of smart contracts for Ethereum and other EVM blockchains. It includes the most used implementations of ERC standards.

What is the use of OpenZeppelin? ›

OpenZeppelin Contracts helps you minimize risk by using battle-tested libraries of smart contracts for Ethereum and other EVM blockchains. It includes the most used implementations of ERC standards.

What is the default admin role in OpenZeppelin? ›

Each role has an associated admin role, and only accounts that have a role's admin role can call grantRole and revokeRole . By default, the admin role for all roles is DEFAULT_ADMIN_ROLE , which means that only accounts with this role will be able to grant or revoke other roles.

Is OpenZeppelin safe? ›

Secure. “Collaborating with OpenZeppelin on our security audit was a positive experience. We appreciated their thoroughness and attention to detail.”

What can be upgraded in smart contracts deployed using OpenZeppelin upgrades plugins? ›

Smart contracts deployed using OpenZeppelin Upgrades Plugins can be upgraded to modify their code, while preserving their address, state, and balance. This allows you to iteratively add new features to your project, or fix any bugs you may find in production.

How to use access control in OpenZeppelin? ›

Using AccessControl

OpenZeppelin Contracts provides AccessControl for implementing role-based access control. Its usage is straightforward: for each role that you want to define, you will create a new role identifier that is used to grant, revoke, and check if an account has that role.

What is a user's default role? ›

A user's default role determines the role used in the Snowflake sessions initiated by the user; however, this is only a default. Users can change roles within a session at any time. Roles can be assigned at user creation or afterwards.

What is ownable in smart contracts? ›

Ownable contracts in Solidity are used to implement access control for certain functions. The idea is that only the contract owner, who is typically the deployer of the contract, can execute these protected functions.

What is the use of UniFi security gateway? ›

The UniFi Security Gateway can create virtual network segments for security and network traffic management. A site‑to‑site VPN secures and encrypts private data communications traveling over the Internet.

What is the use of UTM firewall? ›

Unified threat management (UTM) refers to when multiple security features or services are combined into a single device within your network. Using UTM, your network's users are protected with several different features, including antivirus, content filtering, email and web filtering, anti-spam, and more.

How to create an ERC20 token in OpenZeppelin? ›

How to create an ERC 20 token with OpenZeppelin
  1. Let's get started. Go to the OpenZeppelin Contracts Wizard and click on ERC20. ...
  2. Let's add some features. ...
  3. Let's set the access control. ...
  4. Let's add upgradeability. ...
  5. Let's add a security contact. ...
  6. Download your smart contract code. ...
  7. Compile the smart contract. ...
  8. Deploy the smart contract.
Mar 17, 2023

Top Articles
How Do You Build Credit History More Quickly? | Chase
Welfare benefits or Temporary Assistance for Needy Families (TANF) | USAGov
Monthly Forecast Accuweather
His Lost Lycan Luna Chapter 5
How To Do A Springboard Attack In Wwe 2K22
Mate Me If You May Sapir Englard Pdf
Phone Number For Walmart Automotive Department
Boggle Brain Busters Bonus Answers
Craigslist Furniture Bedroom Set
According To The Wall Street Journal Weegy
What is international trade and explain its types?
Www Movieswood Com
Smokeland West Warwick
Capitulo 2B Answers Page 40
Housework 2 Jab
Beau John Maloney Houston Tx
Think Up Elar Level 5 Answer Key Pdf
The fabulous trio of the Miller sisters
Hca Florida Middleburg Emergency Reviews
Elizabethtown Mesothelioma Legal Question
Chile Crunch Original
The ULTIMATE 2023 Sedona Vortex Guide
065106619
How To Level Up Roc Rlcraft
Concordia Apartment 34 Tarkov
Aps Day Spa Evesham
Rqi.1Stop
Georgia Cash 3 Midday-Lottery Results & Winning Numbers
Sodium azide 1% in aqueous solution
Baja Boats For Sale On Craigslist
A Person That Creates Movie Basis Figgerits
Albert Einstein Sdn 2023
Costco Jobs San Diego
Arlington Museum of Art to show shining, shimmering, splendid costumes from Disney Archives
Hattie Bartons Brownie Recipe
Mgm Virtual Roster Login
Labyrinth enchantment | PoE Wiki
PruittHealth hiring Certified Nursing Assistant - Third Shift in Augusta, GA | LinkedIn
sacramento for sale by owner "boats" - craigslist
Cuckold Gonewildaudio
Pink Runtz Strain, The Ultimate Guide
Love Words Starting with P (With Definition)
Best Conjuration Spell In Skyrim
About Us
Gary Vandenheuvel Net Worth
Unblocked Games - Gun Mayhem
American Bully Puppies for Sale | Lancaster Puppies
News & Events | Pi Recordings
Bama Rush Is Back! Here Are the 15 Most Outrageous Sorority Houses on the Row
Google Flights Missoula
Treatise On Jewelcrafting
How to Find Mugshots: 11 Steps (with Pictures) - wikiHow
Latest Posts
Article information

Author: Terence Hammes MD

Last Updated:

Views: 6288

Rating: 4.9 / 5 (49 voted)

Reviews: 80% of readers found this page helpful

Author information

Name: Terence Hammes MD

Birthday: 1992-04-11

Address: Suite 408 9446 Mercy Mews, West Roxie, CT 04904

Phone: +50312511349175

Job: Product Consulting Liaison

Hobby: Jogging, Motor sports, Nordic skating, Jigsaw puzzles, Bird watching, Nordic skating, Sculpting

Introduction: My name is Terence Hammes MD, I am a inexpensive, energetic, jolly, faithful, cheerful, proud, rich person who loves writing and wants to share my knowledge and understanding with you.