Wizard ERC-20 UUPS Upgradable, order in "is" clause effect on variable storage

TLDR: Testing stepwise ugrade of wizard contracts (adding features and upgrading) I found that if I modified the "is" clause, given by the wizard, to have the new feature contract appended the the end of the "is" clause I could deploy the upgrade.

Is this OK?

UUPS ERC20: Initial deploy OK
Upgrade to ERC20+Mintable: Upgrade deployed OK
Upgrade to ERC20+Mintable+Burnable: Will not deploy upgrade.Variable storage clash.

UUPS ERC20+Mintable+Burnable: Initial deploy OK
Upgrade to UUPS ERC20+Mintable+Burnable+Pausable: Will not deploy upgrade. Variable storage clash.

After moving PausableUpgradeable to the end of the "is" clause and recompiling I could deploy the upgrade.

contract MyToken is Initializable, ERC20Upgradeable, ERC20BurnableUpgradeable, PausableUpgradeable, OwnableUpgradeable, UUPSUpgradeable

To

contract MyToken is Initializable, ERC20Upgradeable, ERC20BurnableUpgradeable, OwnableUpgradeable, UUPSUpgradeable, PausableUpgradeable

I verified contract variable storage by inspecting the corresponding json file under the artifacts/build-info directory.

Hopefully stepwise upgrading using the wizard, then modifying the "is" clause, as needed, when adding features will not impose problems.

Again, anyone see any problems with this?

Cheers

That looks like the right approach to add new inheritance to the end of the list for an upgrade. This would cause the storage variables for those newly inherited contracts to use storage slots that are after all of the other existing inherited contracts' storage slots.

One thing to keep in mind is that adding an inherited contract, even at the end of the list, would cause the storage slots of your actual contract to be shifted as well. Possible solutions are to use storage gaps or keep all storage in inherited contracts only (see this thread). If you are just using the Wizard and do not use storage variables in your contract itself, then this is not a problem.

That's right. So with this pattern, the contract OpenQV# should NEVER have any storage variables of it's own. ALL storage variables must come from inherited OpenQStorageV# contracts.