Lesson 3 — OP Standard Bridge — the canonical L2 deposit/withdrawal pattern
Question
OP Mainnet processes billions of dollars through its standard bridge. The deposit path is fast (~1–3 min); the withdrawal path takes 7 days. That asymmetry is forced by the optimistic rollup trust model. Read the actual contracts and trace exactly why.
Principle (minimum model)
- OP bridge has two contracts.
L1StandardBridgeon Ethereum L1,L2StandardBridgeon OP L2. Deposit goes L1 → L2 (fast); withdrawal goes L2 → L1 (slow, 7-day challenge window). - Deposit path (~1–3 minutes). User calls
L1StandardBridge.depositETHTo(...)→ bridge emitsETHDepositInitiated+ETHBridgeInitiatedand callsL1CrossDomainMessenger→ messenger callsOptimismPortal2.depositTransaction, which emitsTransactionDeposited→ the rollup node derives an L2 deposit transaction from that log → on L2,L2CrossDomainMessengerrelays the message toL2StandardBridge, which credits ETH (or mints the L2 token). - Withdrawal path (7 days). User calls
L2StandardBridge.withdraw(...)(legacy) orbridgeETHTo/bridgeERC20To→ bridge burns the L2 token (for bridged ERC-20s) →L2ToL1MessagePasser.initiateWithdrawalrecords the withdrawal → a proposer posts an output root to L1 as a dispute game → user callsOptimismPortal2.proveWithdrawalTransactionagainst that game → wait 7 days →finalizeWithdrawalTransactionon L1. - The 7-day window is the security model. Anyone can challenge an invalid output root through the fault dispute game. If the challenger wins, withdrawals proven against that game can't be finalized. On OP Mainnet a proven withdrawal waits
proofMaturityDelaySeconds= 604800 (7 days), and the game must also have resolved and passeddisputeGameFinalityDelaySeconds= 302400 (3.5 days) (read from the OP Mainnet portal, Oct 2026). - OptimismPortal is the trust anchor. It decides which withdrawals are valid. On OP Mainnet the deposited ETH sits in
ETHLockbox(~181k ETH, Oct 2026), which only the portal can unlock; bridged ERC-20s sit inL1StandardBridge. A bug in the portal is catastrophic. - The
messagePassingabstraction. OP'sCrossDomainMessengeris the general-purpose primitive;StandardBridgeis a specialisation for ETH/ERC-20. Custom L2 apps useCrossDomainMessengerdirectly. - Liquidity-provider bridges (e.g. Across) skip the 7-day wait. They front the user funds on L1 and reclaim from the canonical bridge after 7 days. Trade-off: a small fee, but instant withdrawal.
Worked example + steps
OP Standard Bridge — the canonical L2 deposit/withdrawal pattern
Every OP Stack chain — Optimism, Base, Mode, Worldchain, Zora — runs the same bridge. They don't each pick a multisig to attest messages or stand up a validator set; they all use the rollup's own state commitments and fault proofs as the bridge's security model. (Caveat: the contracts are upgradeable — on OP Mainnet by a 2-of-2 Safe, the ProxyAdminOwner in the superchain-registry — and a Guardian Safe can pause withdrawals. Those keys are part of the real trust model.) The bridge is just an interface to the rollup, and the rollup is the trust anchor. This is the canonical "trustless L1↔L2" reference, and reading it once teaches you a pattern you'll see (with variations) in every native L2 bridge you encounter.
1. The deposit flow
L1→L2 (deposit) is the easy direction:
sequenceDiagram
participant User
participant L1Bridge as L1StandardBridge (Ethereum)
participant L1Msg as L1CrossDomainMessenger (Ethereum)
participant Portal as OptimismPortal2 (Ethereum)
participant L2Msg as L2CrossDomainMessenger (OP)
participant L2Bridge as L2StandardBridge (OP)
User->>L1Bridge: depositERC20(l1Token, l2Token, amount, ...)
Note over L1Bridge: Lock ERC-20, emit ERC20DepositInitiated
L1Bridge->>L1Msg: sendMessage(...)
L1Msg->>Portal: depositTransaction(...)
Note over Portal: Emit TransactionDeposited
Note over L2Msg: Rollup node derives the deposit tx from the L1 log
L2Msg->>L2Bridge: relayMessage → finalizeBridgeERC20(...)
L2Bridge->>User: Mint OptimismMintableERC20 to user
Key insight: deposits are forced inclusions. The portal emits TransactionDeposited; the derivation rules make every L2 node include that deposit within the sequencing window (seq_window_size = 3600 L1 blocks, ~12 hours, on OP Mainnet per the superchain-registry). A sequencer that skips it produces blocks honest nodes reject. Any user can also call OptimismPortal2.depositTransaction directly to get an arbitrary L2 transaction in past a censoring sequencer.
This means deposits are trustless — the rollup's own derivation rules enforce inclusion. No multisig signs off on deposits.
2. The withdrawal flow
L2→L1 (withdrawal) is much harder:
sequenceDiagram
participant User
participant L2Bridge as L2StandardBridge (OP)
participant Passer as L2ToL1MessagePasser (OP)
participant DGF as DisputeGameFactory (Ethereum)
participant Portal as OptimismPortal2 (Ethereum)
participant L1Bridge as L1StandardBridge (Ethereum)
User->>L2Bridge: withdraw(...) / bridgeERC20To(...)
L2Bridge->>L2Bridge: Burn user's OptimismMintableERC20
Note over L2Bridge: Emit WithdrawalInitiated
L2Bridge->>Passer: (via L2CrossDomainMessenger) initiateWithdrawal(...)
Note over DGF: Proposer creates a dispute game for an output root (~hourly)
User->>Portal: proveWithdrawalTransaction(tx, gameIndex, outputRootProof, withdrawalProof)
Note over Portal: Wait 7 days + game resolved and past finality delay
User->>Portal: finalizeWithdrawalTransaction(tx)
Portal->>L1Bridge: (via L1CrossDomainMessenger) finalizeBridgeERC20(...)
L1Bridge->>User: Release locked L1 tokens
Three things make this slow:
- Output root proposal: a new dispute game roughly every hour on OP Mainnet (the last 94 games in its
DisputeGameFactoryspan ~94 hours, Oct 2026) - Proof maturity: 7 days after proving, and the dispute game must have resolved in the proposer's favour (so fault proofs can be played)
- Two-phase finalization: prove + finalize (separate transactions)
Total: ~7 days from withdrawal initiation to L1 settlement.
The waiting period exists so anyone can win a fault proof dispute game against a proposer who lies about the L2 state. Without it, a proposer could post a fake output root and the L1 contract would trust it.
3. Reading the real contracts
The canonical OP bridge code lives in ethereum-optimism/optimism, packages/contracts-bedrock/. Key files:
| Contract | Role |
|---|---|
src/L1/L1StandardBridge.sol | L1 entry point for users (deposit) and exit point (withdraw); holds bridged ERC-20s |
src/L2/L2StandardBridge.sol | L2 mirror — burns bridged tokens on withdrawal |
src/L1/OptimismPortal2.sol | The actual L1 inbox/outbox: depositTransaction, proveWithdrawalTransaction, finalizeWithdrawalTransaction |
src/L1/ETHLockbox.sol | Holds deposited ETH on chains that use it (OP Mainnet does) |
src/dispute/DisputeGameFactory.sol | Output-root commitments on L1, as dispute games (replaced the old L2OutputOracle) |
src/L1/L1CrossDomainMessenger.sol | Generic message passing (not just tokens) |
src/L2/L2ToL1MessagePasser.sol | L2 side of withdrawals: stores the withdrawal hashes that get proven on L1 |
The bridge is just the asset interface. Underneath, there's a generic cross-domain messenger that handles any calldata.
🔍 Find in repo. Open
L1StandardBridge.sol. Trace what happens whendepositERC20is called. At what point is the deposit guaranteed to happen on L2?
Once the L1 transaction is final. The derivation rules force every L2 node to include the deposit (within the sequencing window), so a sequencer that drops it produces a chain honest nodes reject. The L1 contract itself never learns anything about L2 for a deposit; fault proofs matter only for the other direction.
4. The fast withdrawal market
7-day withdrawal is unusable for many use cases. The market response: third-party fast withdrawals.
A liquidity provider:
- Sees your withdrawal initiated on L2
- Sends you L1 tokens immediately (minus a fee)
- Waits 7 days
- Claims your L1 withdrawal when the period expires
The LP is taking on withdrawal risk (in case L1 state proof fails) in exchange for fee income. Intent-based bridges such as Across do this at scale.
This is not a bridge in the trust sense — it's a financial product layered on top of the trustless bridge. The trust split:
- Bridge itself: trustless (rollup consensus)
- Fast withdrawal LP: capital risk (no trust on user, just market efficiency)
5. The Standard Bridge vs Native Bridge
There is no separate "native bridge": the same L1StandardBridge / L2StandardBridge pair handles both.
- ETH:
depositETH/bridgeETHTo. On L2 it arrives as the native gas token (the deposit tx mints it). - ERC-20s:
depositERC20/bridgeERC20To. The L1 token is locked inL1StandardBridge; on L2 the bridge mints anOptimismMintableERC20(usually created viaOptimismMintableERC20Factory).
There is no registry to sign up for. Instead, the L2 token itself names its L1 counterpart (remoteToken), and the bridge checks the pair on every transfer (_isCorrectTokenPair in StandardBridge.sol). If the pair doesn't match, the bridge refuses. (The OP token is native to OP Mainnet; it isn't bridged in.)
For Tempo, this matters: if Tempo has a stablecoin native to its chain, and you want it on Ethereum, you'd need a Standard Bridge equivalent with the Tempo-Ethereum token pair registered.
6. Tempo↔Ethereum via OP Standard Bridge?
Tempo is not an OP Stack chain (it's a standalone L1). So the OP Standard Bridge doesn't directly apply. But the pattern does:
For Tempo↔Ethereum, the equivalent would be:
- Tempo Standard Bridge (Solidity contracts on both sides)
- Light client of Ethereum on Tempo
- Light client of Tempo on Ethereum (the hard one)
- Withdrawal challenge period (longer if no light client yet)
Until ZK light clients ship, this is CCIP territory — which we cover next lesson.
7. Reading exercise
In ethereum-optimism/optimism/packages/contracts-bedrock:
src/L1/L1StandardBridge.sol— read the deposit function in fullsrc/L1/OptimismPortal2.sol— find where L2 → L1 messages are proven and finalizedsrc/dispute/DisputeGameFactory.sol— find the function proposers call to post an output root (create)- Calculate: how many L1 transactions does a withdrawal require? Why?
Three answers: proveWithdrawalTransaction + wait + finalizeWithdrawalTransaction. Two L1 txs minimum.
8. The op-bridge ExEx pattern
From the Building tier's reorg-aware indexer lab, the op-bridge ExEx example is a real-world indexer that watches L1StandardBridge events:
sol!(L1StandardBridge, "l1_standard_bridge_abi.json");
use crate::L1StandardBridge::{
ETHBridgeFinalized, ETHBridgeInitiated, L1StandardBridgeEvents,
};
This is how indexers (and bridges) consume cross-chain events. The ExEx runs inside an L1 Reth node, watches every block, decodes bridge events, and stores them in its own SQLite database. A bridge contract on the other side can query this index.
The same pattern works for Tempo: an ExEx on Tempo that watches CCIP bridge events would feed the merchant treasury system.
9. Reading list
- Optimism docs — the developer's view
- OP Stack contracts-bedrock — the real code
- Across whitepaper — fast withdrawal market design
Final check: in one sentence, why is the OP Standard Bridge "trustless" but requires a 7-day withdrawal delay? If your answer doesn't reference "optimistic security + fault proofs," re-read §2.
Summary (3 lines)
- OP bridge =
L1StandardBridge+L2StandardBridgeover the cross-domain messengers. Deposit ~1–3 min (fast); withdrawal 7 days (slow — the fault-proof window is the security model). - Trust anchor =
OptimismPortal2(ETH inETHLockboxon OP Mainnet); bug there is catastrophic. Upgrade and pause keys are part of the trust model.CrossDomainMessengeris the general primitive;StandardBridgeis a specialisation for ETH/ERC-20. - Liquidity-provider bridges (e.g. Across) front user funds for instant withdrawal and reclaim from the canonical bridge after 7 days — fee in exchange for speed. Next lesson reads CCIP, Chainlink's cross-chain rail.