-
Notifications
You must be signed in to change notification settings - Fork 11.9k
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
Ownable2StepUpgradeable requires initializing OwnableUpgradeable #4690
Comments
Note we have other examples of contract initializers only calling their parent's initializable. |
All good if that is how it should, it just needs to be mentioned somewhere, that that is how it generaly works, and for people to pay attention to it. |
In my opinion, it should call Although mentioned, I'd prefer having a dev experience that's secure by default. It's also true that is not likely that someone deploys an uninitialized Ownable seriously to production, but it was the default behavior in 4.9 so it isn't crazy to think someone will ignore it. |
It happened to me, but I had tests that cover this case, not sure if everyone does. Maybe something like breaking changes will help, because this is really easy to miss, as it was for me. |
A relevant detail is that in 4.9.3, Ownable2StepUpgradeable's initializer does call OwnableUpgradeable's initializer: But in 5.0.0, it doesn't: |
Yup, that was exactly where I was coming from initially. I used 4.7.3 and then switched to 5. |
Hello I was about to submit this. While developing a new project with v5, I was expecting I agree with @ernestognw's suggestion, this is not only a matter of having better docs. |
Thanks for the feedback to both. Something worth noting is that we've previously identified that OZ upgrade plugins should check lack of initialization as well (among other things). For now, adding |
We chatted about this internally and @Amxx reached the following conclusion: Consider the following example:
This is a problem that not only applies to Ownable but to any contract following the pattern of calling the parent's constructor. It just happened to Ownable because it's the only case in the library where we also extend the base contract (Ownable). Generally, this will be a problem for any inheritance tree where the linearization graph is either incomplete or initializes something twice. So I personally don't see a point in fixing just the case of Ownable if it's a broader problem. We've decided that this is something we should definitely provide along with upgrade-plugins. In a way, is like the replacement for the Solidity inheritance checks (eg. double constructor or missing constructors) but for upgrades. Quoting our current documentation:
We'll keep track of this update through this issue in upgrades plugins. |
🧐 Motivation
Ownable2StepUpgradeable inherits OwnableUpgradeable.
Ownable2StepUpgradeable has initializer
__Ownable2Step_init()
OwnableUpgradeable has initializer
__Ownable_init(address initialOwner)
Currently contracts that inherit Ownable2StepUpgradeable need to call
__Ownable_init(address initialOwner)
to set the initial owner. This is not obvious because users who are just inheriting Ownable2StepUpgradeable directly may not know about this transitive requirement.This differs from the non-upgradeable scenario which was discussed in #4368 (comment), because contracts that extend the non-upgradeable Ownable2Step would fail compilation if they did not call the Ownable constructor.
Next steps
Consider whether the initializer of Ownable2StepUpgradeable should also initialize the owner. This would occur if Ownable2Step calls its parent constructor, however there are some drawbacks to multiple inheritance mentioned in comment #4368 (comment)
The text was updated successfully, but these errors were encountered: