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
Support storage layout gaps #276
Comments
Is there estimation for the feature? We need it |
@aquiladev unfortunately there isn't. I'll see if I can bump it, as I believe it would be valuable ... but I don't want to make any promise I can't keep. |
This is quite limiting unfortunately for automating upgrades |
@itsermin so far I see next options:
|
It would be great if you could prefix match |
Solving this issue is quite important. First, you suggest an approach that does not work as intended. Second, the entire assumption is that you can write upgradeable contracts, but if the storage cannot be upgraded with new variables, the entire castle crashes, forcing to move towards other solutions for upgradeability. Long time is passed since the issue has been open. Is there any news? |
@sullof Thank you for your feedback. We have recently started working on this. |
BTW, I wonder if you are thinking of supporting this: |
@sullof |
Thanks. When do you plan the next major release? |
@sullof It would come after a Solidity version that introduces breaking changes is released. |
That makes sense, thanks. Since our contracts are audited and ready to go, we will deploy the contracts based on current version. |
@sullof We still plan to fix this issue, and plan to continue support using the upgrades plugins with the current version of Contracts (4.x). |
Please note that when using the diamond storage pattern, storage layout is currently not checked at all for incompatibilities. A future version will recognize the pattern and compare the structs between versions. Starting this week we are actively working on adding support for gaps. We are currently analyzing the best way to modify the layout comparison algorithm to work with gaps. The latest idea is that we should preprocess layouts to remove gap variables and leave in actual gaps, then let the levenshtein algorithm recognize the variables that are inserted in the middle. Insertions are currently considered errors though, so we need to change something else to accept them while continuing to reject "bad" insertions. An idea here is that we could work in two modes: the current mode where insertions and deletions are disallowed, and an alternate mode that is used if we have precise storage layout information (slots and offsets) in which we rely solely on |
Thanks. I am sticking with the version 4 and not using Diamond, since you will continue to support V4. I think that whichever solution you choose, it is very important that you support the __gap array approach. We all followed your recommendation and expect that inserting a variable while reducing the length of the array works without errors. Maybe you can just allow to ignore the error and proceed anyway. Everyone tests upgrades on testnet before doing the same on mainnet. |
Errors can be ignored with the use of the |
It would be good if this feature included detecting storage changes for upgrades that use diamond storage. Related issue here: #459 |
@mudgen These are separate features that have to be tackled in different ways. |
@frangio will it be possible to do |
@mistersingh179 There are a set of checks that can be skipped for specific lines (documented here and here), but those do not cover the gaps scenario. When this issue is completed, gaps should be supported (without needing docstring comments). |
Sharing my proposed design notes for this feature. We currently have a levenshtein module that computes a minimum cost edit distance between two storage layouts. A levenshtein edit distance consists of a list of insertion, deletion, and substitution operations that convert one layout into the other. My proposal is to generalize this to a custom edit distance with operations designed for our domain, with something like a "gap shrink" operation. Then, using the levenshtein module (which really stops being about levenshtein and becomes a generalized Wagner-Fischer implementation) we compute the minimum edit distance with the custom operations. That edit distance may include some insertion operations, i.e. storage variables added in the middle of the layout, which we would normally disallow, but we can now allow them if they are followed by a matching gap shrink operation of the right size. Furthermore, we should tune the costs of operations to make sure that the minimum cost edit distance is the one that would include the operations we're looking for. This should be simply a matter of giving lower cost to operations that we want to prioritize, e.g. the gap shrink should be a low cost operation. |
Hello Guys, |
This is now available in the latest version of For details on storage gaps, see docs. |
Can we do a prefix match instead of exact match please? Allows for adding multiple gaps as well as giving them more meaningful names. |
@roshanr95 Please open an issue! |
Done, thanks. #657 |
Hi @frangio , @roshanr95 , I'm still getting the issue when upgrading the proxy by just adding a new state variable and reducing size of gap. New variables should be placed after all existing inherited variables
|
@skyclean906 Please open a new issue and share the code if possible. |
We often recommend including a storage "gap" in storage layout in order to safely add storage variables when using (multiple) inheritance. We use this pattern ourselves in OpenZeppelin Contracts Upgradeable. However, if a slot in the gap is actually used for a new variable later, the plugins will flag this as an error. We should detect gaps through the conventional
__gap
name and treat them specially for layout compatibility: allow replacing gap slots with new variables in an upgrade.The text was updated successfully, but these errors were encountered: