I am attempting to perform operations on returned data from delegatecall opcode using a similar familiar proxy pattern:

assembly {
    let ptr := mload(0x40) // load empty memory address pointer
    calldatacopy(ptr, 0, calldatasize()) // copy calldata to memory
    mstore(0x40, add(ptr, calldatasize())) // reset free memory pointer

    let outptr := add(ptr, calldatasize()) // new free memory pointer for output location
    success := delegatecall(gas(), implementation, ptr, calldatasize(), outptr, 0) // delegate call passing all calldata returning 0 on failure, 1 on success

    returndatacopy(outptr, 0, returndatasize())

The resulting returned data looks something like this (including my returned revert reason):


So to help break it down, this is as far as I've understood this layout.

  • There is an initial 4-bytes: 0x08c379a0

  • Then follows a 32-byte memory slot filled with: 0x0000000000000000000000000000000000000000000000000000000000000020 which itself contains a value = 32

  • Then follows the next 32-byte slot with the expected data; an array length: 0x000000000000000000000000000000000000000000000000000000000000000f = 15 bytes

  • And the array itself, in this case a string, in the next 32-byte slot: 0x6e6f7420696d706c656d656e7465640000000000000000000000000000000000 - "not implemented" which is my error string 15-bytes long, the rest of the slot 0s.

  • Then follows 0's for the rest of the 100-byte-long return data.

My questions are:

  • What does the leading 4-bytes 0x08c379a0 mean? There is a different leading 4-bytes it seems depending on what the returned data is.
  • What is the preceding padded 0x20 that appears before my error message array?
  • Why is the total returndata length 100-bytes that is filled with mostly 0's where my reversion messages do not fill it? If I lengthen my revert return reasons beyond the 100-bytes, the returndata also lengthens accordingly.

1 Answer 1


This answer provides a complete view of the exact issue I stumbled upon here.

  • 0x08c379a0 is the function signature of Error(string) which is what require or revert failures use.
  • The 0x20 preceding the string data is an offset usually included with function call blobs that offsets dynamic variables (such as strings or byte arrays) to the memory area that encodes them. Here it's only a single memory slot (32-byte) offset from the start of this header block (only skipping the offset itself).
  • Since it takes 3 memory slots for the data itself (offset, array length and array) where the array data itself fits into a single slot, we have 32*3=96 plus the remaining 4 bytes for the function signature 96+4=100, and we reach our elusive 100-byte returndatasize.

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.