0

If a contract does returns something, (whether a string or return true/return false) how to get it’s return value ?
I mean where does the return value is stored ? Is necessary to use RETURNDATACOPY or does the value is on the stack in the case of return true/return false ? If it’s on the stack, how to know if the contract exited because of a problem in execution (like revert or out of gas) or because execution was successful at returning false ?

Of course, I’m talking while knowing the site or the type of return value so that using RETURNDATASIZE isn’t required. I don’t want a Solidity or Vyper answer, but to know how things works at the bare low‐level.

1

There are a bunch of questions here which I will try to unpack.

1. How to get its return value?

When a contract terminates in the EVM, it has a halting state, denoted H. This halting state takes three possible values:

  • () when execution needs to halt without return value
  • the empty set, let's call it None when execution needs to continue
  • or a list of two numbers (offset, length) which correspond to a returning value

The convention is for offset, length to correspond to the bytes in memory mem[offset, offset + length - 1] corresponding to return data.

2. Where is the return value stored?

Your question though is how does the return data get there? Well, typically the compiled contract will populate the machine memory with the required data before termination.

3. Is it necessary to use RETURNDATACOPY?

RETURNDATACOPY is actually for the special case where one contract calls another and needs to collect the return data from that other contract. Conceptually, when another contract is called, the parent contract can access the return data in a variable called output or mu_o in yellow paper notation.

The goal of RETURNDATACOPY is to copy data from mu_o into the current memory mu_m so that it can be returned.

4. If it's on the stack, how to know if the contract exited because of a problem in execution?

So as discussed above, the return data is stored in memory before halting the contract. There are other ways of understanding how the contract halted, notably the halting state, exceptional halting function and others.

5. Where is the data after the call returned to the parent contract?

In memory. This is an excerpt from the definition of CALL in the yellow paper.

Excerpt from definition of CALL

As you see the output data is saved in memory and then mu_o is introduced as a short-hand/pointer to that part in memory.

  • Yes, I already know the RETURN opcode reads data from memory… But my question is where is the data after the call returned to the parent contract ? – user2284570 Aug 13 at 13:38
  • In memory. I've edited the answer to show that. In particular when executing CALL you specify where exactly in memory the return data would be written to. – Peteris Aug 15 at 11:49
  • Even for a simple true/false return value ? – user2284570 Aug 15 at 11:51
  • Yes, indeed! EVM doesn't distinguish in terms of simplicity. – Peteris Aug 15 at 13:22
  • And if zero is pushed on the stack, then the contract execution reverted for some reason ? isn’t it ? – user2284570 Aug 15 at 13:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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