Skip to content

Commit 8a9f1d6

Browse files
authored
feat: usdc bridge deployment (#93)
* Deployer script draft * Deploy bridged usdc * Init gateways * Add env.example * Add register gateway script draft * Load upg executor * Add registration logic * Add env examples * Do registration in the same script * Remove separate script for registration * Add env var check * Get rollup address from inbox * Init logic to dummy values * Use SDK estimations instead of hard-coding retryable params * If owner is multisig print TX data to a file * Make gw registration work for fee token chains * Deploy orbit gateway when fee token used * Make ROLLUP_OWNER_KEY optional * Set minter role to L2 gateway * Refactor * Check initialization * Add yarn action * Add readme for deployment * Deploy master minter * Use MasterMinter contract * Update readme with usdc upgrade procedure * Add comment * Add fee transfer logic to list of TXs stored into a file * Do scaling in case of non-18 decimals fee token * Add more docs * Update slither db * Readme clarifications
1 parent d2c09d2 commit 8a9f1d6

File tree

8 files changed

+893
-2
lines changed

8 files changed

+893
-2
lines changed

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,7 @@ network.json
2323

2424
# Gambit (mutation test) files
2525
gambit_out/
26-
test-mutation/mutant_test_env/
26+
test-mutation/mutant_test_env/
27+
28+
# bridged usdc deployment script
29+
registerUsdcGatewayTx.json

contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
2222
* - withdrawals can be paused by the owner
2323
* - owner can set an "transferrer" account which will be able to transfer USDC ownership
2424
* - transferrer can transfer USDC owner and proxyAdmin
25+
*
26+
* NOTE: before withdrawing funds, make sure that recipient address is not blacklisted on the parent chain.
27+
* Also, make sure that USDC token itself is not paused. Otherwise funds might get stuck.
2528
*/
2629
contract L2USDCGateway is L2ArbitrumGateway {
2730
using SafeERC20 for IERC20;

contracts/tokenbridge/ethereum/gateway/L1USDCGateway.sol

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ import {IFiatToken, IFiatTokenProxy} from "../../libraries/IFiatToken.sol";
2929
*
3030
* This contract is to be used on chains where ETH is the native token. If chain is using
3131
* custom fee token then use L1OrbitUSDCGateway instead.
32+
*
33+
* NOTE: before depositing funds, make sure that recipient address is not blacklisted on the child chain.
34+
* Also, make sure that USDC token itself is not paused. Otherwise funds might get stuck.
3235
*/
3336
contract L1USDCGateway is L1ArbitrumExtendedGateway {
3437
address public l1USDC;

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
"test:tokenbridge:deployment": "hardhat test test-e2e/tokenBridgeDeploymentTest.ts",
2929
"test:creation-code": "hardhat test test-e2e/creationCodeTest.ts",
3030
"blockscout:verify": "hardhat run ./scripts/orbitVerifyOnBlockscout.ts",
31+
"deploy:usdc-token-bridge": "hardhat run scripts/usdc-bridge-deployment/deployUsdcBridge.ts",
3132
"typechain": "hardhat typechain",
3233
"deploy:tokenbridge": "hardhat run scripts/deploy_token_bridge_l1.ts --network mainnet",
3334
"gen:uml": "sol2uml ./contracts/tokenbridge/arbitrum,./contracts/tokenbridge/ethereum,./contracts/tokenbridge/libraries -o ./gatewayUML.svg",
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# Bridged USDC standard implementation for Orbit chains
2+
3+
## Background
4+
5+
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.
6+
7+
We provide custom USDC gateway implementation (for parent and child chain) that follows Bridged USDC Standard. These contracts can be used by new Orbit chains. This solution will NOT be used in existing Arbitrum chains. On parent chain contract `L1USDCGateway` is used in case child chain uses ETH as native currency, or `L1OrbitUSDCGateway` in case child chain uses custom fee token. On child chain `L2USDCGateway` is used. For the USDC token contracts, Circle's referent implementation is used.
8+
9+
This doc describes how to deploy USDC bridge compatible with both Arbitrum's token bridge and Circle’s Bridged USDC Standard.Also steps for transition to native USDC issuance are provided.
10+
11+
## Assumptions
12+
13+
It is assumed there is already USDC token deployed and used on the parent chain.
14+
15+
Also, it is assumed the standard Orbit chain ownership system is used, ie. UpgradeExecutor is the owner of the ownable contracts and there is an EOA or multisig which has executor role on the UpgradeExecutor.
16+
17+
Note: throughout the docs and code, terms `L1` and `L2` are used interchangeably with `parent chain` and `child chain`. They have the same meaning, ie. if an Orbit chain is deployed on top of ArbitrumOne then ArbitrumOne is `L1`/`parent chain`, while Orbit is `L2`/`child chain`
18+
19+
## Deployment steps
20+
21+
Checkout target code, install dependencies and build
22+
23+
```
24+
cd token-bridge-contracts
25+
yarn install
26+
yarn build
27+
```
28+
29+
Populate .env based on `env.example` in this directory
30+
31+
```
32+
PARENT_RPC=
33+
PARENT_DEPLOYER_KEY=
34+
CHILD_RPC=
35+
CHILD_DEPLOYER_KEY=
36+
L1_ROUTER=
37+
L2_ROUTER=
38+
INBOX=
39+
L1_USDC=
40+
## OPTIONAL arg. If set, script will register the gateway, otherwise it will store TX payload in a file
41+
ROLLUP_OWNER_KEY=
42+
```
43+
44+
Run the script
45+
46+
```
47+
yarn deploy:usdc-token-bridge
48+
```
49+
50+
Script will do the following:
51+
52+
- load deployer wallets for L1 and L2
53+
- register L1 and L2 networks in SDK
54+
- deploy new L1 and L2 proxy admins
55+
- deploy bridged (L2) USDC using the Circle's implementation
56+
- init L2 USDC
57+
- deploy L1 USDC gateway
58+
- deploy L2 USDC gateway
59+
- init both gateways
60+
- if `ROLLUP_OWNER_KEY` is provided, register the gateway in the router through the UpgradeExecutor
61+
- if `ROLLUP_OWNER_KEY` is not provided, prepare calldata and store it in `registerUsdcGatewayTx.json` file
62+
- set minter role to L2 USDC gateway with max allowance
63+
64+
Now new USDC gateways can be used to deposit/withdraw USDC. And everything is in place to support transtition to native USDC issuance, in case Circle and Orbit chain owner agree to it.
65+
66+
## Transition to native USDC
67+
68+
Once transition to native USDC is agreed on, following steps are required:
69+
70+
- L1 gateway owner pauses deposits on parent chain by calling `pauseDeposits()`
71+
- L2 gateway owner pauses withdrawals on child chain by calling `pauseWithdrawals()`
72+
- master minter removes the minter role from the child chain gateway
73+
- NOTE: there should be no in-flight deposits when minter role is revoked. If there are any, they should be finalized first. That can be done by anyone by claiming the claimable failed retryable tickets which do the USDC depositing
74+
- L1 gateway owner sets Circle's account as burner on the parent chain gateway using `setBurner(address)`
75+
- L1 gateway owner reads the total supply of USDC on the child chain, and then invokes `setBurnAmount(uint256)` on the parent child gateway where the amount matches the total supply
76+
- USDC masterMinter gives minter role with 0 allowance to L1 gateway, so the burn can be executed
77+
- on the child chain, L2 gateway owner calls the `setUsdcOwnershipTransferrer(address)` to set the account (provided and controlled by Circle) which will be able to transfer the bridged USDC ownership and proxy admin
78+
- if not already owned by gateway, L2 USDC owner transfers ownership to gateway, and proxy admin transfers admin rights to gateway
79+
- Circle uses `usdcOwnershipTransferrer` account to trigger `transferUSDCRoles(address)` which will set caller as USDC proxy admin and will transfer USDC ownership to the provided address
80+
- Circle calls `burnLockedUSDC()` on the L1 gateway using `burner` account to burn the `burnAmount` of USDC
81+
- remaining USDC will be cleared off when remaining in-flight USDC withdrawals are executed, if any
82+
- L1 gateway owner is trusted to not frontrun this TX to modify the burning amount

0 commit comments

Comments
 (0)