Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initializer must be reusable for upgrade Initializers #2901

Closed
a-d-j-i opened this issue Oct 5, 2021 · 3 comments · Fixed by #3232
Closed

Initializer must be reusable for upgrade Initializers #2901

a-d-j-i opened this issue Oct 5, 2021 · 3 comments · Fixed by #3232

Comments

@a-d-j-i
Copy link

a-d-j-i commented Oct 5, 2021

🧐 Motivation
All upgradeables are taking some storage space to limit the execution if the Initializer twice.
When you upgrade a contract you need to initialize the new variables and is a good idea to reuse the storage used by Initializer.

📝 Details
I created an example of the main idea in: https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/pull/125/files

@frangio
Copy link
Contributor

frangio commented Oct 15, 2021

Thanks for the suggestion @a-d-j-i.

Looking at your PR (OpenZeppelin/openzeppelin-contracts-upgradeable#125), I'm not a fan of the name upgradeInit but the name reinitializer may be good.

The idea would be that the modifier reinitializer(n) can run only once, and only if the contract isn't already initialized to a level m >= n.

initializer would be the same as reinitializer(1).

One thing I find interesting in your linked code is that the modifier uses the condition require(_initializing || _upgradeLevel <= upgradeLevel). In other words, initializers from a lower level can still be invoked during a reinitializer of a higher level. This may sound undesirable but it actually solves a problem that we currently have: if, for example, someone upgrades an existing ERC20 to add ERC20Votes, they are not able to call ERC20Votes_init because it will see that the contract is already initialized. This is solved with reinitializer because the user can write the following function which would work:

function initializeV2() reinitializer(2) public {
    __ERC20VotesUpgradeable_init(...);
}

One challenge is that if we change Initializable it needs to be storage-compatible with the current version. This is technically doable because it currently has two booleans that could be converted into a uint16. However, the Upgrades Plugins would find that incompatible so we would need to figure out a way to make that work.

We should discuss this quite a bit more so please don't submit any PRs yet.

@a-d-j-i
Copy link
Author

a-d-j-i commented Oct 15, 2021

Ok, this was just an example, I will not insist with this PR.
I just want the functionality.
Finally maybe patch or patch Level is a possible name.
Thanks!!!

@a-d-j-i a-d-j-i closed this as completed Oct 15, 2021
@frangio frangio reopened this Oct 15, 2021
@frangio
Copy link
Contributor

frangio commented Oct 15, 2021

Let's leave open for discussion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants
@frangio @a-d-j-i and others