As a researcher engineer at iExec, part of my work is keeping track of all the hot topics in the Ethereum community and evaluating what impact they have on our project. For the most relevant issues, proofs-of-concept are made, before full integration in iExec. Unsurprisingly, Smart Contract upgradability is one of these hot topics. After several months of working on this topic, we think it is time to share our vision on the matter.
Our contributions to smart contract upgradeability were also recently recognized and awarded by Binance Labs:
Why would we need smart contract upgradeability?
If you are reading this, you should be familiar with the notion of smart contracts. They are on-chain pieces of software that can process assets in a trustless manner. Their execution is part of the blockchain transition function, meaning its completely decentralized and auditable. Their memory state is also part of the blockchain, which guarantees a secure and predictable execution. The drawback with this design is that once a contract is deployed there is no way (except doing a hard fork) to change the code they run.
iExec is based on multiple smart contracts. They are the beating heart of our platform, ensuring the security of our users’ assets and the auditability of all transactions. Tools like Etherscan allow you check the status of these contracts memory. You will also find the solidity source code of the contracts, which has been verified to produce the actual bytecode deployed on the blockchain.
While these contracts have been extensively tested andaudited, it is possible that bugs in the source code or in the compiler could be discovered down the line. Even if a contract is bug-free, it is likely that time ends up pointing out missing features that were not initially envisioned by the developer. In both cases, upgradeability can solve the problem by adding, removing, or modifying functions in the smart contract’s code.
Initially, the idea of the upgradeable smart contract can seem contradictory with the immutability of smart contract. It is however not necessarily the case as Openzeppelin discussed inthisblog article.
How does smart contract upgradeability work?
Each smart contract contains 2 parts, the bytecode that contains the execution logic and the memory that can be accessed and modified by transactions. This distinction is important, particularly when considering the different calling mechanisms proposed by the EVM. Similarly to transactions sent by simple wallet, which can trigger the execution of a smart contract, smart contracts can also send transaction trigger further execution. In addition to calls, that are similar to the one performed by wallets, smart contracts can also perform delegatecall and staticcall. Understanding the difference between call, delegatecall, and staticcall is essential to understanding how upgradeability works.
- Call: When a smart contract performs a call, the execution context changed to the targeted address. The bytecode of the targeted address is executed using the memory of a targeted address. This call can read from and write to the memory of the targeted address using the logic of the targeted address. It is aread-writecall.
- Staticcall:A staticcall is similar to a call, with the only difference being that a staticcall internal transaction cannot modify the memory of the targeted address. It is aread-onlycall.
- Delegatecall:When a smart contract performs a delegate call, the bytecode of the targeted address is executed using the memory of the caller. This allows a contract to authorize another contract’s logic to act on its own memory space (thus the name delegatecall). The memory of the targeted address cannot be accessed/modified by this kind of call. it is an on placeread-writecall that uses an external logic.
You might have guessed it, delegatecall are what make the upgradeable contract a thing. A core contract can store all the memory under its wing, and perform delegatecalls to contracts hosting the logic (but not the memory). Changing the address of the target from a contract to another allows the core to keep its memory intact while updating the logic (bytecode of the targeted address).
As a researcher engineer at iExec, part of my work is keeping track of all the hot...