Essential Guide to Smart Contract Upgradeability

Hariharan Iyappan
Coinmonks
6 min readSep 9, 2022

--

This article assumes some familiarity with the Ethereum development workflow. Namely concepts like smart contract deployment, address and EVM.

Why should you care ?

Smart contracts are written programmatic instructions to the EVM. The EVM then executes them when appropriate (for instance on a RPC call by an user). The process of giving the EVM these instructions is called a deployment. These instructions are given as part of a blockchain transaction, which is eventually added to a block and consensus will be reached. Smart contract deployments being part of the block is very imperative as without it they would be highly unsafe and unfit to handle user funds. This way the immutable nature of a block in the blockchain makes contract deployments also immutable. A smart contract once deployed is immutable and no part of it can be altered further. Ethereum and other EVM compatible blockchains make sure that whenever we deploy a smart contract a new deployment is made. Even if you deploy the same contract again only a new deployment will be made.

Smart contract, fancy name for solidity code
Credits: me.me

Smart contracts are nothing but solidity code written by a programmer. Ethereum development workflow is in many ways quite different from traditional development workflows because of the way EVM, blockchain and solidity are designed. Special care is usually taken to counteract the immutability of a smart contract deployment. Nevertheless bugs do creep in like they do in traditional web2 projects. It would be safe to say that bugs in a web3 project can cause lot more damage than one in web2 projects.

When such bugs are identified after the smart contract deployment the team behind the project needs a way to fix it. The team may come up with a new feature in future for which they need to change the smart contract. In such scenarios we need a way to upgrade a smart contract deployment which is by design immutable. (Note that some highly regarded projects like Uniswap does not use upgradeable smart contracts as a way of guaranteeing to their users that the current version of their protocol will continue to function the same way until eternity. Even when they release newer versions of the protocol the older versions remain in use and upgrading is optional to the user.) While upgrading the smart contract we need to make sure that only the logic of the contract changes but the information in storage remains same. Migrating the storage of one smart contract to another can be its own nightmare. We will avoid this with some fancy solidity footwork, in the next section we will see how.

One more reason to upgrade your smart contract is to keep the address of the deployed smart contract same. Once your project grows big and so many third party clients are connecting to your smart contract changing the address in each and everyone of them will be a challenge.

The Proxy Pattern Saves The Day

The proxy pattern is the widely used pattern for building upgradeable smart contracts. In proxy pattern there is a proxy smart contract and an implementation smart contract. The proxy smart contract is the one to which all RPC calls from users are made. The proxy contract simply stores the address of the implementation contract and relays all calls to it.

DELEGATECALL📞: The life saving helpline

At the heart of the proxy pattern is the DELEGATECALL EVM opcode. When a contract A calls contract B with DELEGATECALL the function called is executed in the context of A. The reads and writes to the storage of the smart contract done by the function call affects the storage of A and not B. Global variables like msg.sender will be same as caller of A inside the function in B. Its easier to understand this in contrast with the CALL EVM opcode. When contract A calls B with CALL EVM opcode the reads and writes in the function called in B affects the storage of B. The global variable msg.sender inside the function call in contract B will be address of contract A. Think of DELEGATECALL as contract A completely trusting contract B and delegating everything to it.

Version 2 is the active implementation here and it can be changed

The delegate call is very imperative to the proxy pattern because it allows us to used the deployed code of the implementation contract with the storage of the proxy contract. When we need to upgrade our smart contract we simply change the address of the implementation contract in the proxy contract to that of the new smart contract deployment. As soon as this is done the proxy contract will start relaying all RPC calls to the new implementation while preserving everything in its storage.

ERC1976: A Proxy Standard

As proxy became such a house hold name in smart contract development standards were developed around it to keep things interoperable. ABI is how a smart contract lets others know what all functions it implements so any other party can use this information to call these functions. In cases where the proxy pattern is used we will be interacting with the proxy contract whose ABI is of no use to us. We need the ABI of the implementation contract to make function calls. It can be a challenge to retrieve the implementation address if different proxy contracts store the implementation address in different manner. ERC1967 introduces a standard for storing the implementation contract address in the proxy contract address. Only knowing that you’re interacting with a proxy is enough to find out the implementation contract address and get its ABI. Etherscan can let you interact with a smart contract using the proxy pattern as long as it follows this standard. Open Zeppelin has an implementation of this proxy standard and some of their proxy contracts inherit from it. I strongly recommend following this standard in your proxy contract.

Proxy Admin: The warden in charge

As you can see anyone cannot be allowed to change the implementation address of the proxy contract. A malicious can simply change it to an implementation which transfers all funds to him 🤑. There is a concept of a proxy admin which is the only account allowed to change the implementation contract address. In Open Zeppelin’s implementation of the proxy deployment plugin the admin is by default the address deploying the proxy contract. The admin can be changed going forward but only by the admin account.

The Transparent Proxy Pattern: A more safe choice

The proxy pattern ran into a vulnerability when there is a clash in function signature between the proxy and the implementation contract. The proxy contract need to have its own functions for upgrading the the implementation smart contract address and a few other purposes. If the functions that are there in the the proxy contract were also to be in the implementation smart contract the user will not be able to call the implementation contract function. To solve the function clash problem a the transparent proxy pattern was introduced.

In the transparent proxy pattern the function call is delegated to the implementation contract only if the call if from an account other than the admin account. If the call is from the admin account it is never delegated to the implementation contract and the functions of the proxy contract is always called. This way the proxy pattern can continue to work promptly even in case of function clash between the proxy contract and the implementation contract.

There are a lot of caveats to writing upgradeable smart contracts. There are a lot of do and don’ts to follow. I won’t cover all of them here. Please read the caveats from the Open Zeppelin documentation here.

An article with hands on walk through of how to write and deploy a upgradeable smart contract with transparent proxy pattern is published here. The same on UUPS proxy pattern is published here. The same for beacon proxy pattern is published here.

Thanks for reading.

Who am I?

I am a full stack blockchain developer, passionate about building a decentralized and potentially more inclusive future. Have a blockchain development need?

Get in touch: 📧 hariharan@alumni.iitm.ac.in

Github

New to trading? Try crypto trading bots or copy trading

--

--

Hariharan Iyappan
Coinmonks

Passionate techie | IITM 2020 | Software Engineer @PhonePe