Use a delegate call to upgrade a Solidity smart contract. A delegate call function runs code of the call in callers context(storage, msg.sender, msg.value). Keep in mind state variables must be in the same order for caller and callee.
How a delegate call works in Solidity
The contract below is an example of how to use a delegate call in solidity. The concept is:
- Your users interact with contract A
- Contract A calls into contract B
- Then at some point in the future you want to upgrade contract B so you create contract C (an upgrade of contract B)
- You then change contract A to interact with contract C
- Your users are abstracted from the change in contracts
Experiment with the contract below and learn the basics of a simple contract. Deploy the contract below to the Ethereum test network using Remix. Try to add another function.
//to make this work I needed to use a lot of gas in the test environment or it will fail
pragma solidity ^0.6.0;
//Original contract
contract Satellite1 {
//these state variables need to be in the exact same order of contract A when performing a delegate call
uint public num;
address public sender;
uint public value;
constructor() public { owner = msg.sender; }
address payable owner;
//capture the following data and save it in the state variables
function setVars(uint _num) public payable {
num = _num;
sender = msg.sender;
value = msg.value;
}
//send funds back to the owner and destroy the contract
function Destruct() public {
selfdestruct(owner);
}
}
//Now lets say we want to upgrade contract B and we create B2
contract Satellite2 {
//these state variables need to be in the exact same order of contract A when performing a delegate call
uint public num;
address public sender;
uint public value;
constructor() public { owner = msg.sender; }
address payable owner;
//capture the following data and save it in the state variables
function setVars(uint _num) public payable {
//lets multiply the num by 2 so we can see a change
num = 2 * _num;
sender = msg.sender;
value = msg.value;
}
//send funds back to the owner and destroy the contract
function Destruct() public {
selfdestruct(owner);
}
}
contract MainContract {
uint public num;
address public sender;
uint public value;
//this is a delegate call to contract B
//we are going to send ether to contract so we are making it payable
function setVars(address _contract, uint _num) public payable {
//this is to make a delegate call to another contract
//the delegate call will produce 2 outputs. success if there are no errors and the output of the function in bytes
(bool success, bytes memory data) = _contract.delegatecall(
//in abi sig we need to pass in the function signature that we are calling
abi.encodeWithSignature("setVars(uint256)", _num)
);
}
}
Try it in Remix
This code is for learning and entertainment purposes only. The code has not been audited and use at your own risk. Remember smart contracts are experimental and could contain bugs.
Click here for more information about how to use the Ethereum test network and how to obtain test ETH.
1 thought on “Delegate call to upgrade a solidity smart contract”