Skip to content

Cannot append to struct at the end of storage layout #1136

@ericglau

Description

@ericglau

When appending to the end of a struct, and there are no other storage variables after that struct, this should be allowed. This should work for both regular variables and namespaced storage, as long as the struct is at the end of the storage layout.

However, this currently gives an error Bad upgrade from struct MyContractV1.MyStruct to struct MyContractV2.MyStruct

Example:

contract MyContractV1 {
    struct MyStruct {
        uint256 x;
        uint256 y;
    }

    MyStruct s;
}

contract MyContractV2 {
    struct MyStruct {
        uint256 x;
        uint256 y;
        uint256 z;
    }

    MyStruct s;
}

Example with namespaced storage:

contract MyContractV1 {
    struct MyStruct {
        uint256 x;
        uint256 y;
    }

    /// @custom:storage-location erc7201:example.main
    struct MyStorage {
        MyStruct s;
    }
}

contract MyContractV2 {
    struct MyStruct {
        uint256 x;
        uint256 y;
        uint256 z;
    }

    /// @custom:storage-location erc7201:example.main
    struct MyStorage {
        MyStruct s;
    }
}

Running upgrades.validateUpgrade from v1 to v2 with the above examples gives an error like:

Error: New storage layout is incompatible

contracts/MyContractV2.sol:12: Upgraded `s` to an incompatible type
  - Bad upgrade from struct MyContractV1.MyStruct to struct MyContractV2.MyStruct
  - In struct MyContractV2.MyStruct
    - Added `z`

Originally reported in https://forum.openzeppelin.com/t/wrong-indication-of-incompatible-layout-after-upgrade/43335

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions