Transaction Receipt
An EVM data structure returned after transaction execution containing the status, gas used, logs, and emitted events.
Key Takeaways
- A transaction receipt is the output record that EVM-compatible blockchains produce after executing a transaction. It contains the execution outcome, gas consumed, and any events emitted by smart contracts.
- Receipts are distinct from transaction objects: the transaction describes what the sender requested, while the receipt describes what the network did with that request, including whether it succeeded or failed.
- Event logs stored in receipts are the primary mechanism dApps and indexers use to track on-chain activity, from token transfers to governance votes, making receipts essential infrastructure for the entire EVM ecosystem.
What Is a Transaction Receipt?
A transaction receipt is a data structure that Ethereum and other EVM-compatible blockchains generate after a transaction has been included in a block and executed. It serves as proof of execution: a permanent record of what happened when the network processed the transaction. Every mined transaction produces exactly one receipt, regardless of whether the transaction succeeded or reverted.
Think of a transaction as a request and the receipt as the response. When you submit a transaction, you specify the recipient, the value, the calldata, and the gas limit. The receipt tells you what the network did with those inputs: how much gas was actually consumed, whether the execution completed successfully, and what events the contract emitted along the way. The receipt only exists after the transaction is included in a block. Pending transactions have no receipt.
Receipts are stored in a dedicated Merkle Patricia trie whose root hash is committed to the block header. This means any light client can verify a receipt's authenticity using a Merkle proof without downloading the full block.
How It Works
When a validator or miner includes a transaction in a block, the EVM executes the transaction's bytecode and produces a receipt. The receipt is then stored alongside the block data and becomes queryable through the JSON-RPC API via the eth_getTransactionReceipt method.
Core Receipt Fields
A transaction receipt contains the following fields, as defined by the Ethereum protocol and returned by the standard JSON-RPC interface:
| Field | Type | Description |
|---|---|---|
status | Integer | 1 for success, 0 for failure (revert). Added in the Byzantium hard fork (EIP-658). |
transactionHash | Bytes32 | Hash of the transaction that produced this receipt. |
transactionIndex | Integer | Position of the transaction within the block. |
blockHash | Bytes32 | Hash of the block containing this transaction. |
blockNumber | Integer | Block number where the transaction was included. |
from | Address | Sender address. |
to | Address | Recipient address. Null for contract creation transactions. |
gasUsed | Integer | Amount of gas consumed by this specific transaction. |
cumulativeGasUsed | Integer | Total gas used in the block up to and including this transaction. |
effectiveGasPrice | Integer | Actual price per unit of gas paid, accounting for EIP-1559 base fee and priority fee. |
contractAddress | Address | Address of the newly created contract, if this was a deployment transaction. Null otherwise. |
logs | Array | Array of log objects emitted during execution (see below). |
logsBloom | Bytes256 | A 2048-bit Bloom filter built from the log entries. Enables efficient filtering by light clients and indexers. |
type | Integer | Transaction type (0 for legacy, 1 for EIP-2930 access list, 2 for EIP-1559, 3 for EIP-4844 blob transactions). |
Event Logs
The logs array is the most important part of the receipt for application developers. Each log entry represents an event emitted by a smart contract during execution using Solidity's emit keyword. A single transaction can produce zero, one, or many log entries across multiple contracts.
Each log object contains:
address: the contract that emitted the eventtopics: an array of up to 4 indexed values. The first topic is typically the keccak256 hash of the event signature (e.g.,Transfer(address,address,uint256)). Remaining topics hold indexed parameters for efficient filtering.data: ABI-encoded non-indexed parameters. These are cheaper to store than indexed topics but cannot be searched directly on-chain.logIndex: position of this log within the block's full log list
Querying Receipts
Applications retrieve receipts through the eth_getTransactionReceipt JSON-RPC method. The method accepts a transaction hash and returns the full receipt object, or null if the transaction is still pending or unknown:
// Request
{
"jsonrpc": "2.0",
"method": "eth_getTransactionReceipt",
"params": ["0xabc123..."],
"id": 1
}
// Response (simplified)
{
"status": "0x1",
"gasUsed": "0x5208",
"cumulativeGasUsed": "0x33bc",
"logs": [],
"contractAddress": null,
"transactionHash": "0xabc123...",
"blockNumber": "0x10a2b3c"
}A null response means the transaction has not been mined yet. Applications typically poll this endpoint or use WebSocket subscriptions to detect when a pending transaction gets included. The presence of a receipt confirms inclusion, but the status field must still be checked to determine success or failure.
Transaction Object vs. Transaction Receipt
A common source of confusion is the difference between the transaction object (returned by eth_getTransactionByHash) and the transaction receipt. They represent two sides of the same coin:
| Aspect | Transaction Object | Transaction Receipt |
|---|---|---|
| Represents | The input: what the sender requested | The output: what the EVM produced |
| Available when | As soon as the transaction is broadcast (even while pending) | Only after the transaction is mined into a block |
| Gas info | gasLimit: maximum gas the sender is willing to pay | gasUsed: actual gas consumed during execution |
| Success/failure | Not available | status: 1 for success, 0 for revert |
| Events | Not available | logs: all events emitted during execution |
| Contract address | Not available | Included for contract creation transactions |
A failed (reverted) transaction still produces a receipt. The receipt's status will be 0x0, and the gasUsed field will reflect the gas consumed before the revert. The sender still pays for that gas. This is why transaction simulation is valuable: it catches reverts before you pay for them.
Use Cases
Confirming Transaction Success
The most basic use of a receipt is confirming that a transaction completed successfully. Wallets and dApps check the status field after submission. A status of 0x1 means the transaction executed without reverting. A status of 0x0 means the EVM encountered a revert opcode, and any state changes were rolled back (though gas was still consumed).
Blockchain Indexing
Indexing services like The Graph scan transaction receipts to build queryable databases of on-chain activity. They define handlers that fire whenever specific events appear in receipt logs. For example, an ERC-20 indexer watches for Transfer events to track token movements across accounts:
// Subgraph event handler (AssemblyScript)
export function handleTransfer(event: TransferEvent): void {
let transfer = new Transfer(
event.transaction.hash.toHex()
+ "-"
+ event.logIndex.toString()
);
transfer.from = event.params.from;
transfer.to = event.params.to;
transfer.value = event.params.value;
transfer.save();
}Each transfer entity uses the transaction hash combined with the log index as a unique identifier, ensuring every event within a transaction is captured individually. Block explorer APIs rely on similar indexing to display transaction histories, token balances, and contract interactions.
Smart Contract Deployment Verification
When a contract creation transaction is mined, the receipt's contractAddress field contains the address of the newly deployed contract. Deployment scripts use this field to verify the contract was created at the expected address and to proceed with initialization steps like setting permissions or registering the contract with other protocols.
dApp UI Updates
Frontend applications use receipt data to update their interfaces after user actions. When a user swaps tokens on a DEX, the dApp parses the Swap event from the receipt logs to display the exact amounts exchanged and the effective price. Without receipts, the UI would have no reliable way to confirm what happened on-chain.
Gas Cost Analysis
The gasUsed and effectiveGasPrice fields let developers and users calculate the exact cost of a transaction after the fact. This is particularly useful for gas optimization: comparing receipts across different contract implementations reveals which approach consumes less gas.
Comparison with Bitcoin
Bitcoin does not have transaction receipts in the EVM sense. Bitcoin uses the UTXO model, where a transaction consumes existing unspent outputs and creates new ones. There is no concept of "execution status" because Bitcoin Script either validates or it doesn't: invalid transactions are simply rejected by nodes and never included in a block. There is no "failed but included" state.
Bitcoin also lacks event logs. Smart contract platforms on Bitcoin like RGB and Stacks use different mechanisms for tracking contract state changes. On Spark, Bitcoin's Layer 2, transaction confirmation works differently from both the UTXO model and the EVM receipt model, offering instant finality without the complexity of gas accounting.
Network-Specific Extensions
While the core receipt fields are standardized across EVM chains, Layer 2 networks and alternative EVM chains sometimes add extra fields:
- L2 rollups may include fields like
l1Feeandl1GasUsedto report the portion of the transaction cost attributable to posting data on the L1 settlement layer - EIP-4844 blob transactions add
blobGasUsedandblobGasPricefields to the receipt - Some chains include additional fields for deposit-type transactions or cross-chain messages
These extensions are backward-compatible: applications that only read the standard fields will still work correctly. For a deeper look at how different chains handle transaction processing, see the research on payment finality across blockchains.
Risks and Considerations
Receipt Does Not Mean Finality
A receipt confirms inclusion in a block, not finality. On chains with probabilistic finality (like Ethereum pre-merge), the block containing a transaction could theoretically be reorganized out of the canonical chain. Most applications wait for a certain number of block confirmations before treating a receipt as authoritative.
Failed Transactions Still Cost Gas
A receipt with status: 0x0 means the transaction reverted, but the sender still paid for the gas consumed up to the point of failure. This is by design: validators expend computational resources executing the transaction, and that work must be compensated. Use transaction simulation to estimate whether a transaction will succeed before submitting it on-chain.
Log Data Is Not Contract State
Event logs in receipts are append-only records. They capture what happened during execution, but they are not the same as the contract's current state. A Transfer event tells you a transfer occurred, but to know a wallet's current balance, you need to read the contract's storage directly or aggregate all relevant events.
Node Sync and Indexing Delays
Nodes that are still syncing or indexing may return errors when queried for receipts. A common JSON-RPC error code (-32000) indicates that transaction indexing is still in progress. Applications should handle this gracefully and retry rather than treating it as a permanent failure.
This glossary entry is for informational purposes only and does not constitute financial or investment advice. Always do your own research before using any protocol or technology.