Skip to content

Commit aa9a797

Browse files
authored
chore: add details on migrate to native (#195)
2 parents 88b2ece + 1d1bb4d commit aa9a797

File tree

1 file changed

+124
-15
lines changed

1 file changed

+124
-15
lines changed

README.md

Lines changed: 124 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,29 @@
22

33
USDC is one of the most bridged assets across the crypto ecosystem, and USDC is often bridged to new chains prior to any action from Circle. This can create a challenge when bridged USDC achieves substantial marketshare, but native USDC (issued by Circle) is preferred by the ecosystem, leading to fragmentation between multiple representations of USDC. Circle introduced the [Bridged USDC Standard](https://www.circle.com/en/bridged-usdc) to ensure that chains can easily deploy a form of USDC that is capable of being upgraded in-place by Circle to native USDC, if and when appropriate, and prevent the fragmentation problem.
44

5-
Bridged USDC Standard for the OP Stack allows for an efficient and modular solution for expanding the Bridged USDC Standard across the Superchain ecosystem.
6-
7-
Chain operators can use the Bridged USDC Standard for the OP Stack to get bridged USDC on their OP Stack chain while also providing the optionality for Circle to seamlessly upgrade bridged USDC to native USDC and retain existing supply, holders, and app integrations.
5+
Bridged USDC Standard for the OP Stack allows for an efficient and modular solution for expanding the Bridged USDC Standard across the Superchain ecosystem.
86

7+
Chain operators can use the Bridged USDC Standard for the OP Stack to get bridged USDC on their OP Stack chain while also providing the optionality for Circle to seamlessly upgrade bridged USDC to native USDC and retain existing supply, holders, and app integrations.
98

109
## Contracts
10+
1111
> :exclamation: `L1OpUSDCFactory.sol` has been deployed to the following addresses:
12-
- Mainnet: `0x7dB8637A5fd20BbDab1176BdF49C943A96F2E9c6`
13-
- Sepolia: `0x82c6c4940cE0066B9F8b500aBF8535810524890c`
12+
13+
- Mainnet: `0x7dB8637A5fd20BbDab1176BdF49C943A96F2E9c6`
14+
- Sepolia: `0x82c6c4940cE0066B9F8b500aBF8535810524890c`
1415

1516
> :exclamation: `L1OpUSDCBridgeAdapter.sol` has been deployed to the following addresses:
16-
- Sepolia: `0x0429b5441c85EF7932B694f1998B778D89375b12`
17+
18+
- Sepolia: `0x0429b5441c85EF7932B694f1998B778D89375b12`
1719

1820
> :exclamation: `L2OpUSDCBridgeAdapter.sol` has been deployed to the following addresses:
19-
- Optimism Sepolia: `0xCe7bb486F2b17735a2ee7566Fe03cA77b1a1aa9d`
21+
22+
- Optimism Sepolia: `0xCe7bb486F2b17735a2ee7566Fe03cA77b1a1aa9d`
2023

2124
> :exclamation: `Bridged USDC` contract has been deployed to the following addresses:
22-
- Optimism Sepolia: `0x7a30534619d60e4A610833F985bdF7892fD9bcD5`
23-
25+
26+
- Optimism Sepolia: `0x7a30534619d60e4A610833F985bdF7892fD9bcD5`
27+
2428
_`L1OpUSDCFactory.sol`_ - Factory contract to deploy and setup the `L1OpUSDCBridgeAdapter` contract on L1. Precalculates the addresses of the L2 deployments and triggers their deployment, by sending a transaction to L2.
2529

2630
_`L2OpUSDCDeploy.sol`_ - One time use deployer contract deployed from the L1 factory through a cross-chain deployment. Used as a utility contract for deploying the L2 USDC Proxy, and `L2OpUSDCBridgeAdapter` contract, all at once in its constructor.
@@ -40,6 +44,7 @@ _`L2OpUSDCBridgeAdapter`_ - Contract that allows for the transfer of USDC from t
4044
For a user to make a deposit, the process is the following:
4145

4246
### Deposits
47+
4348
1. Users approve the `L1OpUSDCBridgeAdapter` to spend USDC.
4449
2. Users proceed to deposit USDC by calling the contract.
4550
3. The `L1OpUSDCBridgeAdapter` sends the message to the appointed CrossDomainMessenger.
@@ -49,6 +54,7 @@ For a user to make a deposit, the process is the following:
4954
Similarly, for withdrawals:
5055

5156
### Withdrawals
57+
5258
1. Users send `bridgedUSDC` to the `L2OpUSDCBridgeAdapter`.
5359
2. The `L2OpUSDCBridgeAdapter` burns the token.
5460
3. The `L2OpUSDCBridgeAdapter` sends the message to the appointed CrossDomainMessenger.
@@ -60,10 +66,103 @@ Similarly, for withdrawals:
6066
6167
## Migrating from Bridged USDC to Native USDC
6268

63-
![image](https://github.com/user-attachments/assets/291aae4c-e9fb-43a5-a11d-71bb3fc78311)
69+
![image](https://github.com/user-attachments/assets/f0b1c8de-658d-4198-9981-63f4bdda9ae3)
70+
71+
### Summary
72+
73+
Bridged USDC representation involves locking liquidity in the home chain and minting tokens on the destination chain. Migrating to native means transferring ownership of the bridged USDC to Circle and burning the locked funds on the home chain to consolidate liquidity across chains, making the bridged USDC canonical. ⚠️ This process is irreversible and will deprecate the adapters ⚠️.
74+
75+
### Step by step
76+
77+
1. Call `migrateToNative()` on L1
78+
- Params
79+
- `_roleCaller` The address that will be allowed to transfer the USDC roles on the destination chain.
80+
- `_burnCaller` The address that will be allowed to call this contract to burn the USDC tokens
81+
- `_minGasLimitReceiveOnL2` Minimum gas limit that the message for the`receiveMigrateToNative` call can be executed with on L2
82+
- `_minGasLimitSetBurnAmount` Minimum gas limit that the message can be executed with to set the burn amount (This param is set on L2, and it represents the `minGasLimit` for when the withdrawal is finalized on L1)
83+
- Effects
84+
- Sets the `burnCaller` variable
85+
- Changes the `messengerStatus` variable locking this function to avoid calling this process twice and locking `sendMessage`, `stopMessaging` and `resumeMessaging`.
86+
- Enables `setBurnAmount` that is only callable by the Linked Adapter.
87+
- Sends message to call `receiveMigrateToNative` on destination chain.
88+
- ⚠️ Note: Once this step is executed the bridges can’t be unpaused.
89+
2. Call `receiveMigrateToNative` on L2 (Automatically relayed)
90+
91+
- Params
92+
- `_roleCaller` The address that will be allowed to transfer the USDC roles on the destination chain.
93+
- `_setBurnAmountMinGasLimit` Minimum gas limit that the setBurnAmount message can be executed on L1
94+
- Effects
95+
- Changes the `messengerStatus` variable locking `receiveStopMessaging`, `receiveResumeMessaging`, and `sendMessage`. Modifying `receiveMessage` behavior to return pending messages to L1 that could arrive after the migration. Also, modifies `withdrawLockedFunds` behavior to send the locked funds to the spender through a message to L1.
96+
- Removes L2 Adapter as minter form USDC contract.
97+
- Calculates the amount of USDC that is going to be burned on origin.
98+
- Sends message to call `setBurnAmount` on origin chain.
99+
⚠️ Note: Messages sent from L2 to L1 are not automatically relayed, so this message needs to be manually treated as the [Optimism Docs](https://docs.optimism.io/app-developers/bridging/messaging#for-l2-to-l1-transactions) suggest, first submit the transaction proof on the portal and then wait 7 days to finalize the withdrawal.
100+
⚠️ Note: User friendly interface to submit the transaction proof: [Superchain Relayer](https://console.optimism.io/relayer)
101+
- Note: This function is not blocked to be triggered again from L1 if a withdrawal for `setBurnAmount` was not yet finalized.
102+
103+
***
104+
105+
After this point L1 (burn locked USDC) and L2 sequences (transfer bridged USDC roles) can be called in any order.
106+
107+
***
108+
109+
- L2 Sequence
110+
1. Call `transferUSDCRoles`
111+
- Params
112+
- `_owner` The address to transfer ownership to
113+
- Effects
114+
- Transfers the ownership of the Bridged USDC contract to the `_owner`
115+
- Transfer the admin rights of the Bridged USDC proxy to the `msg.sender` (a.k.a. `roleCaller`)
116+
- L1 Sequence (MUST wait at least 7 days to execute this sequence).
117+
1. Call `setBurnAmount`
118+
- Params
119+
- `_amount` The amount of USDC tokens that will be burned
120+
- Effects
121+
- Sets `burnAmount` variable that will be later used by `burnLockedUSDC`
122+
- Changes the `messengerStatus` to `Deprecated` disabling all the function related to migration and sending messages.
123+
- ⚠️ Note: After this point the `burnCaller` and the `roleCaller` are not longer updatable
124+
2. Call `burnLockedUSDC`
125+
- Effects
126+
- Burns the USDC locked in the adapter based on the `burnAmount` variable or the contract balance.
127+
- Reset `burnAmount` and `burnCaller` variables, to avoid calling the function more than once.
128+
- `receiveWithdrawLockedFundsPostMigration` is enabled, this function handles the messages that were in-flight during the migration and were sent back from L2 by transferring the locked USDC to the user.
129+
130+
### Contracts behavior after migration
131+
132+
The following functions will revert or won't be callable after migration:
133+
134+
- `L1OpUSDCBridgeAdapter`
135+
- `migrateToNative`
136+
- `setBurnAmount`
137+
- `burnLockedUSDC`
138+
- `stopMessaging`
139+
- `resumeMessaging`
140+
- `sendMessage`
141+
- `L2OpUSDCBridgeAdapter`
142+
- `receiveMigrateToNative`
143+
- `transferUSDCRoles`
144+
- `receiveStopMessaging`
145+
- `receiveResumeMessaging`
146+
- `sendMessage`
147+
- `callUsdcTransaction`
148+
149+
The following functions will be callable after migration:
150+
151+
- `L1OpUSDCBridgeAdapter`
152+
- `receiveMessage`
153+
- `receiveWithdrawLockedFundsPostMigration`
154+
- `withdrawLockedFunds`
155+
- `L2OpUSDCBridgeAdapter`
156+
Note: Since the adapter is deprecated these functions will handle the messages that were in-flight during the migration and will sent locked funds (if the address was blocked by Circle at the moment of the relaying the message and then unblocked) back to the spender through a message to L1.
157+
- `receiveMessage`
158+
![image](https://github.com/user-attachments/assets/4b489415-9dca-406e-bb87-38f9f04ac25a)
159+
160+
- `withdrawLockedFunds`
161+
![image](https://github.com/user-attachments/assets/cc0ca3fe-d608-419d-884b-76b8eec58fc3)
64162

65163

66164
## Security
165+
67166
The referenced implementation for the OP Stack has undergone audits from [Spearbit](https://spearbit.com/) and is recommended for production use. The audit report is available [here](./audits/spearbit.pdf).
68167

69168
## Setup
@@ -142,12 +241,13 @@ ETHEREUM_RPC=
142241
```
143242

144243
After all these variables are set, navigate to the `script/mainnet/Deploy.s.sol` file and edit the following lines with your desired configuration, we add a sanity check that will revert if you forget to change this value:
244+
145245
```solidity
146246
// NOTE: We have these hardcoded to default values, if used in product you will need to change them
147247
148248
bytes[] memory _usdcInitTxs = new bytes[](3);
149249
string memory _name = string.concat('Bridged USDC', ' ', '(', chainName, ')');
150-
250+
151251
_usdcInitTxs[0] = abi.encodeCall(IUSDC.initializeV2, (_name));
152252
_usdcInitTxs[1] = USDCInitTxs.INITIALIZEV2_1;
153253
_usdcInitTxs[2] = USDCInitTxs.INITIALIZEV2_2;
@@ -157,21 +257,25 @@ After all these variables are set, navigate to the `script/mainnet/Deploy.s.sol`
157257
```
158258

159259
Then run this command to test:
260+
160261
```bash
161262
yarn script:deploy
162263
```
163264

164265
And when you are ready to deploy to mainnet, run:
266+
165267
```bash
166268
yarn script:deploy:broadcast
167269
```
168270

169271
In addittion, the L1OpUSDCFactory deployment command is:
272+
170273
```bash
171274
yarn deploy:mainnet:factory
172275
```
173276

174277
And when you are ready to deploy to mainnet, run:
278+
175279
```bash
176280
yarn deploy:mainnet:factory:broadcast
177281
```
@@ -193,9 +297,11 @@ Alternatively, you can run the deployment scripts over your desired testent by r
193297
```
194298

195299
## Migrating to Native USDC
196-
> ⚠️ Migrating to native USDC is a manual process that requires communication with Circle, this section assumes both parties are ready to migrate to native USDC. Please review [Circle’s documentation](https://www.circle.com/blog/bridged-usdc-standard) to learn about the process around Circle obtaining ownership of the Bridged USDC Standard token contract.
300+
301+
> ⚠️ Migrating to native USDC is a manual process that requires communication with Circle, this section assumes both parties are ready to migrate to native USDC. Please review [Circle’s documentation](https://www.circle.com/blog/bridged-usdc-standard) to learn about the process around Circle obtaining ownership of the Bridged USDC Standard token contract.
197302

198303
In order to migrate to native USDC, you will need to fill out these variables in the `.env` file:
304+
199305
```python
200306
# The address of the L1 opUSDC bridge adapter
201307
L1_ADAPTER=
@@ -208,19 +314,21 @@ BURN_CALLER
208314
```
209315

210316
After all these variables are set, run this command to test:
317+
211318
```bash
212319
yarn script:migrate
213320
```
214321

215322
And when you are ready to migrate to native USDC, run:
323+
216324
```bash
217325
yarn script:migrate:broadcast
218326
```
219327

220328
### What will Circle need at migration?
221329

222330
#### Circle will need the metadata from the original deployment of the USDC implementation that was used
223-
331+
224332
To do this you will need to go back to the `stablecoin-evm` github repo that the implementation was deployed from in order to extract the raw metadata from the compiled files. The compiled files are usually found in the `out/` or `artifacts/` folders. To extract the raw metadata you can run a command like this:
225333

226334
```bash
@@ -234,6 +342,7 @@ You will need to do this for both the token contract and any external libraries
234342
The primary license for the boilerplate is MIT, see [`LICENSE`](https://github.com/defi-wonderland/opUSDC/blob/main/LICENSE)
235343

236344
## Bridged USDC Standard Factory Disclaimer
237-
This software is provided “as is,” without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose, and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages, or other liability, whether in an action of contract, tort, or otherwise, arising from, out of, or in connection with the software or the use or other dealings in the software.
238345

239-
Please review [Circle’s disclaimer](https://github.com/circlefin/stablecoin-evm/blob/master/doc/bridged_USDC_standard.md#for-more-information) for the limitations around Circle obtaining ownership of the Bridged USDC Standard token contract.
346+
This software is provided “as is,” without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose, and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages, or other liability, whether in an action of contract, tort, or otherwise, arising from, out of, or in connection with the software or the use or other dealings in the software.
347+
348+
Please review [Circle’s disclaimer](https://github.com/circlefin/stablecoin-evm/blob/master/doc/bridged_USDC_standard.md#for-more-information) for the limitations around Circle obtaining ownership of the Bridged USDC Standard token contract.

0 commit comments

Comments
 (0)