Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: migrating usdc to native flow #24

Merged
merged 6 commits into from
May 28, 2024
Merged

Conversation

excaliborr
Copy link
Contributor

@excaliborr excaliborr commented May 27, 2024

🤖 Linear

Closes OPT-73

Copy link

linear bot commented May 27, 2024

OPT-73 USDC Native Migration Flow

L1 Adapter:

  • receiveSetBurnAmount(uint256 _amount*) external;: Will verify that the calling adapter is the adapter from L2* . Will set the burn amount for that specific adapter, should also set messages as deprecated, this will mean there is no way to restart the adapters. This is the last call in the migration flow so we deprecate here
  • migrateToNative: Will send a transfer ownership call to the L2 adapter for the bridged token, must be called by the UpgradeManager , will set a circle address who will be the only one allowed to call burnLockedUSDC. Will also stop new bridge messages from being sent from this adapter.
  • function burnLockedUSDC() external; must exist in the interface for circle to be able to upgrade the OpUSDC contract of the chain it lives on to native USDC should they want to, this function must do the following:
    1. Be only callable by an address that Circle specifies closer to the time of the upgrade.
    2. Burn the amount of USDC held by the bridge that corresponds precisely to the circulating total supply of bridged USDC established by the supply lock.
    3. Cannot use a parameter to pass in the amount, we will use a storage variable
    4. Concurrent upgrades cannot happen, circle will be reset to address(0) after this is called

L2 Adapter:

  • receiveMigrateToNative : Will receive the transfer ownership call from L1, must be called by the l1Adapter and sent from the messenger , transfers ownership of the Bridged USDC on this chain to newOwner. Will also stop new messages from being sent from this adapter. Should set messaging as deprecated

@excaliborr excaliborr marked this pull request as ready for review May 28, 2024 14:50
// TODO: Implement this in future PR
function migrateToNative(
address _messenger,
address _circle,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing a check over _circle != address(0) that could break the logic

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But maybe this check would fit better inside the prepareNativeMigration function

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a check for this

if (_migration.circle == address(0) || _migration.executor == address(0)) {

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True 👍

Comment on lines 146 to 148
* @dev This only starts the process, full migration cant finish until L1 receives the message for setting the burn amount
* @param _newOwner The address to transfer ownerships to
* @param _setBurnAmountMinGasLimit Minimum gas limit that the setBurnAmount message we are sending can be executed on L1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: linter warning

if (circle != address(0)) revert IOpUSDCBridgeAdapter_MigrationInProgress();

circle = _circle;
messengerStatus[_messenger] = Status.Deprecated;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it worth to create a transitioned state for the 'in upgrade' state?
Because, what happens if the function args are bad and it fails on L2, or even the prepraed migration is wrong?
I think we should allow to re-send the native message while it's paused on L1.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea i like this we can set it as Upgrading, and deptrcate it when we receive the setBurnAmount

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exactly

);

emit MigratingToNative(_messenger, _circle);
emit CircleSet(_circle);
Copy link
Member

@hexshire hexshire May 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this event needed if it only used in this function and also present in the event above?

src/contracts/L2OpUSDCBridgeAdapter.sol Show resolved Hide resolved
@@ -78,25 +78,21 @@ contract L1OpUSDCBridgeAdapter is OpUSDCBridgeAdapter, UUPSUpgradeable, IL1OpUSD
/**
* @notice Sets the amount of USDC tokens that will be burned when the burnLockedUSDC function is called
* @param _amount The amount of USDC tokens that will be burned
* @dev Only callable by the UpgradeManager
* @dev Only callable by a whitelisted messenger during its migration process
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change is not applied on the interface.

Comment on lines 57 to +60
// Execute the L2 Adapter initialization transactions
if (_l2AdapterInitTxs.length > 1) {
if (_l2AdapterInitTxs.length > 0) {
// Initialize L2 adapter
for (uint256 i = 1; i < _l2AdapterInitTxs.length; i++) {
for (uint256 i; i < _l2AdapterInitTxs.length; i++) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It started from 1 because the item 0 of the array is already used on the initialize tx done when l2 adapter proxy is created

@@ -71,9 +70,9 @@ contract L1OpUSDCBridgeAdapter_Unit_Constructor is Base {

contract L1OpUSDCBridgeAdapter_Unit_SetBurnAmount is Base {
/**
* @notice Check that the function reverts if the sender is not in a deprecated state
* @notice Check that the function reverts if the sender is not in a upgrading state
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* @notice Check that the function reverts if the sender is not in a upgrading state
* @notice Check that the function reverts if the messenger is not in an upgrading state

@@ -99,7 +98,7 @@ contract L1OpUSDCBridgeAdapter_Unit_SetBurnAmount is Base {
* @notice Check that the burn amount is set as expected
*/
function test_setAmount(uint256 _burnAmount) external {
adapter.forTest_setMessagerStatus(_messenger, IL1OpUSDCBridgeAdapter.Status.Deprecated);
adapter.forTest_setMessagerStatus(_messenger, IL1OpUSDCBridgeAdapter.Status.Upgrading);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be nice to add the exact same test, but setting Active as status so we also cover the first part of the conditional

Copy link
Contributor Author

@excaliborr excaliborr May 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is the burn amount which can only be called when its upgrading, do you mean the other scenario? I believe we have both branches covered

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah true, I confused 🙏

if (messengerStatus[_messenger] != Status.Active && messengerStatus[_messenger] != Status.Upgrading) {
revert IOpUSDCBridgeAdapter_MessagingDisabled();
}
if (circle != address(0)) revert IOpUSDCBridgeAdapter_MigrationInProgress();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to remove this check right? Otherwise if it's in Upgrading state it will revert here

Copy link
Contributor

@0xDiscotech 0xDiscotech left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fantastic job ser! 🚀

Copy link
Member

@hexshire hexshire left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Outstanding as always!

@excaliborr excaliborr merged commit 861e489 into dev May 28, 2024
4 checks passed
@excaliborr excaliborr deleted the feat/migrating-to-native branch May 28, 2024 23:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants