[Ethereum] Use of delegatecall with msg.data

delegatecallsolidity

I'm trying to understand below code:

pragma solidity ^0.4.23;

contract Relay {
    address public currentVersion;
    address public owner;

    modifier onlyOwner() {
        require(msg.sender == owner);
        _;
    }
    function Relay(address initAddr) {
        currentVersion = initAddr;
        owner = msg.sender; // this owner may be another contract with multisig, not a single contract owner
    }

    function changeContract(address newVersion) public onlyOwner(){
        currentVersion = newVersion;
    }

    function() {
        require(currentVersion.delegatecall(msg.data));
    }
}

This code is for maintaining version of a contract, but I'm not getting use of fallback function here.
I know that msg.data is complete calldata which is non-modifiable, but have no idea use of delegatecall here.

Best Answer

The fallback function gets called when no other function matches the calldata signature. In this code, the fallback functions is used as a universal function.

This is done by forwarding the calldata to the contract at currentVersion. Forwarding the calldata to another smart contract results in it running the proper funcion. There are two ways to do this: address.call and address.delegatecall. The difference between those is the context in which the receiving contract is going to run the code.

With delegatecall, the receiving contract accesses the Relay contract's storage. This way, the receiving contract can alter all fields of the Relay.

Effectively, by updating currentVersion, Relay can update it's code without changing it's address or migrating it's storage contents.

Docs:

Related Topic