Ethereum Yellow Paper Deciphered | Part 6: Message Call

February 12, 2023

Note that this post is updated till the Shanghai version of the ethereum yellow paper.

Message Call

In the last part, we saw how contract creation transactions work. In this part we introduce message call transactions. Like contract creations, message calls also involve many parameters:

  1. State before execution of (contract-creation) transaction, .
  2. Accrued substate till before execution of transaction, .
  3. Sender of the transaction denoted by . This is msg.sender global variable in Solidity.
  4. Original transactor, the EOA which initiated the transaction, . This is tx.origin global variable in Solidity.
  5. The address of recipient of the message call, . This is contract being called.
  6. The account/contract whose code is to be executed, . Most of the time this is same as , but can be different in delegatecalls.
  7. Available gas for the transaction execution, .
  8. Value, sent along with this message call transaction. It is msg.value in Solidity.
  9. The effective gas price, that we saw in previous part.
  10. The input bytes data of the call, . Also known ass **calldata** in Solidity.
  11. Present depth of contract-creation stack, .
  12. Permission to make modification to state, .

With above 12 input parameters, evaluates and outputs a tuple of 5 elements:

  1. Next world state after this contract creation transaction, .
  2. Remaining gas after the execution, .
  3. The accrued substate after this execution, .
  4. The result status (success or fail) of the transaction execution, .
  5. The output bytes data as result of the execution of the transaction, .

can now be mathematically defined as:

Special case of DELEGATECALL opcode

Note that for delegatecall the sender of transaction and originator of the transaction can be different addresses, as we already seen above. o is always an EOA - it cannot be a contract.

Another point of difference is the msg.value global parameter in the call context. Normally, for non-delegatecall calls we denote it with which is simply the msg.value. But for delegatecall we do not specify any value parameter to send with the call. In this case, the called function has the (apparent) msg.value same as the calling context/function.

Let's define an updated state corresponding to the original state as the state with values transferred from sender to receiver. So the contract receiving the call () has balance increased by and sender has its balance decreased by :

Note that the in the transitional state the entry at contract address i.e. is not defined initially.

The equation above can be expanded to more detailed form:

  • When contract/account is non-existent in state and value sent is non-zero:

  • When contract/account is non-existent in state and value sent is zero:

  • When contract/account is exists in state :

Combining all of the above it is same as saying that all else unchanged i.e.

The contract address entry is updated as:

where,

Next the entry for sender address in state is updated as:

  • When sender address is non existent in and value sent is zero:

  • Otherwise:

Combining we get:

where,

Now we formally defined the outputs of the from function.

Remember from previous part that is the EVM code execution function. If executes successfully, the state is transitioned to next state . Otherwise, all changes are reverted and state remains unchanged i.e it remains .

Lets define the function more accurately here. executes the instructions according to a pre-specified execution model of the EVM. Apart from this some addresses are special - called precompiled addresses. Directing a call to these addresses executes special codes at these precompiled addresses. For example, you can use SHA-256 algorithm by calling at address ( in decimal) with appropriate calldata input. The corresponding execution function is denoted as . The calls directed to these pre-compiled addresses ( to ) executes a fixed code in the EVM. Any other address will try to load contract code at that address and execute that against the provided input/calldata. We defined the EVM execution function as:

The set precompiled contracts are are also denoted by :

in the above is execution environment parameters. These are:

  1. Contract address (recipient):

  2. Originator address of the message call:

  3. Effective gas price:

  4. The input data or calldata:

  5. Sender of the message call:

  6. The value sent with the message call:

  7. Message call stack:

  8. Permission to make state modification:

Lets define the output of the function defined with as:

Now we ascertain the final state after execution of the message call, which is the tuple .

The final state,

Note that execution defined by can be halted/reverted. In that case, the output state is empty and final state becomes same as initial state. Otherwise final state is :

Remaining gas,

In case of call revert during execution, all gas is consumed and no remaining gas is left. Otherwise it is :

Accrued substate,

In case of call revert accrued substate remains same as before invoking the . Otherwise, :

Status code,

Status is simply 0 for reverted calls and 1 for successful ones: