The Bridge
How the ADI Canonical Bridge moves assets between Ethereum and ADI Chain — securely, trustlessly, and with zero-knowledge proofs.
The Bridge is the native, protocol-level bridge that connects Ethereum (L1) with the ADI Chain. Unlike third-party bridges that rely on external validators or multisigs, the canonical bridge inherits the full security of the Ethereum mainnet — every cross-chain message is verified through zero-knowledge proofs, making it as secure as Ethereum itself.
The bridge serves two primary purposes:
Deposits (L1 → L2): Move assets from Ethereum to ADI Chain, where they can be used for transactions, DeFi, and other on-chain activities with significantly lower fees and faster confirmations.
Withdrawals (L2 → L1): Move assets back from ADI Chain to Ethereum, verified by cryptographic proofs that guarantee correctness without trusting any intermediary.
The bridge supports:
Native ADI deposits — the chain's base gas token
ERC20 token deposits — any standard ERC20
First-time token bridging — automatic contract deployment on the destination chain
What Makes ADI Different
ADI Chain uses ADI as its native gas token instead of ETH. This means:
All L2 transaction fees are paid in ADI
When you deposit ADI from L1, it becomes native balance on L2 (like ETH on Ethereum)
ADI exists as an ERC20 token on Ethereum, and as the native currency on ADI Chain
Other ERC20 tokens can also be bridged and are represented as wrapped tokens on L2
How It Works — The Big Picture
Deposit (L1 → L2) — lock tokens on Ethereum, mint on ADI Chain:
Withdrawal (L2 → L1) — burn tokens on L2, prove to Ethereum, claim:
Core Contracts
Bridgehub
L1
Deployed per ecosystem
Central registry and routing for all L2 chains. Entry point for deposits
L1 Asset Router
L1
Deployed per ecosystem
Routes asset operations (lock/unlock) to appropriate asset handlers
L1 Native Token Vault
L1
Deployed per ecosystem
Holds locked L1 tokens. Deploys bridged token contracts for L2-native tokens
L1 Nullifier
L1
Deployed per ecosystem
Verifies Merkle proofs and prevents double-claiming of withdrawals
Mailbox
L1
Per-chain Diamond Proxy
Serializes L1→L2 transactions and manages the priority queue
Executor
L1
Per-chain Diamond Proxy
Handles batch commit, prove, and execute lifecycle
L2 Asset Router
L2
0x0000...00010003
Routes deposits to NTV on L2. Entry point for ERC20 withdrawals
L2 Native Token Vault
L2
0x0000...00010004
Mints/burns bridged tokens. Deploys new token contracts on first bridge
L1 Messenger
L2
0x0000...00008008
System contract that sends L2→L1 messages (included in batch proofs)
L2 Base Token
L2
0x0000...0000800A
System contract representing the chain's base token (ADI)
Contract Deployer
L2
0x0000...00008006
System contract for deterministic CREATE2 deployments on L2
Deposits: Moving Assets to ADI Chain (L1 → L2)
Deposits are fast — typically complete within ~15 seconds. Since Ethereum is the source of truth, the ADI sequencer can trust L1 events immediately and process them on L2.
How a Deposit Works
Step by Step
Step 1 — Approve Before depositing, you authorize the bridge to transfer your tokens. For ADI, this is a standard ERC20 approve(). For ERC20 tokens, a separate approval is needed for both the token and ADI (to cover L2 gas).
Step 2 — Initiate the Deposit You submit your deposit through the Bridgehub — the central entry point that coordinates all cross-chain transactions. The Bridgehub validates your request and routes it to the appropriate bridge contracts.
Step 3 — Tokens Are Locked The L1 Asset Router directs your tokens to the L1 Native Token Vault, where they are securely locked. A strict accounting system tracks every token locked per chain, ensuring 1:1 backing at all times.
Step 4 — Priority Transaction Created The Mailbox contract registers your deposit as a priority transaction — an L1→L2 message that the sequencer must process. This emits a NewPriorityRequest event on Ethereum.
Step 5 — L2 Execution The ADI sequencer detects the event, includes it in the next L2 block, and executes it:
For ADI deposits: the bootloader mints native ADI balance to your L2 address
For ERC20 deposits: the L2 Asset Router calls the L2 Native Token Vault, which mints a bridged token representation on L2. If this is the first time a token is being bridged, a new ERC20 contract is automatically deployed on L2 (see First-Time Token Bridging).
Step 6 — Complete Your tokens are now available on ADI Chain. The entire process takes roughly 15 seconds.
Two Deposit Paths
The bridge uses different entry points depending on the token being deposited:
Aspect
Direct (requestL2TransactionDirect)
Two Bridges (requestL2TransactionTwoBridges)
Use case
ADI base token deposits
ERC20 token deposits
Why
Only one token operation needed (lock ADI)
Two token operations: lock ADI for gas + lock ERC20
L2 sender
msg.sender (user, aliased if contract)
secondBridgeAddress (L1 Asset Router)
L2 target
Caller-specified
Set by second bridge (L2 Asset Router)
L2 calldata
Caller-specified
Generated by second bridge (finalizeDeposit)
Deposit tracking
None
depositHappened stored for failed deposit recovery
Withdrawals: Moving Assets Back to Ethereum (L2 → L1)
Withdrawals require more time — typically about 75 minutes — because the bridge must generate a zero-knowledge proof to convince Ethereum that your L2 transaction actually happened. This proof-based approach is what gives the canonical bridge its security: no one can fabricate a withdrawal.
The Three Phases
Phase 1 — Initiate the Withdrawal on L2
You submit a withdrawal transaction on ADI Chain:
For ADI: call
withdraw()on the L2 Base Token contract, sending your ADI asmsg.valueFor ERC20 tokens: call
withdraw()on the L2 Asset Router with the token's asset ID
Your tokens are burned on L2, and the L1 Messenger system contract records a withdrawal message. This message is cryptographically committed into a Merkle tree that will later be verified on Ethereum.
Phase 2 — Batch Processing & Proving
This is where the zero-knowledge magic happens:
Batching: The ADI server groups multiple L2 blocks into a single batch
Commitment: The batch data (including the Merkle root of all L2→L1 messages) is posted to Ethereum
Proving: A zero-knowledge proof is generated, mathematically proving that every transaction in the batch was executed correctly
Execution: The proof is verified on Ethereum and the batch is finalized. The Merkle root is now stored on-chain, making your withdrawal provable
Phase 3 — Claim on Ethereum
Once the batch is finalized, you can claim your tokens:
The portal fetches a Merkle proof for your specific withdrawal
You submit a claim transaction to the L1 Nullifier contract
The Nullifier verifies your Merkle proof against the on-chain root
If valid, it marks the withdrawal as finalized (preventing double-claims) and routes the tokens through the L1 Asset Router to the Token Vault, which releases your tokens
Why Withdrawals Take Longer Than Deposits
Trust model
L1 is the source of truth — L2 trusts it immediately
L2 must prove its state to L1
Verification
None needed — L1 events are canonical
ZK proof + Merkle inclusion proof required
Time
~15 seconds
~75 minutes
Why
Sequencer processes L1 events instantly
ZK proof generation is computationally intensive
The Settlement Waterfall
Every withdrawal goes through a strict sequence of on-chain verification steps before tokens can be released. This "waterfall" ensures that no invalid state transition can ever result in tokens being unlocked on L1.
Each step in this waterfall is irreversible and verifiable on-chain:
Commitment makes the batch data publicly available
Proving cryptographically guarantees every transaction in the batch is valid
Execution stores the Merkle root, enabling individual withdrawal proofs
Claiming verifies a specific withdrawal against the stored root
Batch Phases in Detail
Commit
commitBatchesSharedBridge()
Batch data posted to L1. L2 system logs validated (timestamps, priority ops hash, L2→L1 message root). DA proof checked.
totalBatchesCommitted++
~136,000
Prove
proveBatchesSharedBridge()
ZK proof verified on-chain. Proof covers state transition from previous batch commitment to current.
totalBatchesVerified++
~494,000
Execute
executeBatchesSharedBridge()
Batch finalized. L2→L1 logs root stored in l2LogsRootHashes[batchNumber]. Priority operations marked as processed. Withdrawals become claimable.
totalBatchesExecuted++
~117,000
Gas figures are measured against the L1 settlement layer; the same call pattern applies at any settlement boundary, so the magnitudes are broadly representative.
Withdrawals cannot be claimed until the batch completes all three phases. Attempting to claim before execution reverts with LocalRootIsZero (batch not yet executed) or returns a null proof (batch not yet committed).
For a deeper technical dive into the contract methods, token deployment, and security model, see Canonical Bridge Technical Reference.
Last updated
