3

I am new to inline assembly. I have tried understanding different opcodes, and understood quite a bit, but still not be able to correlate them in context to STATICCALL opcode. Kindly help me understand what's happening here in this piece of code

function getUint(address addr, bytes memory data) internal view returns (uint result) {
    result = 0;

    assembly {
        let status := staticcall(16000, addr, add(data, 32), mload(data), 0, 0)

        // Success!
        if eq(status, 1) {
            if eq(returndatasize(), 32) {
                returndatacopy(0, 0, 32)
                result := mload(0)
            }
        }
    }
}

As far as I have understood from solidity assembly documentation,

STATICCALL: identical to call(g, a, 0, in, insize, out, outsize) but does not have v value and do not allow state modifications

How do the parameters in the above code represent in, insize, out and outsize?

1 Answer 1

3

From the call you have

staticcall(16000, addr, add(data, 32), mload(data), 0, 0)
  • 16000 is gas
  • addr target address
  • add(data, 32) input
  • mload(data) input size
  • 0 output
  • 0 output size

For bytes the first 32 bytes are the size and it follow the raw data. mload(data) read 32 bytes pointed by data (it returns the length of data). add(data, 32) it moves the pointer to the raw data skipping the size field.

4
  • Thanks for the info. I understood the input and inputsize now, but can you explain a bit, why the output and output size are 0? Jun 7, 2021 at 5:23
  • And data here is actually the function signature as, abi.encodeWithSignature("myFunction()"). So, does it mean, mload(data) will read 32 bytes pointed by this signature, and add(data, 32) will point the raw data for it? Jun 7, 2021 at 5:57
  • @RazorSharp Setting output and output size to 0 is due to historical reason. In early EVM versions you had to know the output size in advance, it was a limiting factor for some kind of operations (proxy contracts) so in the Bizantium fork new opcodes were introduced ReturnDataSize and ReturnDataCopy. This allow the caller to determine the output size after the call (ReturnDataSize) and allowing copying to memory (ReturnDataCopy).
    – Ismael
    Jun 9, 2021 at 3:27
  • @RazorSharp The abi.encodeWithSignature(..) encodes a function call using the Contracts ABI. Since myFunction() doesn't have any parameters it should return the function identifier which is in hexa "c3780a3a", mload(data) should be 4 and add(data, 32) will point to the function identifiier.
    – Ismael
    Jun 9, 2021 at 3:40

Your Answer

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

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