Contract Migration
Last updated
Last updated
In attacks where private keys are compromised, it may be impossible to fix the deployed smart contract, even if the contract has an upgradability mechanism. A new instance of the contract will need to be deployed and properly initialized to restore functionality to your users.
Hence, smart contract developers should integrate a migration procedure during the contract design phase.
A migration has two steps:
Recovering the data to migrate
Writing the data to the new contract
Public variables - use public getter functions
Private variables - use events, or compute the location in memory of the variable, then retrieve its value using: await provider.getStorageAt(address, slot)
Arrays - number of elements is known; use methods above
Mappings - keys are not stored, but are required to access mapping values. To simplify off-chain tracking, emit events when a value is stored in a mapping.
For token contracts, often we can find the list of all the holders by tracking the addresses of the Transfer events.
Once holder addresses are obtained, query the function to recover the balance associated to each holder.
For simple variables, set the values through the constructor of the contract.
If there is a large amount of data that cannot be sent with one transaction, the migration has to be split into several. To do this, add an initialisation state to the contract where only the owner can change the state variables, and users can’t take any action.
To reduce the cost, the migration of the balances can be implemented with a batch transfer function that lets you set multiple accounts in a single transaction.
Using the data separation pattern over the delegatecallproxy one. If your project has a clear abstraction separation, upgradeability using data separation will necessitate only a few adjustments. The delegatecallproxy requires EVM expertise and is highly error-prone.
Document the migration/upgrade procedure before the deployment. If you have to react under stress without any guidelines, you will make mistakes. Write the procedure to follow ahead of time. It should include:
The calls that initiate the new contracts
Where are stored the keys and how to access them
How to check the deployment! Develop and test a post-deployment script.
References:
The initialization state can be implemented with a and a boolean indicating the initialization state.
Favoring over upgradeability. Migration system have many of the same advantages than upgradeable, without their drawbacks.