This package contains the same contracts as the vanilla OpenZeppelin Contracts, but modified for use with upgradeable contracts. The main difference is that all contracts in this package are potentially upgradeable : you will notice that no contracts have constructors defined, but use initializer functions instead. Also, this package is set up as an Ethereum package, and provides a small set of pre-deployed logic contracts that can be used directly via the OpenZeppelin SDK, without needing to deploy them again.
Thanks for the reply.
Wouldnât it be possible to make a library to is compatible both for regular and for upgradable contracts?
I want to create an upgradable contract, importing the Ownable contract.
If I import @openzeppelin/contracts/access/Ownable.sol, it complains that Ownable uses a constructor.
How I import the Ownable contract in a upgradable contract?
To use Ownable in an upgradeable contract we need to do the following:
Import OwnableUpgradeSafe as contracts in OpenZeppelin Contracts Ethereum Package have an UpgradeSafe suffix to avoid confusion with their counterparts in OpenZeppelin Contracts.
Create an initialize function to initialize the contract and use the initializer modifier from Initializable to ensure that it is only called once.
// contracts/Box.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
// Import Ownable from the OpenZeppelin Contracts library
import "@openzeppelin/contracts-ethereum-package/contracts/access/Ownable.sol";
import "@openzeppelin/contracts-ethereum-package/contracts/Initializable.sol";
// Make Box inherit from the Ownable contract
contract Box is Initializable, OwnableUpgradeSafe {
uint256 private value;
event ValueChanged(uint256 newValue);
function initialize() public initializer {
__Context_init_unchained();
__Ownable_init_unchained();
}
// The onlyOwner modifier restricts who can call the store function
function store(uint256 newValue) public onlyOwner {
value = newValue;
emit ValueChanged(newValue);
}
function retrieve() public view returns (uint256) {
return value;
}
}
I assume you mean a version of OpenZeppelin Contracts that could be used with regular contracts and upgradeable contracts.
A single version would require contracts to have both constructors and initializers, increasing the complexity, along with the gas costs of deployment.
The same API documentation for OpenZeppelin Contracts can be used with OpenZeppelin Contracts Ethereum Package. The differences are an UpgradeSafe suffix on the contract and using initializers rather than constructors.
This package contains the same contracts as the vanilla OpenZeppelin Contracts, but modified for use with upgradeable contracts. The main difference is that all contracts in this package are potentially upgradeable : you will notice that no contracts have constructors defined, but use initializer functions instead. Also, this package is set up as an Ethereum package, and provides a small set of pre-deployed logic contracts that can be used directly via the OpenZeppelin SDK, without needing to deploy them again.
All contracts have an UpgradeSafe suffix to avoid confusion with their counterparts in OpenZeppelin Contracts. For example, ERC20 becomes ERC20UpgradeSafe .
All in all, you should use this package instead of @openzeppelin/contracts if you are creating upgradeable contracts .
this shows whatâs required to move to upgradeable contracts with the OpenZeppelin themself:
change imports (point to @openzeppelin/contracts-ethereum-package) for all contract imports
derive Box from both InitializableandownableUpgradeSafe (in that order) - I guess this is to make both Box and Ownable upgradeable
call base class initialize implementation functions - for which I have to look at the source (implementation) of the respective OpenZeppelin contract inherited (OwnableUpgradeSafe in this case)
FWIW, I spent quite some time with the docs: I could find 1. there, but the infos 2. and 3. I didnât find (only here in your answer).
With 3.: as a app developer using OZ contracts, am I supposed to read the implementation to figure out the right functions to call in the base class (inside initialize). Eg in my case, with AccessControlUpgradeSafe, I am supposed to call __Context_init_unchained and __AccessControl_init_unchained ⌠I guess)
Thanks for the feedback on the your experience with OpenZeppelin Contracts Ethereum Package. I am sorry that all the information you needed wasnât in the one place.
I had this exact same problem. I had previously been using the regular contracts library, but now see I should use the âcontracts-ethereum-packageâ. One easy step is I think it would be helpful for this to be made clearer in the upgrades section of the docs, or in the contracts library README. Even after reading a lot of the OZ docs, I didnât realize this until I started actually trying to deploy upgradeable contracts, and realizing that Ownable wouldnât work. I do realize it technically on this page, but itâs a bit buried and I totally missed it.
Anyway, thanks for everything! Very helpful libraries, and I love what OZ is doing.