Trey asked on Telegram:
So I guess I’m just struggling with what the “intended” workflow is here for making contract updates. Say I’ve got a project with:
CustomERC20 is IERC20 PausableCustomERC20 is CustomERC20 MyToken is PausableCustomERC20
Given what has been recommended, if I want to deploy a new version of
MyToken, I should make a
MyTokenV2 contract that either inherits from
MyToken or is just copy of it with a compatible storage structure.
But what if I make a change to
PausableCustomERC20? If I truly want the migrations to be reproducible, then it seems like going the route of renaming to “v2” is going to result in me having the rename every class in the inheritance chain to V2. That would logically extend to the OpenZeppelin contracts themselves if I upgrade from one version to another, but you guys don’t update the contract names like this when you make updates, so I don’t really have that option short of forking the Openzeppelin code.
So for example “V1” could include
Then for V2, that made a change to
PausableCustomERC20, I would need to create
contracts/v2/PausableCustomERC20.sol, and then
contracts/v2/PausableCustomERC20.sol could inherit from either from a new
contracts/v2/customERC20.sol or still just from
contracts/v1/CustomERC20.sol (since the file didn’t change).
If, as suggested, I need to also publicly change my contract name to be clear/transparent that the contract has changed, then I’ll need to also update the code at each level of the hierarchy to refer to the classes as
PausableCustomERC20V2, etc. instead of just referencing them with the same class names and relative folder structure as before (i.e. if I just create a parallel path under
contracts/v2, etc. so all the code importing other contracts with relative paths doesn’t have to be modified)
As a parallel, when OpenZeppelin releases a new version of it’s contracts, it versions the release, but leaves the contract names the same between versioned releases, which is pretty standard practice in the software world.
I’m willing to go a different route, but the dependency hierarchy of “just make a MyTokenV2” doesn’t seem to me like it works all that great either, as you essentially end up having to fork every contract in the hierarchy every time you make any change to that contract or any parent class, and constantly updating all the code to add “v2”, “v3”, etc. to referenced classes seems strange.
I feel like I must be overthinking this, but I’m just trying to wrap my head around how people make this work in practice. The “create a release commit with any changes and deploy that commit with consistent contract names” approach feels clean, but requires that every release be run sequentially through the release commits to recreate current state.
The “create a full copy of the hierarchy in the main branch the for every release” also seems like it would work pretty well, so long as we can keep the contract names the same and don’t have to then slap a “v2” at the end of every class name.
If I’m going to increment the contract names to append “v2”, “v3”, etc., It feels like it is going to get messy forking every class name and modifying inheritance hierarchies for every change.
Any pointers on how other people managing this process?