ethereumblockchainsoliditysmartcontractsevm

Bypassing Solidity's assembly return blocking further function execution


Say I have

contract Bar {

    function blockingFunction() public pure returns (bool) {
        assembly {
            return(0,0x20)
        }
    }
}

contract Foo is Bar {

    function foo() public pure returns(bool) {
        bool result = blockingFunction();
        require(result == true, "msg");
        return result;
    }
}

Note that blockingFunction is a snip from a larger function that does something useful and actually returns a boolean.

The call blockingFunction() inside foo makes the following code unreachable, as return inside assembly blocks further execution. I first noticed this when hardhat complained as noted here. From the docs it says

return(p, s)   end execution, return data mem[p…(p+s))

My way of bypassing this was to call the function as this.blockingFunction() (or not inherit Bar but pass it inside Foo constructor and call blockingFunction externally via Bar from foo) which worked inside hardhat tests, but now when testing this on a testnet, I get the same problem. How do I bypass this and actually use the return value inside a contract?

There were a couple of answers saying require fails after the blockingFunction call. I would have noticed this either in hardhat test or with testnet.


Solution

  • return opcode returns from entire contract execution not only function execution. Instead just return from the assembly like this

    contract Bar {
        function blockingFunction() public pure returns (bool val) {
            assembly {
                let freePointer := mload(0x40)
                // store true
                mstore(freePointer,true)
                // return the stored value without return opcode
                val:=mload(freePointer)
            }      
        }  
    }
    
    contract Foo is Bar {
        function foo() public pure returns(bool) {
            bool result = blockingFunction();
            require(result == true, "msg");
            return result;
        }
    }
    

    proof of work:

    enter image description here