Delegate call to upgrade a solidity smart contract

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.

Next Review – Create an covered call option smart contract in Solidity

Ledger Nano X - The secure hardware wallet

1 thought on “Delegate call to upgrade a solidity smart contract

Leave a Reply