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.
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: