Updating inheritance of contract during contract upgrade

I'm also looking to have more info on this :).

The problem is that by adding a new base class, we're going to have a storage layout incompatibility (if both the new base contract and the derived contract have state variables). We're going to get the “New variables should be placed after all existing inherited variables” error when upgrading the proxy.

What I was trying to do:

contract BoxV1 is Initializable, OwnableUpgradeable {
    uint256 public value;
    // ...
}

contract BoxV2 is Initializable, OwnableUpgradeable, PausableUpgradeable {
    uint256 public value;
    // ...
}

Error:

../@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol:28: Inserted `_paused`
  > New variables should be placed after all existing inherited variables

A solution I found, while still using the Transparent Proxy Pattern, is to place any state variables of the Box contract into another contract which will be inherited by the Box contract:

contract BoxStorage {
    uint256 public value;
    uint256[49] private gap;
}

contract BoxV1 is BoxStorage, Initializable, OwnableUpgradeable {
    // ...
}

This way we are sure that BoxStorage state variables come first in the storage layout and that the Box contract has the ability to inherit from other classes in the future.

I added the gap variable in BoxStorage to keep the ability to add new storage variables. I haven't done any testing yet, and I would gladly welcome any input on this “solution” :smile:.

1 Like