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 thesecondBridgeAddress
with the custom shared bridge deployed on L1. This way, the bridgehub contracts knows which contract to ping to. requestL2TransactionTwoBridges
makes a call to the custom shared bridgecustomBridgeL1.bridgehubDeposit
function and transfersUSDC
from the user to this contract and emits an event.- sequencers will pick this event and automatically make a call to
customL2Bridge.finalizeDeposit
on the custom bridge deployed on L2 (on Sophon). finalizeDeposit
is the one that callsusdc.mint()
to mintUSDC
on L2 (note this custom bridge must haveMINTER
role on theUSDC
contract).
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.finalizeWithdrawal
to finalise the withdrawal
$ forge build
# zkSync build
$ forge build --zksync --contracts ./src/
# Deploy L1 Shared Bridge
$ source .env && forge script ./script/DeployL1USDCBridge.s.sol --rpc-url ethereum --private-key $PRIVATE_KEY --verify --broadcast
# Deploy L2 Shared Bridge
$ source .env && forge script ./script/DeployL2USDCBridge.s.sol --rpc-url sophon --private-key $PRIVATE_KEY --zksync --broadcast --verify --slow
# Initialise L1 Shared Bridge
$ source .env && forge script ./script/InitialiseL1USDCBridge.s.sol --rpc-url ethereum --private-key $PRIVATE_KEY --broadcast
# Bridge from Sophon to Ethereum (L1 -> L2)
$ source .env && forge script ./script/Bridge.s.sol --rpc-url ethereum --private-key $PRIVATE_KEY --ffi --broadcast
# Withdraw from Sophon to Ethereum (L2 -> L1)
$ source .env && forge script ./script/Withdraw.s.sol --rpc-url sophon --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 ethereum --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 snapshot