Skip to main content

How to Read a Blockchain Transaction

How to read a blockchain transaction field by field: hash, sender, value, gas, nonce, input data, logs, and red flags to catch before you sign.

Written by Eco
Updated today

How to Read a Blockchain Transaction

Learning how to read a blockchain transaction is the single most useful onchain skill you can pick up. Every swap, transfer, approval, and contract call leaves a public receipt, and once you can scan one in under a minute you stop relying on wallet UIs to tell you what actually happened. This guide walks through every field you will see on a typical Etherscan page, shows you how to decode input data and event logs, and flags the red patterns that signal something went wrong or something is trying to drain you.

By the end you will know how to interpret the tx hash, sender and receiver, value, EIP-1559 gas fields, nonce, input data, internal transactions, and event logs — with a special focus on ERC-20 transfers, which are the transactions most users actually care about. You will also learn to recognize failed transactions, dust attacks, unbounded approvals, and the kind of sandwich patterns that show up in the internal tx list.

Blockscout transaction detail page showing Aave V2 flashloan with Success status and 5 token transfer rows

Fig 1. The whole transaction at a glance: Success status, the flashloan method name, and a preview of the 5-hop token movement. Every field this article teaches is visible somewhere on this screen.

Start at the top: status, hash, and block

When you paste a transaction hash into Etherscan, the top row is always the same three fields. Status is either Success (green) or Failed (red). Transaction Hash is the 66-character identifier (0x + 64 hex chars) that uniquely identifies this transaction across Ethereum history. Block is the number of the block that included it, plus the number of confirmations since.

A Failed status does not mean "nothing happened." Gas was still consumed, and the sender still paid. It means the state changes the transaction tried to make were reverted — usually because a require() check failed inside a contract. Etherscan shows the revert reason when one is emitted; if you see "execution reverted: InsufficientAllowance" you know exactly why. On chains like Base, Arbitrum, and Optimism you will see the same layout on Basescan, Arbiscan, and the Optimism explorer, because they all use Etherscan's codebase.

Confirmations matter because reorganizations can invalidate recent blocks. On Ethereum L1, six confirmations is the traditional safety threshold for high-value transfers; on L2s the threshold depends on whether the transaction has been posted to L1 and whether its batch has been proven or challenged. For anything above five figures, wait for finality, not just for the block to be mined.

Sender, receiver, and value

From (sender) is the externally owned account that signed the transaction and paid the gas. To (receiver) is either another EOA (if the transaction is a simple transfer) or a smart contract (if the transaction is a contract call). Etherscan labels known contracts — "Uniswap V3: Router" or "USDC" — which saves you from having to memorize addresses.

Value is the amount of native currency (ETH, MATIC, BNB, etc.) sent with the transaction. For most ERC-20 transfers this is zero, because the tokens move through the contract's internal ledger rather than as native value. This trips up new users constantly: if you see a USDC transfer with "Value: 0 ETH" that is normal. The actual USDC amount lives in the input data and the event logs, not in the Value field.

For contract calls where Value is non-zero (a Uniswap swap using ETH, for example), the ETH is pulled from the sender and either forwarded or wrapped into WETH inside the contract. You can track where it ultimately went by opening the Internal Txns tab, which we will cover below.

The gas fields after EIP-1559

EIP-1559 changed how Ethereum prices gas, and Etherscan's layout reflects that. The fields you will see on a post-1559 transaction are:

  • Gas Limit — the maximum gas units the sender was willing to consume. Set by the wallet based on estimation; unused gas is refunded.

  • Gas Used by Transaction — the actual gas units consumed. A simple ETH transfer uses 21,000; an ERC-20 transfer typically uses 45,000-70,000; a complex DeFi call can use 200,000 to over 1,000,000.

  • Base Fee per Gas — set by the protocol for every block, adjusted up or down based on how full the previous block was. This fee is burned, not paid to the validator.

  • Max Priority Fee per Gas — the tip the sender is willing to pay the validator on top of the base fee.

  • Max Fee per Gas — the ceiling the sender is willing to pay per unit (base fee + priority fee). The wallet sets this; the actual price paid is min(max fee, base fee + priority fee).

  • Transaction Fee — the total cost in native currency (gas used x (base fee + priority fee)).

The EIP-1559 specification is written up in the EIP-1559 standard document, and the Ethereum Foundation maintains a plain-English primer on how gas works. If the transaction predates August 2021, or you are on a chain that has not adopted 1559, you will see Gas Price instead — a single flat price per unit.

Nonce: the detail most guides skip

Nonce is the sequence number of the transaction from the sender's account. It starts at zero and increments by one for every transaction that account sends. Nonces are what prevent replay attacks and enforce order: a transaction with nonce 47 cannot be mined until nonce 46 has been mined from the same sender.

Why does nonce matter when you are reading a transaction? Three reasons. First, if a transaction has been "pending" for hours with a low gas price, and the sender sends a new transaction with the same nonce and a higher gas price, the new one replaces the old one — this is how you speed up or cancel a stuck transaction. Second, a nonce gap (you see nonces 45 and 47 from the same account but not 46) means there is a pending or dropped transaction at nonce 46 that is blocking everything behind it. Third, if you are trying to understand why a contract call behaves differently than you expected, the nonce tells you whether other transactions from the same account have already moved state.

Input data: where the action actually lives

For any contract call, the Input Data field is where the real semantics live. Raw input data looks like gibberish — a long hex string starting with 0x. The first 4 bytes (8 hex chars after 0x) are the function selector, a hash of the function signature. The rest is the ABI-encoded arguments.

Etherscan has a "Decode Input Data" button that, if the contract is verified, turns the hex into human-readable fields: MethodID (which function was called), and each argument with its type and value. For an ERC-20 transfer you will see something like:

  • Function: transfer(address _to, uint256 _value)

  • MethodID: 0xa9059cbb

  • [0] _to: 0x... (the recipient address)

  • [1] _value: 1000000 (the amount in the token's smallest unit)

Two things to watch. First, the amount is in the token's smallest unit, not a human-readable number. USDC has six decimals, so 1000000 means 1.0 USDC. USDT also has six decimals on most chains. Most ERC-20s (DAI, LINK, UNI, etc.) have 18 decimals, matching ETH. If the decoded amount looks absurd, divide by 10^decimals.

Second, if the "Decode Input Data" button is grayed out, the contract has not been verified. This is a yellow flag for any contract you are about to approve or interact with. Unverified bytecode means no one has published source code matching the deployed contract, so you have no way to know what the function actually does. For a tutorial on how to verify a contract yourself, see our companion guide in this cluster.

ERC-20 transfers specifically

ERC-20 transfers are the transactions most users care about, and they have a slightly confusing layout because the native Value field stays at zero. The actual token movement is encoded in two places: the input data (as the arguments to transfer() or transferFrom()) and the event logs (as a Transfer event emitted by the token contract).

The ERC-20 standard defines the Transfer event as: event Transfer(address indexed from, address indexed to, uint256 value). The topic0 of this event is always 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef — the keccak256 hash of the event signature. Any time you see that topic in a log, a token is moving.

One practical use: if you are worried a transaction did something other than a simple transfer, look at the Logs tab. A clean ERC-20 transfer has exactly one Transfer event. A swap has many (one for each hop). A liquidity deposit has Transfer events plus Mint/Burn events. The number and shape of events is a quick sanity check on what the transaction actually did.

Blockscout Token Transfers tab showing 5-hop WETH and DAI arbitrage across Uniswap V2 and SushiSwap

Fig 2. Read top to bottom — each row is one hop of the arbitrage. WETH borrowed from Aave moves through two DEXs and returns as more WETH than it started with. The delta is the profit.

Event logs: the contract's public diary

The Logs tab on Etherscan shows every event emitted during execution. Events are how smart contracts communicate state changes to the outside world; they are cheap to emit and indexed so off-chain services can filter them.

Each log has four components. Address is the contract that emitted the event (which may differ from the contract you called, because one call can trigger others). Topics are indexed event parameters; topic0 is always the event signature hash. Data is the non-indexed parameters, ABI-encoded. Etherscan decodes this into human-readable form when the contract is verified.

For ERC-20 Transfer events, topic1 is the from address (indexed), topic2 is the to address (indexed), and data is the value (non-indexed). For ERC-721 Transfer events, topic3 is the token ID (also indexed), because NFT transfers care about which specific NFT moved. For Uniswap Swap events, you will see Swap logs with sender, recipient, amount0, amount1, and tick parameters — enough to reconstruct the trade.

Blockscout Logs tab decoded ERC-20 Transfer event showing topic0 hash, indexed from and to topics, and wad value

Fig 4. Topic 0 is always the event-signature hash — the same 0xddf252ad... appears on every ERC-20 Transfer. Topic 1 and 2 are the indexed sender and recipient; the amount sits in the data field.

Internal transactions: the hidden second layer

Internal transactions are state-changing calls that happened inside the execution of an outer transaction. They are not separate transactions — they share the outer transaction's hash and gas — but they are visible because Etherscan reconstructs them by running the transaction through an EVM tracer.

The Internal Txns tab is where you see where ETH actually moved during a contract call. If you called a DEX router with 1 ETH, the router probably wrapped it into WETH (one internal tx), called a pool contract (another internal tx), and the pool forwarded WETH to a different address (a third internal tx). None of these show up in the top-level "From/To/Value" fields, but they all happened.

Blockscout Internal Txns tab showing Call and Delegate call frames between Aave Lending Pool, WETH, Uniswap, and Dai Stablecoin

Fig 3. None of these calls appear in the top-level From/To. The EVM tracer reconstructs every sub-call — the DEX routing, the pool interactions, the token wrapping — that the outer transaction would otherwise hide.

Two things to look for in internal txs. First, unexpected recipients — if you swapped tokens but an internal tx shows ETH going to an address that is neither you nor a known pool, something is off. Second, reentrancy patterns — internal txs that call back into the originating contract before the outer call completed. Most exploited protocols in the last five years show a telltale back-and-forth in their internal tx list during the hack block.

If the Internal Txns tab still doesn't answer your question, the Raw Trace tab is the full EVM call tree — every CALL, DELEGATECALL, and STATICCALL frame with gas, value, and input data. It is overkill for routine reads, but indispensable when you are reverse-engineering an exploit or a MEV pattern.

Blockscout Raw Trace tab showing the full EVM call tree as nested JSON with action and result frames

Fig 6. The raw trace is what sits beneath the Internal Txns table — every EVM frame with its gas, value, input, and output. Worth knowing exists; rarely needed day to day.

Red flags: what a bad transaction looks like

Once you can read the normal fields, the same fields tell you when something is wrong. Here is a practical checklist.

Failed status with an approval

If an approve() transaction failed, the allowance did not get set — but the gas was still paid. This is usually benign. What is not benign is a failed transaction you did not sign, showing up in your account history with nonce zero — that is someone else's failed spam, not a threat to you.

Unbounded approvals (approve with value = max uint256)

When a dapp asks you to approve a token and you see the decoded value as 115792089237316195423570985008687907853269984665640564039457584007913129639935 (or "unlimited"), you are giving the contract permission to move any amount of that token forever. Many protocols still default to this. It is convenient and gas-efficient, but it means if the protocol is hacked or upgraded to a malicious version, your entire balance can be drained in one call. Revoke.cash is the canonical tool for auditing and removing these approvals.

Approval draining / ERC-20 permit signatures

A more subtle pattern: phishing sites ask you to sign an EIP-2612 permit or a Permit2 signature, not a transaction. A signature does not show up in your account history as a tx, but it authorizes someone else to move your tokens. If you signed a permit and later see a transferFrom() draining your wallet, the signature is the culprit. Check the EIP-2612 permit extension for how these signatures are structured.

Dust attacks

A dust attack is a tiny incoming transfer (0.00001 of some token, often a fake USDC clone) from an address designed to look similar to one you have used. The goal is to get you to paste the attacker's address when you next send. Etherscan flags many of these as spam now. The defense is never to copy an address from your transaction history — copy from the counterparty's official channel.

Sandwich and MEV patterns

If you swapped and the transaction immediately before and after yours were from the same address, you probably got sandwiched. The attacker bought the asset you were about to buy (pushing the price up), let your trade fill at the worse price, then sold back (pushing the price back down and capturing the spread). The internal tx list makes this visible. Intent-based routing systems were designed partly to eliminate this, and the intent-based protocols landscape covers the design space.

Cross-chain transactions: one mental model, three explorers

Reading a cross-chain transaction is where single-explorer workflows fall apart. A USDC transfer from Ethereum to Arbitrum involves a transaction on Ethereum (burning or locking), a message through a messaging layer (CCTP, Hyperlane, or another rail), and a transaction on Arbitrum (minting or releasing). To see the full flow you need all three pages open at once.

Circle's CCTP and other cross-chain messaging protocols publish dashboards that stitch the view together, but most block explorers only show their own chain. For stablecoin flows across the 15 chains Eco supports — Ethereum, Optimism, Base, Arbitrum, HyperEVM, Plasma, Polygon, Ronin, Unichain, Ink, Celo, Solana, Sonic, BSC, and Worldchain — the fastest way to see the full settlement path is to look at the Eco-signed intent and its fulfillment record, rather than trying to reconstruct it from three explorer tabs. For teams building on this, Routes CLI or the Routes API exposes the intent hash and both legs of execution as a single logical transaction.

A quick read-order cheat sheet

Blockscout State tab showing before and after balance diff for validator, WETH mint and burn addresses, AToken, and Collector

Fig 5. The State tab collapses an entire transaction into "who had what before, who has what now." Cross-reference the final balance of the initiator with Fig 1 — the difference is the realized profit in a single row.

When you open a new transaction, read fields in this order for the fastest mental model:

  1. Status — did it succeed?

  2. From / To — who sent, who (or what contract) received?

  3. Value — did native currency move? If zero, expect the action to be in input data.

  4. Input Data (decoded) — what function was called with what arguments?

  5. Logs — what events were emitted? (Does the count and shape match what you expect?)

  6. Internal Txns — where did value actually flow during execution?

  7. Gas — did the cost make sense for the operation?

  8. Nonce — only if you are debugging a stuck or replayed transaction.

Do this ten times and it becomes automatic. Do it a hundred times and you will catch exploits and phishing attempts that most wallet UIs will happily let through.

FAQ

What does a failed blockchain transaction mean?

A failed transaction means one of the require() or revert checks inside the called contract rejected the execution, so no state changes were applied. Gas was still consumed and paid, because the validator did the work to run the transaction. Etherscan shows the revert reason in the status tooltip when available, which usually tells you which condition failed.

What does Value: 0 ETH mean on an ERC-20 transfer?

ERC-20 tokens are not native ETH — they live inside a token contract's internal ledger. When you send USDC or DAI, the transaction calls the token contract's transfer() function; no native ETH moves, so Value is zero. The actual token amount appears in the decoded input data and in the Transfer event under Logs, not in the Value field.

How do I decode transaction input data?

On Etherscan, click "Decode Input Data" under the Input Data field. The button only works if the target contract is verified — meaning its source code has been published and compiled to match the deployed bytecode. For unverified contracts, use a tool like Openchain's signature database to look up the 4-byte function selector and reconstruct the ABI manually.

What is the nonce on a blockchain transaction?

The nonce is the sequence number of the transaction from the sender's account, starting at zero and incrementing by one each time. Nonces enforce ordering and prevent replay. A pending transaction with a low gas price can be replaced by sending a new transaction with the same nonce and higher gas, which is how wallets implement "speed up" and "cancel."

How can I tell if a transaction was a phishing or drainer attack?

Look for unbounded approvals (decoded value equal to max uint256), signed permits rather than transactions (which do not appear in your tx history but authorize transfers), or transferFrom() calls that move your tokens to an address you did not interact with. Reviewing your outstanding approvals regularly on Revoke.cash is the most reliable defense.

Why can't I see the full path of a cross-chain transaction on Etherscan?

Block explorers are chain-scoped. A cross-chain stablecoin transfer has at least one transaction on the source chain and one on the destination chain, connected by a messaging layer that a single explorer cannot render. The cleanest view comes from the orchestration layer that initiated the transfer, which treats both legs as a single intent. Eco's Routes CLI and Routes API expose cross-chain execution as one record rather than three pages.

What are internal transactions on Etherscan?

Internal transactions are state-changing calls that happened inside the execution of a top-level transaction — for example, a DEX router calling a pool contract, which then forwarded ETH to another address. They share the outer transaction's hash and gas, and Etherscan reconstructs them by tracing the EVM execution. They are essential for understanding where value actually moved during a contract call.

Did this answer your question?