Bridging between L2s with small size
Moving $100 between L2s can cost more than expected if the route goes through Ethereum. A faster bridge may save time and fees, but it adds another settlement system to trust.
I compare the withdrawal path, net amount received, and gas needed on each chain before choosing a route. The calculator below uses placeholder quotes so the comparison is easy to repeat.
Withdrawal through L1 or a liquidity payout
Canonical path: slow but minimal extra trust
Most optimistic rollups use a standard bridge that routes withdrawals back to Ethereum, then you deposit to the destination L2. On OP Stack chains, withdrawals through the Standard Bridge require a 7-day challenge period before finalization on L1. Optimism docs OP Stack withdrawals spec
Arbitrum’s official bridge has the same multi-day wait for withdrawals back to Ethereum, with the docs calling out a 7-8 day window before funds can be claimed. Arbitrum bridge docs
If you follow this path to move between L2s, you have at least two on-chain steps (withdraw to L1, then deposit to the destination). It is slower, but you are not depending on third-party liquidity to get paid out early.
Liquidity bridges: fast but more moving parts
Liquidity bridges front you funds on the destination chain and settle the accounting later. Hop does this with market makers (“Bonders”) who front liquidity using hTokens that are swapped in an AMM. Hop docs
Across uses a relayer model: you deposit into a Spoke Pool on the source chain, relayers pay you on the destination chain, and the relayer is reimbursed from a Hub Pool after an optimistic oracle verifies the relay. Across overview
These paths are much faster, but you are adding smart-contract and liquidity-provider trust to skip the standard bridge delay.
flowchart LR A["L2 A"] -->|"Withdraw to L1 (challenge period)"| B["Ethereum L1"] B -->|"Deposit"| C["L2 B"] A -->|"Liquidity bridge payout"| C
Checks before a $100 test transfer
- I choose the destination L2 and confirm I can pay gas on both sides before I bridge anything.
- I check the canonical bridge path first, then compare a liquidity bridge if I need speed.
- I cap the first transfer to a small test amount (usually $100-$250) and wait for full settlement.
- I record the source tx hash, the destination receive tx, and the total time so I can compare future runs.
- I only scale to a larger transfer after the small test finishes without surprises.
Code: compare bridge paths with fee math
I do a quick fee check before committing. This is not a bridge quote engine; it is just a small calculator to compare the fees and expected net received once you have numbers from the bridge UIs.
from dataclasses import dataclass
@dataclass
class BridgeQuote:
name: str
send_amount_usd: float
bridge_fee_usd: float
slippage_usd: float
source_gas_usd: float
destination_gas_usd: float
def net_received(self) -> float:
"""Return expected amount received after fees and slippage."""
return self.send_amount_usd - self.bridge_fee_usd - self.slippage_usd
def total_cost(self) -> float:
"""Return all-in cost including gas on both chains."""
return self.bridge_fee_usd + self.slippage_usd + self.source_gas_usd + self.destination_gas_usd
def compare(quotes: list[BridgeQuote]) -> None:
"""Print a quick comparison of net received and total cost."""
for quote in quotes:
print(
f"{quote.name}: net ${quote.net_received():.2f}, "
f"total cost ${quote.total_cost():.2f}"
)
if __name__ == "__main__":
# Replace these placeholder numbers with quotes from the bridge UIs.
quotes = [
BridgeQuote(
name="Canonical via L1",
send_amount_usd=500,
bridge_fee_usd=0.00,
slippage_usd=0.00,
source_gas_usd=1.25,
destination_gas_usd=3.50, # L1 finalize + L2 deposit gas
),
BridgeQuote(
name="Liquidity bridge",
send_amount_usd=500,
bridge_fee_usd=2.40,
slippage_usd=0.60,
source_gas_usd=0.90,
destination_gas_usd=0.90,
),
]
compare(quotes)
If the total cost difference is only a couple of dollars, I default to the path with fewer moving parts. I still check the withdrawal delay: a cheaper path is not useful if I need the funds before it settles.
Risk analysis: L2-to-L2 bridging
- Technical risk (bridge mechanics). Standard bridges for optimistic rollups include a 7-day challenge period for withdrawals, which can lock funds longer than expected. Optimism docs OP Stack withdrawals spec
- Technical risk (liquidity bridge design). Liquidity bridges rely on relayers or bonders to front funds and get reimbursed later, which adds smart-contract and counterparty risk. Hop docs Across overview
- Economic risk (liquidity and slippage). AMM-based bridging can see worse rates when liquidity is thin, which matters more at small sizes where a few dollars is a large percentage. Hop docs
- Operational risk (gas on both chains). You often need gas on the source and destination chains, and canonical withdrawals require an L1 finalization step that costs gas. OP Stack withdrawals spec
Before starting the next bridge
- Run a tiny test transfer first and record time-to-receive before you scale size.
- Prefer the simpler path when fee differences are small.
- Keep a small gas buffer on both chains before initiating any bridge.
- Treat liquidity bridges as a convenience tradeoff, not a risk-free upgrade.