Upgradeable Solidity Smart Contracts. Part 1 — Versioning

--

Smart contracts in the Ethereum network are immutable by default. However, for some scenarios, it is desirable to be able to modify them. Updating a smart contract changes the business logic of the contract while maintaining its state. It implies updating the code base, but the contract's address, state, and balances must remain unchanged.

Why is this necessary?

Firstly, errors or potential vulnerabilities may be found in the smart contract that must be fixed. Here, it is necessary to stipulate that we have time to do this if the consequences of the hack have yet to occur. Otherwise, it no longer makes sense.

Secondly, a scenario may be required when the smart contract project needs improvements or new functionalities. This may usually be required at the start when the project is changing quickly and dynamically.

Important! To avoid malicious actions, update control should be decentralized. That is, it should not be under the control of one address. You can use multi-sig or build a full-fledged DAO to manage the code update process.

There are several ways to change the code of smart contracts:

  1. Create multiple versions of smart contracts and migrate the state from the old contract to the new contract.
  2. Create multiple smart contracts to store state and business logic separately.
  3. Use Proxy patterns to delegate function calls from an immutable proxy contract to a mutable logical contract.
  4. Use Strategy pattern. Create an immutable main contract that interacts with flexible auxiliary contracts and relies on them to perform certain functions.
  5. Use the Diamond pattern to delegate function calls from a proxy contract to logical contracts.

We will discuss each of the methods in detail below. The most popular is the proxy pattern. If you need a smart contract code example, go there immediately.

Versioning

The basic idea is to create a new contract and migrate the state from the old contract to it. Initially, the newly deployed contract should have an empty storage. The process of migrating to the new version might look like this:

  1. Create a new contract instance.
  2. Transfer state or migrate data. This can be done in two ways:
  • On-chain. Migration using smart contracts.
  • Off-chain. Data collection from the old contract occurs outside the blockchain. At the last stage, the collected data is written to the address of the new contract.

3. Update the new contract address for all contracts, services, and client applications. That is, replace the old address with a new one.

4. Convince users and other projects to use the new contract.

Migrating data is relatively straightforward but can take time and require significant gas costs. Not all users will want to upgrade to the new version, so support measures for such users and old contracts must be considered.

On-chain migration

Migration using smart contracts. This migration can be implemented in two ways:

  1. At the user’s expense, when we offer the user to pay for gas, we implement a migration smart contract that, when called, identifies the user and transfers the functionality to a new contract.
  2. We can do this at the protocol's expense. We implement a migration smart contract that will accept a list of addresses and transfer the state to a new contract. In this case, the project covers gas costs.

Off-chain migration

We read all the data from the blockchain. If there was a hack or a failure, it is necessary to read up to the problematic block. In this case, it is better to suspend the work of the current smart contract (if possible). All public primitives are easy to read. It is a little more complicated for private variables, but you can rely on events or use the getStorageAt() method to read such variables from storage.

You need to understand how events are stored, indexed, and filtered outside the blockchain to restore data from events. This is well described here. One option for collecting data is to use the Google BigQuery API service. I have prepared several examples and a short guide for the Google BigQuery API. After all the data from the old contract is collected, it must be written to the new contract.

Hey, professionals, let’s connect on LinkedIn! 🤝

https://www.linkedin.com/in/dmytronasyrov

Feel free to drop a “Hi” at Pharos Production, where we bring software to life! 👋✨

https://pharosproduction.com

“Join our exciting journey with Ludo — the reputation system of the Web3 world! 🌍✨”

https://ludo.com

--

--

Dmytro Nasyrov | Pharos Production | Founder & CTO
Dmytro Nasyrov | Pharos Production | Founder & CTO

Written by Dmytro Nasyrov | Pharos Production | Founder & CTO

https://pharosproduction.com | blockchain, web3, DeFi, FinTech Software Development Services 22+ years turning ideas into scalable software and managing teams.

No responses yet