EIP-658 Recording the transaction status code in the receipt (Embedding transaction status code in receipts)

Final · EVM & execution · EIP status Final · created 2017-06-30

This replaces the intermediate state root field in the transaction receipt with a status code, recording 1 if the transaction succeeded and 0 if it failed. Anyone can check whether a transaction succeeded without re-executing it.

Why it is needed

Previously, whether a transaction had failed was inferred by checking whether all its gas had been consumed, since a failed transaction used up all its gas. But once EIP-140 introduced the REVERT opcode, a transaction could fail while returning unused gas, and this inference method no longer worked. There was no longer a clear way for a caller to determine whether a transaction succeeded and whether its state changes had actually been applied. A full node with all the data could offer an RPC that re-executes the transaction and reports the result, but a fast-sync node could only re-execute transactions after its pivot point, and a light node could not re-execute transactions at all. Solving this outside the consensus rules was therefore impractical, and a consensus-level change was needed to record success or failure directly in the receipt.

What changes

Today

After EIP-658

Who is affected

In depth

Replacing the intermediate state root with a status code

The receipt originally contained the intermediate state root immediately after each transaction was processed. This field had already become useless due to EIP-98. This EIP replaces it with a return status indicating whether the top-level call succeeded: 1 for success, 0 for failure. This lets callers determine whether a transaction succeeded, while also filling the existing gap of missing execution-result information in the receipt.

Why a solution outside consensus was not possible

When EIP-140 introduced the REVERT opcode, the equivalence of "ran out of gas means failure" broke down. There was no longer a clear way for a caller to determine whether a transaction succeeded or whether the state changes inside it had actually been applied. A full node can offer an RPC that re-executes the transaction and reports the return state and value, but a fast sync node can only do this for transactions after the pivot point, and a light node cannot do it at all. So any solution outside the consensus rules was impractical, and the receipt itself, a consensus data structure, had to change.

Specification: activation point and status code values

From the block where block.number >= BYZANTIUM_FORK_BLKNUM, the intermediate state root in the receipt is replaced by a status code. 0 means failure, caused by any operation that can revert the transaction or the top level call. 1 means success. The specification is a short change that defines only these two values and the activation point.

Design rationale: a minimal change

The author explains that this approach is the smallest possible change that allows querying a transaction's success or failure status. It preserves existing functionality while minimizing the extra work and confusion needed for the Metropolis upgrade. Because it reuses a field already deprecated by EIP-98, the size and shape of the receipt structure does not change.

Status: Final, active from Byzantium

This EIP was proposed on June 30, 2017, and its current status is Final. As specified, it applies to every block after the Byzantium fork block (BYZANTIUM_FORK_BLKNUM). It requires EIP-140 (the REVERT opcode) as a prerequisite.

Original EIP · ← EIPs