Storage migration with unlimited gas - Suggestions?

We have a platform with 10 deployed contracts, each one of them with it's own UpgradeabilityProxy storing data. All of our contract are actually on Solidity version 0.5 and OpenZeppelin 2.x. We want to upgrade to Solidity 0.8 and OZ 4.x.
The issue comes when we want to upgrade OZ version, since there are 2 major jumps, so storage will be compromised/corrupted. Luckily we are operating in a private network and we are in complete control of the nodes, so gas price = 0 and we can execute very costful transactions easily.

Our plan is to deploy a new proxy for the new contract and also it's new implementation. Once that's deployed we will query the old contract, and send a transaction to the new one to save all this data.
This is not ideal, first we have some security concerns, we need to be very careful with this "transaction" that we are sending, if we leave some open function behind that can affect every storage variable our contract becomes very vulnerable.
On the other hand, mapping are not easy to 'query', so we will rely on a database that we have to do that querying.
Lastly, we don't know how many storage sets we can make in one transaction without breaking the gas limit. If that limit is too low, we will have to sending a couple thousands transactions to our net.

Eventhough all this issues are a bad smell that we are thinking something wrong, this is our best plan so far.
Have you encountered this situation before? Do you have any ideas/suggestions?

Hey @Uriel_Chami_MB! Migrating storage is super tricky indeed, but it's a good thing that you have no gas costs. I recall the Augur team going through this when they migrated from Serpent (Vyper's predecessor) to Solidity back in the day, you can find more info here.

I'd suggest handling this by having a dedicated migration contract. This contract would only have methods (callable just by your team) for setting up the storage in one or multiple txs. Once the setup is ready, you can then migrate to the actual new implementation contract.

You can also add some tests on the migration contract so you cannot "finish" the migration until these pass. For instance, if you're working with an erc20, you may want to require that the total supply in the new contract matches the value from the old one.

Hope this helps!

1 Like