Hi, I have situation like below, so I have
layout:
uint256
Data (struct)
I want to add to Data struct at the end, additional variable uint256 data3
Running this with upgrades raises error that layout is not compatible. Is this expected behaviour? As I see it would not affect any layout as information is added at the end of Data struct and Data struct is last variable in storage.
contracts/test/TestContractV2.sol:19: Upgraded `data` to an incompatible type
- Bad upgrade from struct TestContract.Data to struct TestContractV2.Data
- In struct TestContractV2.Data
- Added `data3`
Thank you in advance.
Code to reproduce
// INITIAL CONTRACT LAYOUT
contract TestContract is OwnableUpgradeable {
struct Data {
uint256 data1;
uint256 data2;
}
/// @custom:storage-location erc7201:openzeppelin.storage.TestContract
struct TestContractStorage {
string _version;
Data data;
}
// keccak256(abi.encode(uint256(keccak256("f.storage.TestContract")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant TestContractStorageLocation =
0xca9ab86016606c0de0fd52d033f885973b1d29b412e722f528ec4c1b4b023800;
function _getTestContractStorage()
private
pure
returns (TestContractStorage storage $)
{
assembly {
$.slot := TestContractStorageLocation
}
}
}
// UPGRADE
contract TestContractV2 is OwnableUpgradeable {
struct Data {
uint256 data1;
uint256 data2;
uint256 data3;
}
/// @custom:storage-location erc7201:openzeppelin.storage.TestContract
struct TestContractStorage {
string _version;
Data data;
}
// keccak256(abi.encode(uint256(keccak256("f.storage.TestContract")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant TestContractStorageLocation =
0xca9ab86016606c0de0fd52d033f885973b1d29b412e722f528ec4c1b4b023800;
function _getTestContractStorage()
private
pure
returns (TestContractStorage storage $)
{
assembly {
$.slot := TestContractStorageLocation
}
}
Environment
hardhat-upgrades 3.9.0 . transparent proxy