fast-fill — Live Mainnet Demo (CCTP, Base ⇄ Arbitrum)
This is a record of fast-fill running on Ethereum mainnet L2s with real USDC: the CctpAdapter
deployed on Base and Arbitrum, three real $1 transfers, settled through Circle's real attestation
service and MessageTransmitterV2. All amounts are in USDC base units (6 decimals; 1,000,000 = $1).
Prototype, unaudited. Run with ~$5 of USDC for demonstration only.
This historical demo predates
CctpExecutor. It demonstrates the direct CCTP adapter settlement path that is still used whenmintFee == 0. The executor-routed path (mintFee > 0) has since been deployed and smoke-tested; see DEPLOYMENTS.md.
Deployments
| What | Address |
|---|---|
CctpAdapter (Base) | 0xC4a956Ec34BF7C0B07e4c84B72232E83879Ce1c0 |
CctpAdapter (Arbitrum) | 0xA4a9CaC201a6A625C04552624d8D1b172B08fad9 |
| User / relayer (EOA) | 0xA06Bf163BC51A457D99C6283e78897727c4fDdF2 |
Owner = the EOA. Wired bidirectionally: domains (Base 6, Arbitrum 3), remote adapters, and per-chain
USDC (remoteUsdc).
Runs 1 & 2 — baseline path (no relayer)
A $1 transfer Base→Arbitrum with no optimistic fill: the recipient simply receives the funds when the CCTP message settles. Each delivered 999,870 (the 130-unit haircut is Circle's 1.3 bps fast-transfer fee). These also seeded USDC onto Arbitrum to use as relayer liquidity for Run 3.
| Step | Chain | Tx |
|---|---|---|
Run 1 — burn (initiateCCTP) | Base | 0x1ac1f0d3…dde2d2 |
| Run 1 — settle | Arbitrum | 0x4920e31c…dc405d |
| Run 2 — burn | Base | 0x9119fa4b…43afe2 |
| Run 2 — settle | Arbitrum | 0x71361a96…90c2c8 |
Run 3 — optimistic fill (the headline)
A $1 transfer Base→Arbitrum to a fresh recipient 0xb959…bE53, with a user-chosen premium that
caps at the adapter's 0.5%. The relayer fronts the funds on Arbitrum before the bridge settles,
then is reimbursed when it does.
| Step | Chain | Tx | Effect |
|---|---|---|---|
| initiate ($1, premium order) | Base | 0x9d449485…573d09 | burns 1,000,000; outputAmount = 999,800 |
| fill (relayer) | Arbitrum | 0x7764c033…1625fde | recipient +994,801 instantly |
| settle | Arbitrum | 0x1b6bc543…4614e3 | relayer +999,800; recipient +70 surplus |
orderId 0x5711e377…8286af; final record filler = EOA, status = Settled.
Outcome
| Party | Result |
|---|---|
Recipient 0xb959…bE53 | 994,871 total — of which 994,801 arrived at fill time, before the bridge settled |
| Relayer (EOA) | net +4,999 (~$0.005) — the 0.5% premium earned for fronting capital over the bridge-latency window |
| Premium | 4,999 / 999,800 ≈ 0.5% (the adapter maxFeeRate cap) |
The recipient got their money in seconds instead of waiting for CCTP, for a sub-cent premium; the relayer earned that premium. And Runs 1–2 show the fallback: if nobody fills, the recipient just gets the funds when CCTP settles, at no premium.
How it was reproduced
Note: this run predates the config-registry refactor and the CCTP Executor, so the deploy/wire steps below reflect the original per-instance setters. The current flow deploys one immutable
FastFillConfig(CREATE2), thenCctpExecutor, then the CCTP adapter with the executor address baked in — see README → Deploy. The directmintFee == 0fill/attest/settle mechanics are unchanged.
- Deploy
CctpAdapteron each chain (forge create, constructor: owner, maxFeeRate,TokenMessengerV2,MessageTransmitterV2, USDC). - Wire each:
setDomain,setRemoteAdapter,setRemoteUsdc(addresses inscript/config/Addresses.sol). - Initiate on the source: approve the adapter, then
initiateCCTP(dstChainId, recipient, amount, maxFee, mintFee, minFinalityThreshold, deliveryWindow, discountRate, baseFee, exec)—mintFee = 0uses the directsettlepath shown here;mintFee > 0routes settlement throughCctpExecutor.execute.minFinalityThresholdis 1000 (fast) or 2000 (finalized);deliveryWindowis relative seconds;baseFeeis the flat optimistic-fill fee (0 for none). (This historical run predated the relative-window + base-fee + destination-execution additions.) - (optional) Fill on the destination before settlement: relayer approves the adapter and calls
fill(order). - Attest: poll Circle's API
https://iris-api.circle.com/v2/messages/{srcDomain}?transactionHash={burnTx}untilstatus == complete. - Settle on the destination, direct path:
settle(message, attestation)(wraps the realreceiveMessage). Executor-routed orders instead callCctpExecutor.execute(message, attestation).
See docs/ARCHITECTURE.md for how the contracts work, and test/fork/CctpForkE2E.t.sol for the fork-based dry-run that validated the source + message parsing against the real CCTP contracts before any funds were spent.
Additional live coverage
The CctpExecutor-routed CCTP path has now been demonstrated with live USDC for both unfilled and optimistically filled orders; see DEPLOYMENTS.md. The OFT (LayerZero) path is proven in the local + mock harness and is wired the same way, but a live OFT demo additionally requires deploying a demo OFT on both chains and configuring the LayerZero peers + DVN/executor security stack. Tracked as follow-up work.
