Upgradable smartcontracts ,Proxy Contract & Delegate Call
Introduction to Upgradable smartcontracts
In this Article we will discuss on below
1) Why we upgrade smart contracts,
2) How to upgrade smart contracts, and
3) What issues to consider when you’re doing
Why do we need to upgrade smart contracts?
To alter a smart contract to fix a bug they found,
To add additional features, or simply to change the rules enforced by it.
To optimize the code for more efficient use of Ethereum gas
Think of a traditional contract between two parties: if they both agreed to change it, they would be able to do
How to upgrade smart contracts?
Upgrading a smart contract does not mean we modify the code of a smart contract that is deployed—it means we swap one smart contract out for another. We accomplish this so that, in most circumstances, the end user's interaction with the dApp is unaffected.
What would be required if a contract had a bug:
Deploy a new version of a contract
Manually migrate from the old to the new smart contract (very expensive)
Parameterised updates, Update all contracts that interacted with the old contract to use the address of the new one
We have contract upgrades already incorporated into our plugins to save you from having to go through this hassle. This gives us the flexibility to alter the contract code while keeping the state, balance, and address the same.
- Proxy contracts: It will use delegate call which is a low-level function similar to call
you can swap out other smart contracts in the system and simply update the proxy smart contract with the correct address of the newly deployed smart contract. End users of the dApp interact with the proxy directly, and with the other smart contracts only indirectly, via the proxy.
Delegate call is a method in Solidity used to call a function in a target contract from an original contract.
How does Uniswap upgrade its smart contract given that smart contract are immutable once deployed?
UNISWAP uses this proxy contracts - community driven upgrade to a blockchain project.
The basic idea is using a proxy for upgrades. The first contract is a simple wrapper or "proxy" which users interact with directly and is in charge of forwarding transactions to and from the second contract, which contains the logic. The key concept to understand is that the logic contract can be replaced while the proxy or the access point is never changed. Both contracts are still immutable in the sense that their code cannot be changed, but the logic contract can simply be swapped by another contract. The wrapper can thus point to a different logic implementation and in doing so, the software is "upgraded".
Being a smart contract, a proxy has its own Ethereum contract address that is “stable” (i.e. unchanging). So you can swap out other smart contracts in the system and simply update the proxy smart contract with the correct address of the newly deployed smart contract. End users of the app interact with the proxy directly, and with the other smart contracts only indirectly, via the proxy.
Proxy Pattern is achieved through the following two pieces
The proxy smart contract
The execution contract, also called the logic contract or the implementation contract.
User ---- tx ---> Proxy ----------> Implementation_v0
|
------------> Implementation_v1
|
------------> Implementation_v2
The proxy contract uses storage variables to keep track of the addresses of other smart contracts that make up the dApp. This is how it can redirect transactions and call the relevant smart contract.
DELEGATE CALL
How proxy contract pass the message calls to the correct contract. The proxy contract doesn’t just do a regular function call to the logic contract; it uses something called a delegate call.
What happens when the target contract is called from the original contract using the delegatecall()
method is that It executes the function using the context of the original or calling contract.
If the logic contract’s code changes storage variables, those changes are reflected in the proxy contract’s storage variables—i.e. in the proxy contract’s state.
In Ethereum, a function can be represented as 4 + 32*N
bytes where 4 bytes
are for the function selector and the 32*N
bytes are for function arguments.
Function selector : we hash the function's name along with the type of its arguments without the empty space and then take its first 4 bytes
eg : putValue(uint)
Function Argument: is created when you convert each argument into a 32 bytes hex string and then concatenate them
what is a delegate method in solidity ?
A solidity method used to call a function in a target contract from original contract
Where is delegate call method heavily used? proxy (upgradeable) contracts
.delegatecall()
is heavily used within proxy (upgradeable) contracts. Since smart contracts are not upgradeable by default, the way to make them upgradeable is typically by having one storage contract which does not change, which contains an address for an implementation contract. If you wanted to update your contract code, you change the address of the implementation contract to something new. The storage contract makes all calls using .delegatecall()
which allows to run different versions of the code while maintaining the same persisted storage over time, no matter how many implementation contracts you change. Therefore, the logic can change, but the data is never fragmented
How to prevent attacks on contracts which are using delegatecall?
Use stateless library contracts which means that the contracts to which you delegate the call should only be used for execution of logic and should not maintain state. This way, it is not possible for functions in the library to modify the state of the calling contract.