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
- Transaction failure was inferred from whether all gas had been consumed
- After REVERT was introduced, this inference no longer held
- Light nodes had no way to verify whether a transaction succeeded
- The receipt contained an intermediate state root that had already become useless
After EIP-658
- Looking at the receipt's status code alone immediately tells you success (1) or failure (0)
- The result can be known without re-executing the transaction
- All nodes, including light nodes, can verify it the same way
- The slot previously occupied by the intermediate state root now holds genuinely useful information
Who is affected
- Users: Wallets and explorers can accurately show whether a transaction succeeded or failed.
- Wallet & app developers: Success or failure is determined from the receipt's status code, without re-executing the transaction or estimating gas consumption.
- Client teams: A consensus change must be implemented that replaces the intermediate state root in the receipt structure with a status code.
- Light node operators: Transaction results can now be verified even in environments where transactions cannot be re-executed.
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.