Skip to main content
added 142 characters in body
Source Link
k06a
  • 3.1k
  • 2
  • 22
  • 35

UPDATE: Check out my new answer with 2 different solutions to the similar issue here: https://ethereum.stackexchange.com/a/142712/3032

Yep, but it is tricky:

pragma solidity ^0.5.0;

contract D {
    function g(uint256 a) public view returns(uint256) {
        return a*2;
    }
}

contract A {
    D public impl;
    
    constructor() public {
        impl = new D();
    }
    
    function() external {
        require(msg.sender == address(this));
        
        (bool success, bytes memory data) = address(impl).delegatecall(msg.data);
        assembly {
            switch success
                // delegatecall returns 0 on error.
                case 0 { revert(add(data, 32), returndatasize) }
                default { return(add(data, 32), returndatasize) }
        }
    }
    
    function f(uint256 a)
        public
        view
        returns(uint256)
    {
        (bool success, bytes memory data) = address(this).staticcall(
            abi.encodeWithSelector(
                impl.g.selector,
                10
            )
        );
        
        assembly {
            switch success
                // delegatecall returns 0 on error.
                case 0 { revert(add(data, 32), returndatasize) }
                default { return(add(data, 32), returndatasize) }
        }
    }
}

Yep, but it is tricky:

pragma solidity ^0.5.0;

contract D {
    function g(uint256 a) public view returns(uint256) {
        return a*2;
    }
}

contract A {
    D public impl;
    
    constructor() public {
        impl = new D();
    }
    
    function() external {
        require(msg.sender == address(this));
        
        (bool success, bytes memory data) = address(impl).delegatecall(msg.data);
        assembly {
            switch success
                // delegatecall returns 0 on error.
                case 0 { revert(add(data, 32), returndatasize) }
                default { return(add(data, 32), returndatasize) }
        }
    }
    
    function f(uint256 a)
        public
        view
        returns(uint256)
    {
        (bool success, bytes memory data) = address(this).staticcall(
            abi.encodeWithSelector(
                impl.g.selector,
                10
            )
        );
        
        assembly {
            switch success
                // delegatecall returns 0 on error.
                case 0 { revert(add(data, 32), returndatasize) }
                default { return(add(data, 32), returndatasize) }
        }
    }
}

UPDATE: Check out my new answer with 2 different solutions to the similar issue here: https://ethereum.stackexchange.com/a/142712/3032

Yep, but it is tricky:

pragma solidity ^0.5.0;

contract D {
    function g(uint256 a) public view returns(uint256) {
        return a*2;
    }
}

contract A {
    D public impl;
    
    constructor() public {
        impl = new D();
    }
    
    function() external {
        require(msg.sender == address(this));
        
        (bool success, bytes memory data) = address(impl).delegatecall(msg.data);
        assembly {
            switch success
                // delegatecall returns 0 on error.
                case 0 { revert(add(data, 32), returndatasize) }
                default { return(add(data, 32), returndatasize) }
        }
    }
    
    function f(uint256 a)
        public
        view
        returns(uint256)
    {
        (bool success, bytes memory data) = address(this).staticcall(
            abi.encodeWithSelector(
                impl.g.selector,
                10
            )
        );
        
        assembly {
            switch success
                // delegatecall returns 0 on error.
                case 0 { revert(add(data, 32), returndatasize) }
                default { return(add(data, 32), returndatasize) }
        }
    }
}
Source Link
k06a
  • 3.1k
  • 2
  • 22
  • 35

Yep, but it is tricky:

pragma solidity ^0.5.0;

contract D {
    function g(uint256 a) public view returns(uint256) {
        return a*2;
    }
}

contract A {
    D public impl;
    
    constructor() public {
        impl = new D();
    }
    
    function() external {
        require(msg.sender == address(this));
        
        (bool success, bytes memory data) = address(impl).delegatecall(msg.data);
        assembly {
            switch success
                // delegatecall returns 0 on error.
                case 0 { revert(add(data, 32), returndatasize) }
                default { return(add(data, 32), returndatasize) }
        }
    }
    
    function f(uint256 a)
        public
        view
        returns(uint256)
    {
        (bool success, bytes memory data) = address(this).staticcall(
            abi.encodeWithSelector(
                impl.g.selector,
                10
            )
        );
        
        assembly {
            switch success
                // delegatecall returns 0 on error.
                case 0 { revert(add(data, 32), returndatasize) }
                default { return(add(data, 32), returndatasize) }
        }
    }
}