0

I know that: return(p, s): end execution, return data mem[p…(p+s)).

I want to return something in memory but not a multiple of bytes32. For example, I want to return 1 byte:

pragma solidity 0.8.20;
contract Adder {
    function add(uint a, uint b) public pure returns (uint8) {
        assembly {
            mstore(0x0, add(a, b))
            return(0x0, 8)
        }
    }
    function test() public pure returns(uint8){
        return add(1,2);
    }
}

But when I call add(1,2) and test() in Remix, there is something wrong:

Failed to decode output: Error: data out-of-bounds (length=8, offset=32, code=BUFFER_OVERRUN, version=abi/5.7.0)

The doc doesn't say we should use a multiple of bytes32. 1 byte is okay in theory? But What happened?

1 Answer 1

0

The error happened because Remix expected a uint8 as output. This is encoded as 32 bytes, so when it tries reading the value it fails ("data out-of-bounds" error).

It's not a blockchain or solidity error. If you were sending a transaction it would go through without reverting. The problem is that Remix will interpret the output as uint8 abi-encoded.

I don't think there's a way in Remix to get the value without attempting the abi-decoding. So the only solution is making a "raw" eth_call and reading the returned value directly.


BTW.

        assembly {
            mstore(0x0, add(a, b))
            return(0x0, 8)
        }

The value of add(a, b) will be "aligned to the right". So if you want to return it you have to do:

        assembly {
            mstore(0x0, add(a, b))
            return(24, 32)
        }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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