Skip to content

Commit

Permalink
Merge branch 'audit/spearbit' into feat/symb-prop19
Browse files Browse the repository at this point in the history
  • Loading branch information
simon-something committed Aug 2, 2024
2 parents 0717f1d + d2d9d5c commit b6ec887
Show file tree
Hide file tree
Showing 14 changed files with 168 additions and 57 deletions.
7 changes: 7 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ L1_FACTORY_MAINNET=
L1_ADAPTER_OP=
L2_ADAPTER_OP=

# Custom Chain
BRIDGED_USDC_IMPLEMENTATION=
L1_MESSENGER=
CHAIN_NAME=
L1_ADAPTER=
ROLE_CALLER=
BURN_CALLER=


# Optimism
Expand Down
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
"lint:sol-logic": "solhint -c .solhint.json 'src/**/*.sol' 'script/**/*.sol'",
"lint:sol-tests": "solhint -c .solhint.tests.json 'test/**/*.sol'",
"prepare": "husky install",
"script:deploy": "forge script script/mainnet/deploy/Deploy.s.sol --slow --via-ir",
"script:deploy:broadcast": "forge script script/mainnet/deploy/Deploy.s.sol --broadcast --verify --slow --via-ir",
"script:migrate": "forge script script/mainnet/migration/MigrateToNative.s.sol --slow --via-ir",
"script:migrate:broadcast": "forge script script/mainnet/migration/MigrateToNative.s.sol --broadcast --verify --slow --via-ir",
"test": "forge test -vvv",
"test:fuzz": "echidna test/invariants/fuzz/OpUSDC.t.sol --config test/invariants/fuzz/config.yaml --contract OpUsdcTest",
"test:integration": "forge test --match-contract Integration -vvv",
Expand Down
44 changes: 44 additions & 0 deletions script/mainnet/deploy/Deploy.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;

import {Script} from 'forge-std/Script.sol';
import {console} from 'forge-std/Test.sol';
import {IL1OpUSDCFactory} from 'interfaces/IL1OpUSDCFactory.sol';
import {USDCInitTxs} from 'src/contracts/utils/USDCInitTxs.sol';

contract Deploy is Script {
uint32 public constant MIN_GAS_LIMIT_DEPLOY = 9_000_000;
IL1OpUSDCFactory public immutable L1_FACTORY = IL1OpUSDCFactory(vm.envAddress('L1_FACTORY_MAINNET'));
address public immutable BRIDGED_USDC_IMPLEMENTATION = vm.envAddress('BRIDGED_USDC_IMPLEMENTATION');
address public immutable L1_MESSENGER = vm.envAddress('L1_MESSENGER');
string public chainName = vm.envString('CHAIN_NAME');
address public owner = vm.rememberKey(vm.envUint('MAINNET_PK'));

function run() public {
vm.createSelectFork(vm.rpcUrl(vm.envString('MAINNET_RPC')));
vm.startBroadcast(owner);

// NOTE: We have these hardcoded to default values, if used in product you will need to change them
bytes[] memory _usdcInitTxs = new bytes[](3);
_usdcInitTxs[0] = USDCInitTxs.INITIALIZEV2;
_usdcInitTxs[1] = USDCInitTxs.INITIALIZEV2_1;
_usdcInitTxs[2] = USDCInitTxs.INITIALIZEV2_2;

IL1OpUSDCFactory.L2Deployments memory _l2Deployments = IL1OpUSDCFactory.L2Deployments({
l2AdapterOwner: owner,
usdcImplAddr: BRIDGED_USDC_IMPLEMENTATION,
usdcInitTxs: _usdcInitTxs,
minGasLimitDeploy: MIN_GAS_LIMIT_DEPLOY
});

// Deploy the L2 contracts
(address _l1Adapter, address _l2Factory, address _l2Adapter) =
L1_FACTORY.deploy(L1_MESSENGER, owner, chainName, _l2Deployments);
vm.stopBroadcast();

/// NOTE: Hardcode the `L1_ADAPTER_BASE` and `L2_ADAPTER_BASE` addresses inside the `.env` file
console.log('L1 Adapter:', _l1Adapter);
console.log('L2 Factory:', _l2Factory);
console.log('L2 Adapter:', _l2Adapter);
}
}
22 changes: 22 additions & 0 deletions script/mainnet/migration/MigrateToNative.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;

import {Script} from 'forge-std/Script.sol';
import {IL1OpUSDCBridgeAdapter} from 'interfaces/IL1OpUSDCBridgeAdapter.sol';

contract MigrateToNative is Script {
uint32 public constant MIN_GAS_LIMIT_RECEIVE_L2 = 100_000;
uint32 public constant MIN_GAS_LIMIT_SET_BURN_AMOUNT_L2 = 100_000;
IL1OpUSDCBridgeAdapter public immutable L1_ADAPTER = IL1OpUSDCBridgeAdapter(vm.envAddress('L1_ADAPTER'));

address public owner = vm.rememberKey(vm.envUint('MAINNET_OWNER_PK'));
address public roleCaller = vm.envAddress('ROLE_CALLER');
address public burnCaller = vm.envAddress('BURN_CALLER');

function run() public {
vm.createSelectFork(vm.rpcUrl(vm.envString('MAINNET_RPC')));
vm.startBroadcast(owner);
L1_ADAPTER.migrateToNative(roleCaller, burnCaller, MIN_GAS_LIMIT_RECEIVE_L2, MIN_GAS_LIMIT_SET_BURN_AMOUNT_L2);
vm.stopBroadcast();
}
}
18 changes: 9 additions & 9 deletions src/contracts/L1OpUSDCBridgeAdapter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ contract L1OpUSDCBridgeAdapter is IL1OpUSDCBridgeAdapter, OpUSDCBridgeAdapter {
uint32 _minGasLimitReceiveOnL2,
uint32 _minGasLimitSetBurnAmount
) external onlyOwner {
// Leave this flow open to resend upgrading flow incase message fails on L2
// Leave this flow open to resend upgrading flow in case message fails on L2
// Circle's USDC implementation of `transferOwnership` reverts on address(0)
if (_roleCaller == address(0) || _burnCaller == address(0)) revert IOpUSDCBridgeAdapter_InvalidAddress();

Expand Down Expand Up @@ -118,7 +118,7 @@ contract L1OpUSDCBridgeAdapter is IL1OpUSDCBridgeAdapter, OpUSDCBridgeAdapter {

// NOTE: This is a very edge case and will only happen if the chain operator adds a second minter on L2
// So now this adapter doesnt have the full backing supply locked in this contract
// Incase the bridged usdc token has other minters and the supply sent is greater then what we have
// in case the bridged usdc token has other minters and the supply sent is greater then what we have
// We need to burn the full amount stored in this contract
// This could also cause in-flight messages to fail because of the multiple supply sources
uint256 _burnAmount = burnAmount;
Expand Down Expand Up @@ -147,7 +147,7 @@ contract L1OpUSDCBridgeAdapter is IL1OpUSDCBridgeAdapter, OpUSDCBridgeAdapter {
*/
function stopMessaging(uint32 _minGasLimit) external onlyOwner {
// Ensure messaging is enabled
// If its paused we still leave this function open to be called incase the message fails on L2
// If its paused we still leave this function open to be called in case the message fails on L2
if (messengerStatus != Status.Active && messengerStatus != Status.Paused) {
revert IOpUSDCBridgeAdapter_MessagingDisabled();
}
Expand All @@ -164,12 +164,12 @@ contract L1OpUSDCBridgeAdapter is IL1OpUSDCBridgeAdapter, OpUSDCBridgeAdapter {
/**
* @notice Resume messaging on the messenger
* @dev Only callable by the owner
* @dev Cant resume deprecated or upgrading messengers
* @dev Can't resume deprecated or upgrading messengers
* @param _minGasLimit Minimum gas limit that the message can be executed with
*/
function resumeMessaging(uint32 _minGasLimit) external onlyOwner {
// Ensure messaging is disabled
// If its active we still leave this function open to be called incase the message fails on L2
// If its active we still leave this function open to be called in case the message fails on L2
if (messengerStatus != Status.Paused && messengerStatus != Status.Active) {
revert IOpUSDCBridgeAdapter_MessagingEnabled();
}
Expand All @@ -188,7 +188,7 @@ contract L1OpUSDCBridgeAdapter is IL1OpUSDCBridgeAdapter, OpUSDCBridgeAdapter {
///////////////////////////////////////////////////////////////*/

/**
* @notice Send tokens to other chain through the linked adapter
* @notice Send tokens to another chain through the linked adapter
* @param _to The target address on the destination chain
* @param _amount The amount of tokens to send
* @param _minGasLimit Minimum gas limit that the message can be executed with
Expand All @@ -206,7 +206,7 @@ contract L1OpUSDCBridgeAdapter is IL1OpUSDCBridgeAdapter, OpUSDCBridgeAdapter {
}

/**
* @notice Send signer tokens to other chain through the linked adapter
* @notice Send signer tokens to another chain through the linked adapter
* @param _signer The address of the user sending the message
* @param _to The target address on the destination chain
* @param _amount The amount of tokens to send
Expand Down Expand Up @@ -270,7 +270,7 @@ contract L1OpUSDCBridgeAdapter is IL1OpUSDCBridgeAdapter, OpUSDCBridgeAdapter {
/**
* @notice Receives a message from L2 if the adapter is deprecated and a user is withdrawing blacklisted funds
* @dev If the _spender is still blacklisted, the user will be forced to replay this message
* @param _spender The user that initialy provided the tokens
* @param _spender The user that initially provided the tokens
* @param _amount The amount of tokens to withdraw
*/
function receiveWithdrawBlacklistedFundsPostMigration(address _spender, uint256 _amount) external onlyLinkedAdapter {
Expand All @@ -283,7 +283,7 @@ contract L1OpUSDCBridgeAdapter is IL1OpUSDCBridgeAdapter, OpUSDCBridgeAdapter {
}

/**
* @notice Withdraws the blacklisted funds from the contract incase they get unblacklisted
* @notice Withdraws the blacklisted funds from the contract in case they get unblacklisted
* @param _spender The address that provided the tokens
* @param _user The user to withdraw the funds for
*/
Expand Down
2 changes: 1 addition & 1 deletion src/contracts/L1OpUSDCFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ contract L1OpUSDCFactory is IL1OpUSDCFactory {
L2Deployments calldata _l2Deployments
) external returns (address _l1Adapter, address _l2Factory, address _l2Adapter) {
// Checks that the first init tx selector is not equal to the `initialize()` function since we manually
// construct this function on the L2 factory contract
// Construct this function on the L2 factory contract
if (bytes4(_l2Deployments.usdcInitTxs[0]) == _INITIALIZE_SELECTOR) revert IL1OpUSDCFactory_NoInitializeTx();

// Update the salt counter so the L2 factory is deployed with a different salt to a different address and get it
Expand Down
12 changes: 7 additions & 5 deletions src/contracts/L2OpUSDCBridgeAdapter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ contract L2OpUSDCBridgeAdapter is IL2OpUSDCBridgeAdapter, OpUSDCBridgeAdapter {

/**
* @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
* @dev Full migration can't finish until L1 receives the message for setting the burn amount
* @param _roleCaller The address that will be allowed to transfer the USDC roles
* @param _setBurnAmountMinGasLimit Minimum gas limit that the setBurnAmount message can be executed on L1
*/
Expand Down Expand Up @@ -142,7 +142,7 @@ contract L2OpUSDCBridgeAdapter is IL2OpUSDCBridgeAdapter, OpUSDCBridgeAdapter {
///////////////////////////////////////////////////////////////*/

/**
* @notice Send tokens to other chain through the linked adapter
* @notice Send tokens to another chain through the linked adapter
* @param _to The target address on the destination chain
* @param _amount The amount of tokens to send
* @param _minGasLimit Minimum gas limit that the message can be executed with
Expand All @@ -159,7 +159,7 @@ contract L2OpUSDCBridgeAdapter is IL2OpUSDCBridgeAdapter, OpUSDCBridgeAdapter {
}

/**
* @notice Send signer tokens to other chain through the linked adapter
* @notice Send signer tokens to another chain through the linked adapter
* @param _signer The address of the user sending the message
* @param _to The target address on the destination chain
* @param _amount The amount of tokens to send
Expand Down Expand Up @@ -212,10 +212,12 @@ contract L2OpUSDCBridgeAdapter is IL2OpUSDCBridgeAdapter, OpUSDCBridgeAdapter {
function receiveMessage(address _user, address _spender, uint256 _amount) external override onlyLinkedAdapter {
if (messengerStatus == Status.Deprecated) {
uint32 _minGasLimit = 150_000;
// Return the funds to the spender incase the target on L2 is a contract that can´t handle the funds on L1
// Return the funds to the spender in case the target on L2 is a contract that can´t handle the funds on L1
ICrossDomainMessenger(MESSENGER).sendMessage(
LINKED_ADAPTER, abi.encodeCall(IOpUSDCBridgeAdapter.receiveMessage, (_spender, _spender, _amount)), _minGasLimit
);

emit ReplayedFundsSentBackToL1(_spender, _amount);
} else {
// Mint the tokens to the user
try IUSDC(USDC).mint(_user, _amount) {
Expand All @@ -228,7 +230,7 @@ contract L2OpUSDCBridgeAdapter is IL2OpUSDCBridgeAdapter, OpUSDCBridgeAdapter {
}

/**
* @notice Mints the blacklisted funds from the contract incase they get unblacklisted
* @notice Mints the blacklisted funds from the contract in case they get unblacklisted
* @dev Returns the funds to the spender through a message to L1 if the contract is deprecated
* @param _spender The address that provided the tokens
* @param _user The user to withdraw the funds for
Expand Down
4 changes: 2 additions & 2 deletions src/contracts/universal/OpUSDCBridgeAdapter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,15 @@ abstract contract OpUSDCBridgeAdapter is UUPSUpgradeable, OwnableUpgradeable, EI
///////////////////////////////////////////////////////////////*/

/**
* @notice Send tokens to other chain through the linked adapter
* @notice Send tokens to another chain through the linked adapter
* @param _to The target address on the destination chain
* @param _amount The amount of tokens to send
* @param _minGasLimit Minimum gas limit that the message can be executed with
*/
function sendMessage(address _to, uint256 _amount, uint32 _minGasLimit) external virtual;

/**
* @notice Send signer tokens to other chain through the linked adapter
* @notice Send signer tokens to another chain through the linked adapter
* @param _signer The address of the user sending the message
* @param _to The target address on the destination chain
* @param _amount The amount of tokens to send
Expand Down
4 changes: 2 additions & 2 deletions src/interfaces/IL1OpUSDCBridgeAdapter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,15 @@ interface IL1OpUSDCBridgeAdapter {
/**
* @notice Resume messaging on the messenger
* @dev Only callable by the owner
* @dev Cant resume deprecated messengers
* @dev Can't resume deprecated messengers
* @param _minGasLimit Minimum gas limit that the message can be executed with
*/
function resumeMessaging(uint32 _minGasLimit) external;

/**
* @notice Receives a message from L2 if the adapter is deprecated and a user is withdrawing blacklisted funds
* @dev If the _spender is still blacklisted, the user will be forced to replay this message
* @param _spender The user that initialy provided the tokens
* @param _spender The user that initially provided the tokens
* @param _amount The amount of tokens to withdraw
*/
function receiveWithdrawBlacklistedFundsPostMigration(address _spender, uint256 _amount) external;
Expand Down
20 changes: 17 additions & 3 deletions src/interfaces/IL2OpUSDCBridgeAdapter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,35 @@ interface IL2OpUSDCBridgeAdapter {
*/
event USDCFunctionSent(bytes4 _functionSignature);

/**
* @notice Emitted when a `receiveMessage` call message is replayed after the adapter was deprecated
* @param _spender The address that provided the tokens
* @param _amount The amount of USDC sent back to L1
*/
event ReplayedFundsSentBackToL1(address _spender, uint256 _amount);

/**
* @notice Emitted when the blacklisted funds are sent back to L1
* @param _spender The address that provided the tokens
* @param _amountSent The amount of tokens that were withdrawn
*/
event BlacklistedFundsSentBackToL1(address indexed _spender, uint256 _amountSent);

/*///////////////////////////////////////////////////////////////
LOGIC
///////////////////////////////////////////////////////////////*/

/**
* @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
* @dev Full migration can't finish until L1 receives the message for setting the burn amount
* @param _roleCaller The address that will be allowed to transfer the USDC roles
* @param _setBurnAmountMinGasLimit Minimum gas limit that the setBurnAmount message can be executed on L1
*/
function receiveMigrateToNative(address _roleCaller, uint32 _setBurnAmountMinGasLimit) external;

/**
* @notice Transfer the USDC roles to the new owner
* @param _owner The address to transfer ownerships to
* @param _owner The address to transfer ownership to
* @dev Can only be called by the role caller set in the migration process
*/
function transferUSDCRoles(address _owner) external;
Expand All @@ -44,7 +58,7 @@ interface IL2OpUSDCBridgeAdapter {
function receiveResumeMessaging() external;

/**
* @notice Call with abitrary calldata on USDC contract.
* @notice Call with arbitrary calldata on USDC contract.
* @dev can't execute the following list of transactions:
* • transferOwnership (0xf2fde38b)
* • changeAdmin (0x8f283970)
Expand Down
29 changes: 12 additions & 17 deletions src/interfaces/IOpUSDCBridgeAdapter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -58,16 +58,18 @@ interface IOpUSDCBridgeAdapter {
* @param _messenger The address of the messenger contract that was sent through
* @param _minGasLimit Minimum gas limit that the message can be executed with
*/
event MessageSent(address _user, address _to, uint256 _amount, address _messenger, uint32 _minGasLimit);
event MessageSent(
address indexed _user, address indexed _to, uint256 _amount, address indexed _messenger, uint32 _minGasLimit
);

/**
* @notice Emitted when a message as recieved
* @notice Emitted when a message as received
* @param _spender The address that provided the tokens
* @param _user The user that recieved the message
* @param _amount The amount of tokens recieved
* @param _messenger The address of the messenger contract that was recieved through
* @param _user The user that received the message
* @param _amount The amount of tokens received
* @param _messenger The address of the messenger contract that was received through
*/
event MessageReceived(address _spender, address _user, uint256 _amount, address _messenger);
event MessageReceived(address indexed _spender, address indexed _user, uint256 _amount, address indexed _messenger);

/**
* @notice Emitted when messaging is resumed
Expand All @@ -91,21 +93,14 @@ interface IOpUSDCBridgeAdapter {
* @param _amount The amount of tokens that were added to the blacklisted funds
* @param _messenger The address of the messenger that the message failed for
*/
event MessageFailed(address _spender, address _user, uint256 _amount, address _messenger);
event MessageFailed(address indexed _spender, address indexed _user, uint256 _amount, address indexed _messenger);

/**
* @notice Emitted when the blacklisted funds are withdrawn
* @param _user The user that the funds were withdrawn for
* @param _amountWithdrawn The amount of tokens that were withdrawn
*/
event BlacklistedFundsWithdrawn(address _user, uint256 _amountWithdrawn);

/**
* @notice Emitted when the blacklisted funds are sent back to L1
* @param _spender The address that provided the tokens
* @param _amountSent The amount of tokens that were withdrawn
*/
event BlacklistedFundsSentBackToL1(address _spender, uint256 _amountSent);
event BlacklistedFundsWithdrawn(address indexed _user, uint256 _amountWithdrawn);

/*///////////////////////////////////////////////////////////////
ERRORS
Expand Down Expand Up @@ -194,15 +189,15 @@ interface IOpUSDCBridgeAdapter {
function initialize(address _owner) external;

/**
* @notice Send tokens to other chain through the linked adapter
* @notice Send tokens to another chain through the linked adapter
* @param _to The target address on the destination chain
* @param _amount The amount of tokens to send
* @param _minGasLimit Minimum gas limit that the message can be executed with
*/
function sendMessage(address _to, uint256 _amount, uint32 _minGasLimit) external;

/**
* @notice Send signer tokens to other chain through the linked adapter
* @notice Send signer tokens to another chain through the linked adapter
* @param _signer The address of the user sending the message
* @param _to The target address on the destination chain
* @param _amount The amount of tokens to send
Expand Down
Loading

0 comments on commit b6ec887

Please sign in to comment.