-
Notifications
You must be signed in to change notification settings - Fork 280
Fix: Allow appending to struct at the end of storage layout #1136 #1147
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
Conversation
…tructs in storage layout. Added checks for struct member changes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR.
Can you please add some tests? These should include when validations should pass, and when validations should report errors (for example, when appending at the end of a struct, but the struct is not at the end of storage).
…ludes cases for valid and invalid struct modifications, ensuring proper error handling and namespace support.
…ayoutComparator to improve code clarity and maintainability.
…ncy. Cleaned up whitespace in struct append tests for improved readability.
…mplement tests for valid and invalid struct appending scenarios in storage layout validation.
Hi @ericglau , I have implemented the changes based on your suggestions. Could you please review them at your convenience? If everything looks good, would you mind proceeding with the merge? Thank you! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've adjusted the test cases for the second scenario to properly demonstrate insertion before the end of storage layout.
However, the first test case is still failing with the following operations even though it should have been filtered out by the new code in compare.ts:
[
{
"kind": "typechange",
"change": {
"kind": "struct members",
"ops": [
{
"kind": "append",
"totalCost": 0,
"predecessor": {
"kind": "nop",
"totalCost": 0,
"predecessor": {
"kind": "nop",
"totalCost": 0,
"predecessor": {
"kind": "nop",
"totalCost": 0
}
}
},
"updated": {
"label": "z",
"type": {
"id": "t_uint256",
"head": "t_uint256",
"item": {
"label": "uint256",
"numberOfBytes": "32"
}
},
"offset": 0,
"slot": "2"
}
}
],
...
The logic for the comparison may need to be investigated or this may need further debugging.
@@ -0,0 +1,42 @@ | |||
// SPDX-License-Identifier: MIT | |||
pragma solidity ^0.8.0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is missing test cases for namespaced structs as described in #1136
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added test cases for namespaced structs as requested in the latest commit. Let me know if there are any more suggestions
…tructs in storage layout. Added checks for struct member changes
…ludes cases for valid and invalid struct modifications, ensuring proper error handling and namespace support.
…ayoutComparator to improve code clarity and maintainability.
…ncy. Cleaned up whitespace in struct append tests for improved readability.
…mplement tests for valid and invalid struct appending scenarios in storage layout validation.
…penzeppelin-upgrades into struct-append-1136
Hey @ericglau I have made the suggested changes and pushed some commit, could you review them, if they are Ok or not? |
1c682de
to
a53fcf5
Compare
hey @ericglau its been a week almost. Would you review if the commits are ok ? and If it is can you merge the PR ? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the late response, but the new commits don't address my previous comments. The testcase failure still occurs, and namespaced test cases have not been added.
This section of code is in a critical part of the validation logic, and needs to be carefully considered for quality and fully tested with both positive and negative tests.
The changes proposed here aren't succinct and it does not fix the originally described issue, as demonstrated by the failing test case.
Thanks for your efforts, but due to the above, I would suggest to either close this PR or it can be revisited at a later time.
const structEnd = storageFieldEnd(o.original); | ||
if (structEnd === undefined) { | ||
return true; | ||
} | ||
|
||
const hasFieldsAfter = original | ||
.filter(field => !isGap(field)) | ||
.some(field => { | ||
const fieldStart = storageFieldBegin(field); | ||
if (field === o.original || fieldStart === undefined) { | ||
return false; | ||
} | ||
return fieldStart > structEnd; | ||
}); | ||
|
||
return hasFieldsAfter; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not clear what this section of code achieves. There should be testcases and changing/removing any of this code should cause those testcases to fail.
Issue
When appending fields to a struct that is at the end of a contract's storage layout, the upgrades validation incorrectly reports an incompatible layout error. This happens despite the fact that this operation is safe, as it only extends into previously unused storage space.
Fix
This PR modifies the storage layout validation logic to properly handle struct field appending when:
The changes include:
Works With
Fixes #1136