The USDC bridge is an iteration over the Shared Bridge code to adhere to the native USDC standard.
We want to use the canonical zkSync Bridge with a custom bridge implementation that would work only for USDC (since we want to use the native USDC and not the ERC20 that the zksync bridge deploys by default).
The repo implements the src/L1USDCBridge.sol and src/L2USDCBridge.sol which are custom bridge contracts based on the ones found on MatterLabs era-contracts (we've forked from this commit)
Bridge/Withdrawal flow
The flow to bridge and withdraw using custom bridges is the same as when bridging with any token except for the fact that when Bridgehub is called, you need specify the address of the custom L1 bridge.
To bridge USDC from L1 (Ethereum) -> L2 (Sophon):
- Call
bridgehub.requestL2TransactionTwoBridges(same as normally) but you set thesecondBridgeAddresswith the custom shared bridge deployed on L1. This way, the bridgehub contracts knows which contract to ping to. requestL2TransactionTwoBridgesmakes a call to the custom shared bridgecustomBridgeL1.bridgehubDepositfunction and transfersUSDCfrom the user to this contract and emits an event.- sequencers will pick this event and automatically make a call to
customL2Bridge.finalizeDepositon the custom bridge deployed on L2 (on Sophon). finalizeDepositis the one that callsusdc.mint()to mintUSDCon L2 (note this custom bridge must haveMINTERrole on theUSDCcontract).
To withdraw USDC from L2 (Sophon) -> L1 (Etheruem):
- User makes a call to
customBridgeL2.withdraw(same as normally except for the fact that you're calling the custom bridge contract) - Once the batch is sealed, user needs to call
customL1Bridge.finalizeWithdrawalto finalise the withdrawal
$ forge build
# zkSync build
$ forge build --zksync# Deploy L1 Shared Bridge
$ source .env && forge script ./script/DeployL1USDCBridge.s.sol --rpc-url sepoliaTestnet --private-key $PRIVATE_KEY --verify --broadcast
# Deploy L2 Shared Bridge
$ source .env && forge script ./script/DeployL2USDCBridge.s.sol --rpc-url sophonTestnet --private-key $PRIVATE_KEY --zksync --broadcast --verify --slow
# Initialise L1 Shared Bridge
$ source .env && forge script ./script/InitialiseL1USDCBridge.s.sol --rpc-url sepoliaTestnet --private-key $PRIVATE_KEY --broadcast
# Bridge from Sophon to Ethereum (L1 -> L2)
$ source .env && forge script ./script/Bridge.s.sol --rpc-url sepoliaTestnet --private-key $PRIVATE_KEY --ffi --broadcast
# Withdraw from Sophon to Ethereum (L2 -> L1)
$ source .env && forge script ./script/Withdraw.s.sol --rpc-url sophonTestnet --private-key $PRIVATE_KEY --zksync --slow -vvvv --broadcast
# Finalise withdrawal on Ethereum
$ source .env && export L2_WITHDRAWAL_HASH="YOUR_TX_HASH" && forge script ./script/FinalizeWithdrawal.s.sol --rpc-url sepoliaTestnet --private-key $PRIVATE_KEY --ffi --broadcast$ forge test$ forge coverage --report lcov --no-match-coverage '^.*(node_modules|test|script)/.*$' && genhtml ./lcov.info --branch-coverage --rc derive_function_end_line=0 --output-directory report$ forge fmt$ forge snapshotThe Custom USDC Bridge is distributed under the terms of either
- Apache License, Version 2.0, (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or https://opensource.org/blog/license/mit/)
at your option.