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
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 36 additions & 16 deletions src/contracts/L1OpUSDCBridgeAdapter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -78,25 +78,22 @@ 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.

*/
function setBurnAmount(uint256 _amount) external onlyUpgradeManager {
function setBurnAmount(uint256 _amount) external {
if (
messengerStatus[msg.sender] != Status.Upgrading
|| ICrossDomainMessenger(msg.sender).xDomainMessageSender() != LINKED_ADAPTER
) {
revert IOpUSDCBridgeAdapter_InvalidSender();
}

burnAmount = _amount;
messengerStatus[msg.sender] = Status.Deprecated;

emit BurnAmountSet(_amount);
}

/**
* @notice Sets the address of the Circle contract
* @param _circle The address of the Circle contract
* @dev Only callable by the UpgradeManager
*/
function setCircle(address _circle) external onlyUpgradeManager {
circle = _circle;

emit CircleSet(_circle);
}

/**
* @notice Resume messaging on the messenger
* @dev Only callable by the UpgradeManager
Expand Down Expand Up @@ -252,11 +249,34 @@ contract L1OpUSDCBridgeAdapter is OpUSDCBridgeAdapter, UUPSUpgradeable, IL1OpUSD

/**
* @notice Initiates the process to migrate the bridged USDC to native USDC
* @param _l1Messenger The address of the L1 messenger
* @param _messenger The address of the L1 messenger
* @param _circle The address to transfer ownerships to
* @param _minGasLimitReceiveOnL2 Minimum gas limit that the message can be executed with on L2
* @param _minGasLimitSetBurnAmount Minimum gas limit that the message can be executed with to set the burn amount
*/
function migrateToNative(address _l1Messenger, address _circle) external {
// 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 👍

uint32 _minGasLimitReceiveOnL2,
uint32 _minGasLimitSetBurnAmount
) external onlyUpgradeManager {
// Ensure messaging is enabled
// Leave this flow open to resend upgrading flow incase message fails on L2
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


circle = _circle;
messengerStatus[_messenger] = Status.Upgrading;

ICrossDomainMessenger(_messenger).sendMessage(
LINKED_ADAPTER,
abi.encodeWithSignature('receiveMigrateToNative(address,uint32)', _circle, _minGasLimitSetBurnAmount),
_minGasLimitReceiveOnL2
);

emit MigratingToNative(_messenger, _circle);
}

/**
Expand Down
21 changes: 21 additions & 0 deletions src/contracts/L2OpUSDCBridgeAdapter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,27 @@ contract L2OpUSDCBridgeAdapter is IL2OpUSDCBridgeAdapter, Initializable, OpUSDCB
emit MessagingResumed(MESSENGER);
}

/**
* @notice Initiates the process to migrate the bridged USDC to native USDC
* @dev 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 can be executed on L1
*/
function receiveMigrateToNative(address _newOwner, uint32 _setBurnAmountMinGasLimit) external checkSender {
// Transfer ownership of the USDC contract to the circle
IUSDC(USDC).transferOwnership(_newOwner);

uint256 _burnAmount = IUSDC(USDC).totalSupply();
hexshire marked this conversation as resolved.
Show resolved Hide resolved

ICrossDomainMessenger(MESSENGER).sendMessage(
LINKED_ADAPTER, abi.encodeWithSignature('setBurnAmount(uint256)', _burnAmount), _setBurnAmountMinGasLimit
);

isMessagingDisabled = true;

emit MigratingToNative(MESSENGER, _newOwner);
}

/**
* @notice Authorize the upgrade of the implementation of the contract
* @param _newImplementation The address of the new implementation
Expand Down
4 changes: 2 additions & 2 deletions src/contracts/L2OpUSDCFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ contract L2OpUSDCFactory is IL2OpUSDCFactory {
}

// 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++) {
Comment on lines 57 to +60
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

(bool _success,) = _adapterProxy.call(_l2AdapterInitTxs[i]);
if (!_success) {
revert IL2OpUSDCFactory_AdapterInitializationFailed();
Expand Down
12 changes: 10 additions & 2 deletions src/contracts/UpgradeManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,14 @@ contract UpgradeManager is Initializable, OwnableUpgradeable, UUPSUpgradeable, I
/**
* @notice Execute the migration of the L1 Adapter to the native chain
* @param _l1Messenger The address of the L1 messenger
* @param _minGasLimitReceiveOnL2 Minimum gas limit that the message can be executed with on L2
* @param _minGasLimitSetBurnAmount Minimum gas limit that the message can be executed with to set the burn amount
*/
function executeMigration(address _l1Messenger) external {
function executeMigration(
address _l1Messenger,
uint32 _minGasLimitReceiveOnL2,
uint32 _minGasLimitSetBurnAmount
) external {
Migration memory _migration = migrations[_l1Messenger];

// Check the migration is prepared, not executed and is being called by the executor
Expand All @@ -131,7 +137,9 @@ contract UpgradeManager is Initializable, OwnableUpgradeable, UUPSUpgradeable, I
if (msg.sender != _migration.executor) revert IUpgradeManager_NotExecutor();

// Migrate
IL1OpUSDCBridgeAdapter(L1_ADAPTER).migrateToNative(_l1Messenger, _migration.circle);
IL1OpUSDCBridgeAdapter(L1_ADAPTER).migrateToNative(
_l1Messenger, _migration.circle, _minGasLimitReceiveOnL2, _minGasLimitSetBurnAmount
);

migrations[_l1Messenger].executed = true;

Expand Down
21 changes: 12 additions & 9 deletions src/interfaces/IL1OpUSDCBridgeAdapter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ interface IL1OpUSDCBridgeAdapter {
* @param Uninitialized The messenger is Uninitialized
* @param Active The messenger is active
* @param Paused The messenger is paused
* @param Upgrading The messenger is upgrading
* @param Deprecated The messenger is deprecated
*/
enum Status {
Uninitialized,
Active,
Paused,
Upgrading,
Deprecated
}

Expand All @@ -39,12 +41,6 @@ interface IL1OpUSDCBridgeAdapter {
*/
event L2AdapterUpgradeSent(address _newImplementation, address _messenger, bytes _data, uint32 _minGasLimit);

/**
* @notice Emitted when circle is set
* @param _circle The address of the Circle contract
*/
event CircleSet(address _circle);

/**
* @notice Emitted when a new messenger is initialized
* @param _messenger The address of the messenger
Expand Down Expand Up @@ -78,7 +74,7 @@ interface IL1OpUSDCBridgeAdapter {
/**
* @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 owner
* @dev Only callable by a whitelisted messenger during its migration process
*/
function setBurnAmount(uint256 _amount) external;

Expand All @@ -102,10 +98,17 @@ interface IL1OpUSDCBridgeAdapter {

/**
* @notice Initiates the process to migrate the bridged USDC to native USDC
* @param _l1Messenger The address of the L1 messenger
* @param _messenger The address of the L1 messenger
* @param _circle The address to transfer ownerships to
* @param _minGasLimitReceiveOnL2 Minimum gas limit that the message can be executed with on L2
* @param _minGasLimitSetBurnAmount Minimum gas limit that the message can be executed with to set the burn amount
*/
function migrateToNative(address _l1Messenger, address _circle) external;
function migrateToNative(
address _messenger,
address _circle,
uint32 _minGasLimitReceiveOnL2,
uint32 _minGasLimitSetBurnAmount
) external;

/**
* @notice Send the message to the linked adapter to mint the bridged representation on the linked chain
Expand Down
12 changes: 12 additions & 0 deletions src/interfaces/IOpUSDCBridgeAdapter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@ interface IOpUSDCBridgeAdapter {
*/
event MessagingResumed(address _messenger);

/**
* @notice Emitted when the adapter is migrating usdc to native
* @param _messenger The address of the messenger contract that is doing the migration
* @param _newOwner The address of the new owner of bridged usdc
*/
event MigratingToNative(address _messenger, address _newOwner);

/*///////////////////////////////////////////////////////////////
ERRORS
//////////////////////////////////////////////////////////////*/
Expand All @@ -60,6 +67,11 @@ interface IOpUSDCBridgeAdapter {
*/
error IOpUSDCBridgeAdapter_MessageExpired();

/**
* @notice Error when a migration is in progress
*/
error IOpUSDCBridgeAdapter_MigrationInProgress();

/*///////////////////////////////////////////////////////////////
LOGIC
//////////////////////////////////////////////////////////////*/
Expand Down
10 changes: 8 additions & 2 deletions src/interfaces/IUpgradeManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,14 @@ interface IUpgradeManager {
/**
* @notice Execute the migration of the L1 Adapter to the native chain
* @param _l1Messenger The address of the L1 messenger
*/
function executeMigration(address _l1Messenger) external;
* @param _minGasLimitReceiveOnL2 Minimum gas limit that the message can be executed with on L2
* @param _minGasLimitSetBurnAmount Minimum gas limit that the message can be executed with to set the burn amount
*/
function executeMigration(
address _l1Messenger,
uint32 _minGasLimitReceiveOnL2,
uint32 _minGasLimitSetBurnAmount
) external;

/**
* @notice Stop messaging on the messenger
Expand Down
6 changes: 6 additions & 0 deletions src/interfaces/external/IUSDC.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,10 @@ interface IUSDC is IERC20 {
* @param _amount Amount of tokens to burn
*/
function burn(address _account, uint256 _amount) external;

/**
* @notice Transfers USDC ownership to another address
* @param newOwner Address to transfer ownership to
*/
function transferOwnership(address newOwner) external;
}
Loading
Loading