How to adopt the bridged USDC standard on your Arbitrum chain
Circle’s Bridged USDC Standard is a specification and process for deploying a bridged form of USDC on EVM blockchains with optionality for Circle to seamlessly upgrade to native issuance in the future.
Why adopt the bridged USDC standard?
When USDC is bridged into an Arbitrum chain, the default path is to use the chain’s canonical gateway contracts for ERC-20's. By way of example, when a user bridges USDC from Arbitrum One to an Arbitrum chain, their Arbitrum One USDC tokens are locked into the Arbitrum chain’s parent side bridge, and a representative USDC token is minted to the user’s address on the Arbitrum chain, via the child side bridge.
The challenge with this user flow is twofold.
- Native vs. non-Native
USDC: TheUSDCtokens issued by Circle (’native USDC’) are locked in the parent side bridge contract. Conversely, theUSDCtokens on the Arbitrum chain aren’t nativeUSDCbut are collateralized by the locked tokens in the bridge. As such, Circle will not recognize these tokens across their product suite. - Fragmented UX: If Circle were to provide native support for
USDCby deploying aUSDCcontract on the Arbitrum chain, there would be two forms ofUSDCon the chain (native and non-nativeUSDC). This leads to a fragmented user experience, and users with non-native USDC would have to withdraw to the parent chain to be able to turn their tokens into nativeUSDC.
By deploying the bridged USDC standard from the start, all USDC tokens that are bridged are locked in a gateway contract that can be adopted by Circle should a chain upgrade its USDC into native USDC. This allows USDC adoption on Arbitrum chains today without encountering either of the two problems above.
How to implement the bridged USDC Standard
We provide a custom USDC gateway implementation (for parent and child chains) that follows the Bridged USDC Standard. These contracts can be used by new Arbitrum chains. This solution will not be used in existing Arbitrum chains that are governed by the DAO.
- On a parent chain the contract
L1USDCGatewayis used in case the child chain usesETHas native currency, orL1OrbitUSDCGatewayin case the child chain uses a custom fee token. - On a child chain,
L2USDCGatewayis used. - For the
USDCtoken contracts, Circle's reference implementation is used.
This page describes how to deploy a USDC bridge compatible with both the Arbitrum chain (Orbit) token bridge and Circle’s Bridged USDC Standard.
Steps for a transition to native USDC issuance are also provided. Note that both Circle and the Arbitrum chain owner must agree to transition to native USDC issuance.
Requirements
- Recommended token bridge version 1.2.0
- No additional dependencies with Nitro or Nitro contract version
Other requirements:
- It is assumed there is already a
USDCtoken deployed and used on the parent chain. - Also, it is assumed that the standard Arbitrum chain ownership system is used, i.e.,
UpgradeExecutoris the owner of theownablecontracts, and there is an EOA or multi-sig that has the executor role on theUpgradeExecutor. - Refer to the token bridge overview page for more information about the token bridge design and operational dynamics. You can learn more in our overview of gateways operating models.
Deployment steps
Checkout target code, install dependencies, and build
cd token-bridge-contracts
yarn install
yarn build
Populate your .env file based on env.example in the project's root directory
PARENT_RPC=
PARENT_DEPLOYER_KEY=
CHILD_RPC=
CHILD_DEPLOYER_KEY=
L1_ROUTER=
L2_ROUTER=
INBOX=
L1_USDC=
## OPTIONAL arg. If set, the script will register the gateway. Otherwise, it will store the transaction's payload in a file
ROLLUP_OWNER_KEY=
Run the script
yarn deploy:usdc-token-bridge
The script will do the following:
- load deployer wallets for L1 and L2
- register L1 and L2 networks in SDK
- deploy new L1 and L2 proxy admins
- deploy bridged (L2)
USDCusing the Circle's implementation - init L2
USDC - deploy L1
USDCgateway - deploy L2
USDCgateway - init both gateways
- if
ROLLUP_OWNER_KEYis provided, register the gateway in the router through the UpgradeExecutor - if
ROLLUP_OWNER_KEYis not provided, prepare calldata and store it in theregisterUsdcGatewayTx.jsonfile - set minter role to L2
USDCgateway with max allowance
Now, new USDC gateways can be used to deposit/withdraw USDC. Everything is now in place to support transition to native USDC issuance if Circle and the Arbitrum chain owner agree to it.
Transitioning to native USDC
Once a transition to native USDC is agreed upon, the following steps are required:
- L1 gateway owner pauses deposits on the parent chain by calling
pauseDeposits() - L2 gateway owner pauses withdrawals on the child chain by calling
pauseWithdrawals() - master minter removes the minter role from the child chain gateway
There should be no in-flight deposits when the minter role is revoked. If there are any, they should be finalized first. Anyone can do that by claiming the failed retryable tickets that execute a USDC deposit
- L1 gateway owner sets Circle's account as burner on the parent chain gateway using
setBurner(address) - L1 gateway owner reads the total supply of
USDCon the child chain and then invokessetBurnAmount(uint256)on the parent/child gateway where the amount matches the total supply USDCmasterMintergives the minter role with0allowance to the L1 gateway so that the burn can be executed- on the child chain, the L2 gateway owner calls the
setUsdcOwnershipTransferrer(address)to set the account (provided and controlled by Circle), which will be able to transfer the bridgedUSDCownership and proxy admin - if not already owned by the gateway, the L2
USDCowner transfers ownership to the gateway, and proxy admin transfers admin rights to the gateway - Circle uses the
usdcOwnershipTransferreraccount to triggertransferUSDCRoles(address), which will set the caller asUSDCproxy admin and will transferUSDCownership to the provided address - Circle calls
burnLockedUSDC()on the L1 gateway using theburneraccount to burn theburnAmountofUSDC- remaining
USDCwill be cleared off when remaining in-flightUSDCwithdrawals are executed, if any - The L1 gateway owner is trusted to not front-run this transaction to modify the burning amount
- remaining