0

Is it safe to reuse memory for both inputs and ouputs when working with assembly call? If not, what can go wrong?

Contract below uses assembly to call Target

contract YulStaticCall {
    function test_staticcall(address a, bytes calldata data) public view {
        assembly {
            let p := mload(0x40)
            // Copy calldata to memory
            calldatacopy(p, data.offset, data.length)
            // HERE - no need to update free memory pointer?
            // mstore(0x40, add(p, data.length))

            let ok := staticcall(gas(), a, p, data.length, 0, 0)

            if iszero(ok) { revert(0, 0) }

            // p := mload(0x40)
            let return_data_size := returndatasize()
            // Copy returned data to memory
            // HERE - is it safe to overwrite memory that was used for inputs?
            returndatacopy(p, 0, return_data_size)
            return(p, return_data_size)
        }
    }

    function test_abi_decode_uint256(address a, bytes calldata data)
        public
        view
        returns (uint256)
    {
        test_staticcall(a, data);
    }
}

contract Target {
    function return_uint256(uint256 x) public pure returns (uint256) {
        return x;
    }
}

1 Answer 1

1

You can reuse the same memory without problems. You don't even need to read the free memory pointer in your example, and let p := 0 to save more gas.

When messing with memory, we only need to keep in mind that any solidity code after the assembly block will assume we followed the usual rules. In any case, your code ends with a return so no problem arises.

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.