Skip to main content
Bridge USDC from Ethereum Mainnet to Arc Mainnet with Circle’s CCTP V2. Para authenticates the user and signs transactions on both chains. Bridge Kit handles the approval, burn, attestation, and mint steps.

Before you start

Start with a Next.js app that has ParaProvider, a login flow, and an EVM wallet for the signed-in user. These Para guides cover that setup:
The wallet needs native USDC to bridge and ETH for Ethereum gas. It also needs enough USDC on Arc to pay for a destination transaction, since Arc uses USDC as its gas token. Review the transfer amount and network fees with the user before submitting a mainnet transaction.
This route uses CCTP domain 0 for Ethereum and domain 26 for Arc. These are protocol domain IDs, not EVM chain IDs. Bridge Kit’s Ethereum and Arc chain definitions carry the domains and CCTP contract addresses; the example does not hardcode them.

Install the bridge packages

From your Para Next.js application, install Bridge Kit, Circle’s viem adapter, and the Para viem integration. The versions below are the ones used for this guide.
Set NEXT_PUBLIC_ETHEREUM_RPC_URL and NEXT_PUBLIC_ARC_RPC_URL to RPC endpoints for the two mainnets. The values are public browser configuration, so do not put private RPC credentials in them.

Connect Para to Bridge Kit

Use and inside your existing ParaProvider to check the signed-in Para wallet. Confirm the session with . selects the EVM wallet, and gives Circle’s ViemAdapter a wallet client for each chain. Both clients use the same Para account.
src/hooks/useCctpAdapter.ts
Keep the authenticated Para session available until the bridge finishes. Do not replace the Para account with a private-key viem account: that would bypass Para signing.

Bridge Ethereum USDC to Arc

Call bridge() in response to a user action. Bridge Kit uses CCTP V2 to burn USDC on Ethereum, waits for Circle’s attestation, then mints USDC on Arc. Setting useForwarder: false keeps the Arc mint signed by Para. The result contains each step and the overall state. amount is a human-readable USDC amount.
src/hooks/useCctpBridge.ts
In a client component, call bridgeUsdc("1.00") from a transfer button. It returns the Bridge Kit result and a summary with status, failedStep, and the burn and mint transaction hashes and explorer links. Show a transfer as complete only when status is complete. For a failed transfer, read failedStep?.name and failedStep?.errorMessage. Handle errors thrown before Bridge Kit returns a result separately. Open the Ethereum burn and Arc mint explorer links to check their receipts and transferred amounts. The fetchAttestation event records progress between those transactions; it is not itself an onchain transaction.

Resume an interrupted transfer

If result.state is error, inspect result.steps before asking the user to try again. An approved or burned transfer may already have spent gas or destroyed the source USDC. Keep that result and pass it to resumeTransfer(result) from a separate Resume action. The hook gives Bridge Kit’s retry() a fresh authenticated Para adapter and returns the updated result and status summary. Do not start a second bridge() call to recover a transfer whose burn succeeded. If a retry still fails, keep the burn transaction hash and investigate the failed step before attempting another transaction. A pending result is not a confirmed destination mint.

Check the route

For a production check, record both the Ethereum burn transaction and the Arc mint transaction from the same Bridge Kit result. The source receipt alone confirms only the burn. The destination explorer receipt confirms the mint. For a testnet trial before using mainnet funds, follow Circle’s . Circle’s covers fees, supported routes, and recovery behavior.

Keep building with Para

Use the same signed-in Para wallet for other EVM actions: