-
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
Rigidity in Initializable's INITIALIZABLE_STORAGE slot #4782
Comments
Hey @howydev, sorry for the late response. I'm not sure if I'm following. If I understand correctly, the issue is that most SCA use the UUPSUpgradeable pattern (I assume including an If this is the case, I think you can use the Can you provide a concrete example where the use of Initializable becomes a problem?
The
This sounds better, but I think an example of how |
Thanks for the response @ernestognw. Big fan of yours, hope you're having a great new year so far! Yep, thats a good summary!
Yup the chosen storage slot is in line with 7201! However, to fully reap the benefits of 7201, contracts have to intentionally design storage to be clumped. For a private
From a high level, these are how we think about smart accounts:
For regular protocols, because they design every version of their protocol, they can use the same storage structs or use append-only inherited storage as a solution to minimize storage collision risk. We can adhere to this internally to allow safe upgrades from an Alchemy v1 account to an Alchemy v2 account. But what about the Alchemy v1 smart account -> Zerodev v1 smart account path? If Alchemy and Zerodev both use OZ.Initializable, over a long timespan of versions, storage collisions are nearly guaranteed. Therefore, to derisk, both Alchemy and Zerodev (and all SCA builders) must each choose our own unique storage locations I can't think of a way to achieve the above with the current reinit design without requiring massive collaboration across the ecosystem around assigning version id numbers since we need them to be unique. I think the strictly increasing id numbers also prevent downgrades. Let me know if I overlooked something here
Thinking about this a big more - a large number of Initializable contracts must use some kind of access control to protect the |
Heads up we're reconsidering this @howydev, I agree with the use cases you pointed out and I also believe that an account should easily change between implementations safely. I had a couple of repeated convos about storage collisions. I guess the solution for fixing this for the
We're still to see when Verkles are going to become a thing so this is still open for discussion. The general idea is that storage would cost pretty much the same for that namespace even if it's not optimized for Verkle, whereas the optimization will help with data structures that are natively implemented in sequential storage locations |
Thanks for reconsidering! For the verkle case, you would need to access multiple storage slots beyond just the |
🧐 Motivation
Most ERC4337/ERC6900 smart contract accounts use the UUPSUpgradeable proxy pattern today. In OZ5.0's Initializable, the same
INITIALIZABLE_STORAGE
slot is used. As such, if more than 1 SCA implementation uses OZ5.0's Initializable, when a proxy is initialized with one of those implementations, it would not upgrade to other SCA implementations that require aninitializer
function to set up - as such, for security reasons, no SCA can use the Initializable library📝 Details
_getInitializableStorage()
orINITIALIZABLE_STORAGE
tointernal virtual
and allow parent contracts to choose which storage slot to use. This also allows child contracts to group storage slots together when verkle trees are adopted without having to worrying about storage collisions across versions.INITIALIZABLE_STORAGE
instead. One possible implementation is:Credit: @gpersoon
The text was updated successfully, but these errors were encountered: