I think this may be the use case we were struggling to find when we were discussing it.
One option is to change the error numbers to distinguish a return from a contract from a return to a non-contract address (empty or EOA).
i.e. instead of
0 - success
1 - revert
2 - failure
we could do
0 - successful call
1 - successful non-call
254 - failure (-2 uint 8)
255 - revert (-1 uint 8)
So we can determine from the call what happened. The downside is it would eliminate the (ISZERO RJUMPI[n]) check and require a couple of exra opcodes per call (PUSH1[127] LT RJUMPI[n]) but allow an executed onReceived to be distinguished from a transfer or no-op call. Although in cases where you only want to accept successful and want to hot-path that handling ISZERO still works
Other alternatives that were rejected
- Use only PAY to do transfers, this prevents some calls from requiring payment, such as WETH
- Require Value when calling a non-contract and if not failure, it felt too special cased.
I’ll bring this up in the EOF call this wendsday, as I think it is the example we were missing. Solidity had brought it up but the collective seeme persuaded by the AA argument.