UTXO and account models · Lesson 5 of 6
Layer 2s, sidechains and bridges as data sources
7 min read
A large share of activity on Ethereum-style networks now happens on layer 2 chains and sidechains rather than on the base chain itself. Funds move between layers through bridges, and each layer has its own blocks, its own explorer and its own chain ID. An analyst who follows funds only on layer 1 sees them vanish into a bridge contract; one who understands how layers record deposits, withdrawals and messages can follow them across and say how certain each link is.
A map of the territory
| Design | Security comes from | Transaction data published | Withdrawal to L1 | Examples |
|---|---|---|---|---|
| Optimistic rollup | L1, through fraud (fault) proofs during a challenge window | On L1, as compressed batches | After the challenge window, typically about a week | OP Mainnet, Base, Arbitrum One |
| ZK (validity) rollup | L1, through validity proofs verified on L1 | On L1, as transactions or state differences | Once a proof is verified, typically hours to a day | zkSync Era, Scroll, Linea, Starknet |
| Validium or alt-DA chain | Proofs or fraud proofs, but data held off L1 | Elsewhere (a committee or another data layer) | Depends on design | Various |
| Sidechain | Its own validator set | On its own chain only | Through a bridge operated by validators or a committee | Polygon PoS, Gnosis Chain |
The distinction that matters for evidence is where the data lives and who could rewrite it. A rollup's history can in principle be rebuilt from L1; a sidechain's history is only as reliable as its own validators.
Sequencers and finality on L2
Most rollups have a single sequencer that orders transactions and produces L2 blocks quickly (typically every 2 seconds on OP Stack chains, faster on some others). Users get a "soft" confirmation from the sequencer within seconds; the transaction becomes anchored when the sequencer posts the batch to L1, and settled when that L1 block is finalized. Most rollups also let users force a transaction in through L1 if the sequencer censors them.
For analytics, this creates layered finality. OP Stack nodes expose unsafe (sequencer-only), safe (derived from data posted to L1) and finalized (derived from finalized L1 blocks) heads, and the safe and finalized tags work in standard JSON-RPC calls. Build datasets from safe or finalized L2 blocks, as you would on L1 (see the lesson Blocks and headers as data). Sequencer outages have happened on several rollups, and the unsafe head can be reorganized.
Data availability: where to read L2 data
In practice, analysts read L2 data from L2 nodes, explorers and warehouses, exactly as on L1, with the same receipts, logs and traces. The L1 copy matters for verification and for understanding costs:
- Until March 2024, rollups posted batches as L1 call data, stored forever.
- Since the Dencun upgrade (March 13, 2024), most post them as blobs (EIP-4844). L1 consensus nodes keep blob data for 4,096 epochs, about 18 days, then prune them; only a versioned hash stays in the L1 transaction. Rebuilding old L2 history from L1 therefore needs a blob archive.
- Some ZK rollups post state differences instead of transactions, so the L1 copy proves balances but does not list every transfer.
Record for every L2 dataset the chain ID, the L2 block range, the node or provider and, where relevant, the L1 block that anchored it.
L1 to L2: deposits and messages
A deposit moves value or a message from L1 to L2. On OP Stack chains, a user (or the standard bridge contract acting for them) calls the OptimismPortal on L1, which emits TransactionDeposited(address indexed from, address indexed to, uint256 indexed version, bytes opaqueData). L2 nodes read these events and create a deposit transaction of type 0x7E at the start of a later L2 block. As an OP Stack node returns it:
{
"type": "0x7e",
"sourceHash": "0x3c9e…a0d4",
"from": "0xA1b2…9F",
"to": "0xA1b2…9F",
"mint": "0x6f05b59d3b20000",
"value": "0x6f05b59d3b20000",
"gas": "0x186a0",
"input": "0x"
}
A deposit transaction has no signature: its authority comes from the L1 event. mint is the ETH created on L2 (here 0.5 ETH), mirrored by ETH locked in the portal on L1. sourceHash uniquely identifies the L1 origin, computed from the L1 block hash and the event's log index, which makes it the exact join key between the L1 event and the L2 transaction. In a warehouse that stores the type as an integer, these are rows with type 126.
Arbitrum uses retryable tickets: an L1 call to createRetryableTicket on the Inbox contract creates a ticket that is normally redeemed automatically on L2. If the automatic redemption fails, the ticket waits up to one week for a manual redemption, so an analyst may see a deposit on L1 with its L2 effect days later.
Both families apply address aliasing. When an L1 contract sends a message to L2, its address on L2 is shifted by adding 0x1111000000000000000000000000000000001111, so it cannot impersonate an L2 contract at the same address. A message from L1 contract 0x5d3a…7c10 therefore arrives on L2 from 0x6e4b…8d21. EOAs are not aliased. An analyst who searches L2 for the L1 contract's address will find nothing; search for the alias.
L2 to L1: withdrawals
A canonical withdrawal is a multi-step process spread over two chains and several days. On OP Stack chains:
- Initiate on L2: the user calls the
L2ToL1MessagePasserpredeploy at0x4200…0016(directly or through the L2 bridge), which emitsMessagePassedwith a withdrawal hash. - Prove on L1: once the L2 state including that message has been proposed on L1, anyone submits a proof to the OptimismPortal, which emits
WithdrawalProven(bytes32 indexed withdrawalHash, address indexed from, address indexed to). - Finalize on L1: after the challenge window, anyone calls finalize; the portal emits
WithdrawalFinalized(bytes32 indexed withdrawalHash, bool success)and releases the funds.
On Arbitrum, the L2 side calls the ArbSys precompile (address 100, 0x…0064) with sendTxToL1, and about a week later the message is executed on L1 through the Outbox contract's executeTransaction.
The withdrawal hash links all three steps. Two pitfalls: the address that proves or finalizes can be anyone, often a relayer, and is not necessarily the owner; and challenge windows differ by chain and change as proof systems evolve (some chains have shortened theirs with newer proof systems), so check the parameters in force at the time. Because a week is long, many users exit through third-party bridges or liquidity providers instead, which pay out on L1 from their own funds and break the canonical link; matching those flows is covered in the lesson Cross-chain tracing.
Chain IDs and identities across layers
Every EVM chain has a chain ID (EIP-155), returned by eth_chainId and embedded in signed transactions:
| Chain | Chain ID | Type |
|---|---|---|
| Ethereum | 1 | L1 |
| OP Mainnet | 10 | Optimistic rollup |
| BNB Smart Chain | 56 | Separate L1 |
| Polygon PoS | 137 | Sidechain with checkpoints to Ethereum |
| zkSync Era | 324 | ZK rollup |
| Base | 8453 | Optimistic rollup |
| Arbitrum One | 42161 | Optimistic rollup |
| Linea | 59144 | ZK rollup |
| Scroll | 534352 | ZK rollup |
Key every table by chain ID and address together, never address alone. The same private key controls the same EOA address on every EVM chain, which makes cross-chain identity easy for EOAs. Contracts are different: an address can host a contract on one chain and nothing, or someone else's contract, on another. In June 2022 about 20 million OP tokens were sent to an address on Optimism where the intended recipient's multisig existed only on Ethereum; before the owner could deploy it there, an attacker deployed a different multisig at that address on Optimism and took the tokens. Same address does not mean same owner unless the code and deployment are verified on each chain.
A daily count of OP Stack deposits shows the standard filter:
-- Daily L1-to-L2 deposits on an OP Stack chain (deposit type 0x7E = 126)
SELECT
CAST(block_timestamp AS DATE) AS day,
COUNT(*) AS deposits,
SUM(mint) / 1e18 AS eth_minted
FROM transactions
WHERE chain_id = 8453
AND tx_type = 126
AND block_timestamp >= TIMESTAMP '2026-01-01 00:00:00'
GROUP BY 1
ORDER BY 1;
The query filters to one chain and to deposit transactions, then sums the ETH minted. Column names vary between datasets (type or transaction_type, mint may be absent), and timestamp types differ by engine; check the schema before trusting a zero.
Exam focus: optimistic vs ZK rollups vs sidechains and where each one's data lives; sequencers and the unsafe, safe and finalized heads; blobs since March 2024 and their roughly 18-day retention; OP Stack deposits (TransactionDeposited, type0x7E,mint,sourceHashas the join key) and Arbitrum retryable tickets; address aliasing of L1 contracts by adding0x1111…1111; the initiate, prove and finalize steps of an OP Stack withdrawal and the withdrawal hash that links them; why finalizers are not necessarily owners; chain IDs, keying data by chain ID plus address, and why the same contract address on two chains does not imply the same owner.