Updating inheritance of contract during contract upgrade

wanted to confirm if it is possible to update the inheritance of a contract during upgrade. For example, adding another parent contract (not removing existing parent contract).

Existing Contract Format:
contract MyContract is IMyContract, PausableUpgradeable {}

Upgraded Contract Format:
contract MyContract is IMyContract, PausableUpgradeable, ProxyRouter {}

:computer: Environment

Truffle v5.4.6

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

@nyg's answer is correct.

@kombos also asked specifically if they can add another parent contract at the end. The answer to that is generally yes, but in some edge cases it can change the linearization which can affect storage layout. The Upgrades plugins should alert you if that happens.

@frangio Thanks for your answer! Even though my solution might be correct from a Solidity point of view, I ran into this limitation on Truffle's side: Storage layout upgrade with `hardhat-upgrades`.

I was able to modify the file in .openzeppelin as you advised and re-run the proxy upgrade migration successfully, but this means I can't run all my tests at once…