Since Byzantium we can implement upgradable proxy contracts much easier with the use of returndatacopy and returndatasize assembly instructions. This means we no longer have to register return types and sizes like when using the EtherRouter.

The most reliable way we know how to structure a proxy contract is like the Zeppelin Proxy where the delegatecall is made in assembly. However, it also seems to work when doing the delegatecall as a high level Solidity call where the proxy contract fallback function looks like this instead:

function () public {

    bool callSuccess = upgradableContractAddress.delegatecall(msg.data);

    if (callSuccess) {
        assembly {
            returndatacopy(0x0, 0x0, returndatasize)
            return(0x0, returndatasize)
        }
    } else {
        revert();
    }
}

This approach (see the whole proxy here) is a bit more succinct and requires less knowledge of assembly to understand. My minimal tests for this approach seem to work.

So in what situations will this high level approach not work?

And if there aren't any, how likely is it that the compiled bytecode for the high-level delegatecall will change between versions of Solidity, breaking this approach for those versions?

  • 1
    You might want to contribute to the discussion going on github.com/ethereum/EIPs/pull/897 – skang404 Mar 1 at 23:04
  • 1
    thank you for this great example code. I don't have an answer to your quesiton but wondered if you could help me? I'd like to use this method but I only care about one specific function. When using delegatecall would I specify the function explicitly or will it be included in msg.data? if I do it explicitly would it look like this? gist.github.com/okwme/a86e32a843bc15453002c5a0229da021 – okwme Mar 22 at 14:43

One issue is that you copy your data into memory starting at address 0. This will work for return sizes less than 64 bytes, but will start overwriting other memory at that point.

Instead you should do something more like

let m := mload(0x40)
returndatacopy(m, 0, returndatasize)
return(0, returndatasize)

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.