Upgrading Ink! contracts
Smart contracts are by default immutable in nature. Once uploaded to the chain, we cannot change its runtime logic or storage structure. This is an inconvenience since upgrades are common in software development. Even though the original contract is immutable, we can perform an upgrade of the contract by alternative means. Currently, there are three separate mechanisms to upgrade a contract that can be used according to the suitable use case.
In this upgrade mechanism, we upload a new proxy contract with a mechanism to forward calls that are not implemented in the proxy contract to the actual contract. For this, we would need to set the actual contract account ID as
Proxy.forward_to
, for the call forwarding. Since we are setting the Contract Address to forward calls in the proxy contract, the actual contract must be deployed first.If we deploy V2 of the contract with new methods, we can set the
Proxy.forward_to
parameter in the Proxy contract, with the address of the V2 contract. After that, all the calls to the Proxy contract would be directed to V2. Migrating the storage V1 to V2 falls under the responsibility of the V1/V2 contract developers.

Forwarding Calls (Proxy Pattern)
This is similar to forward calls pattern. The only difference is that the unmatched calls are delegated using the upgraded contracts code hash. Since code hash can also be updated, the smart contract can be upgraded any number of times. The V1/V2 contracts does not need to be deployed (call the constructor) after uploading, since the proxy contract calls the V1/V2 contract using the code hash. The storage is lazy initialized using the
Upgradeable
wrapper trait.
Delegate Calls
This is the simplest approach to upgrading an Ink! contract. In this approach, we change the runtime execution code of a contract by changing its code hash to that of a new contract. It is basically replacing the old contract with new runtime logic. Example Code: Set Code Hash

Update Runtime
There is no straightforward way to upgrade existing storage in case of a change in the storage existing layout of a contract. If we need to upgrade a contract with changes in layout data structure, then the most accessible path would be to use a forward-calls pattern in which the upgraded contract initializes its own storage and imports old records from previous contract storage. Developers would need to write their own data migration procedure for this.
Last modified 8mo ago