diff --git a/packages/contracts-bedrock/src/L1/L1StandardBridge.sol b/packages/contracts-bedrock/src/L1/L1StandardBridge.sol index 757c140c56e..21c75f04fd9 100644 --- a/packages/contracts-bedrock/src/L1/L1StandardBridge.sol +++ b/packages/contracts-bedrock/src/L1/L1StandardBridge.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { Predeploys } from "src/libraries/Predeploys.sol"; +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { StandardBridge } from "src/universal/StandardBridge.sol"; import { ISemver } from "src/universal/ISemver.sol"; import { CrossDomainMessenger } from "src/universal/CrossDomainMessenger.sol"; @@ -20,22 +20,6 @@ import { SystemConfig } from "src/L1/SystemConfig.sol"; /// of some token types that may not be properly supported by this contract include, but are /// not limited to: tokens with transfer fees, rebasing tokens, and tokens with blocklists. contract L1StandardBridge is StandardBridge, ISemver { - /// @custom:legacy - /// @notice Emitted whenever a deposit of ETH from L1 into L2 is initiated. - /// @param from Address of the depositor. - /// @param to Address of the recipient on L2. - /// @param amount Amount of ETH deposited. - /// @param extraData Extra data attached to the deposit. - event ETHDepositInitiated(address indexed from, address indexed to, uint256 amount, bytes extraData); - - /// @custom:legacy - /// @notice Emitted whenever a withdrawal of ETH from L2 to L1 is finalized. - /// @param from Address of the withdrawer. - /// @param to Address of the recipient on L1. - /// @param amount Amount of ETH withdrawn. - /// @param extraData Extra data attached to the withdrawal. - event ETHWithdrawalFinalized(address indexed from, address indexed to, uint256 amount, bytes extraData); - /// @custom:legacy /// @notice Emitted whenever an ERC20 deposit is initiated. /// @param l1Token Address of the token on L1. @@ -81,21 +65,28 @@ contract L1StandardBridge is StandardBridge, ISemver { SystemConfig public systemConfig; /// @notice Constructs the L1StandardBridge contract. - constructor() StandardBridge() { + constructor(address _otherBridge, address _l1USDC, address _l2USDC) StandardBridge() { initialize({ _messenger: CrossDomainMessenger(address(0)), _superchainConfig: SuperchainConfig(address(0)), - _systemConfig: SystemConfig(address(0)) + _systemConfig: SystemConfig(address(0)), + _otherBridgeAddress: _otherBridge, + _l1USDC: _l1USDC, + _l2USDC: _l2USDC }); } /// @notice Initializer. /// @param _messenger Contract for the CrossDomainMessenger on this network. /// @param _superchainConfig Contract for the SuperchainConfig on this network. + /// @param _otherBridgeAddress Contract for the other StandardBridge contract. function initialize( CrossDomainMessenger _messenger, SuperchainConfig _superchainConfig, - SystemConfig _systemConfig + SystemConfig _systemConfig, + address _otherBridgeAddress, + address _l1USDC, + address _l2USDC ) public initializer @@ -104,7 +95,9 @@ contract L1StandardBridge is StandardBridge, ISemver { systemConfig = _systemConfig; __StandardBridge_init({ _messenger: _messenger, - _otherBridge: StandardBridge(payable(Predeploys.L2_STANDARD_BRIDGE)) + _otherBridge: StandardBridge(payable(_otherBridgeAddress)), + _l1USDC: _l1USDC, + _l2USDC: _l2USDC }); } @@ -113,39 +106,18 @@ contract L1StandardBridge is StandardBridge, ISemver { return superchainConfig.paused(); } - /// @notice Allows EOAs to bridge ETH by sending directly to the bridge. - receive() external payable override onlyEOA { - _initiateETHDeposit(msg.sender, msg.sender, RECEIVE_DEFAULT_GAS_LIMIT, bytes("")); - } - /// @inheritdoc StandardBridge function gasPayingToken() internal view override returns (address addr_, uint8 decimals_) { (addr_, decimals_) = systemConfig.gasPayingToken(); } - /// @custom:legacy - /// @notice Deposits some amount of ETH into the sender's account on L2. - /// @param _minGasLimit Minimum gas limit for the deposit message on L2. - /// @param _extraData Optional data to forward to L2. - /// Data supplied here will not be used to execute any code on L2 and is - /// only emitted as extra data for the convenience of off-chain tooling. - function depositETH(uint32 _minGasLimit, bytes calldata _extraData) external payable onlyEOA { - _initiateETHDeposit(msg.sender, msg.sender, _minGasLimit, _extraData); - } - - /// @custom:legacy - /// @notice Deposits some amount of ETH into a target account on L2. - /// Note that if ETH is sent to a contract on L2 and the call fails, then that ETH will - /// be locked in the L2StandardBridge. ETH may be recoverable if the call can be - /// successfully replayed by increasing the amount of gas supplied to the call. If the - /// call will fail for any amount of gas, then the ETH will be locked permanently. - /// @param _to Address of the recipient on L2. - /// @param _minGasLimit Minimum gas limit for the deposit message on L2. - /// @param _extraData Optional data to forward to L2. - /// Data supplied here will not be used to execute any code on L2 and is - /// only emitted as extra data for the convenience of off-chain tooling. - function depositETHTo(address _to, uint32 _minGasLimit, bytes calldata _extraData) external payable { - _initiateETHDeposit(msg.sender, _to, _minGasLimit, _extraData); + /// @notice Burns all locked USDC if the pbridge is already paused + function burnAllLockedUSDC() external { + require(paused() == true, "Bridge should be paused before burning all locked USDC"); + require(msg.sender == superchainConfig.guardian(), "SuperchainConfig: only guardian can burn all USDC"); + // uint256 _balance = totalBridgedUSDC; + deposits[l1USDC][l2USDC] = 0; + // IERC20(l1USDC).burn(_balance); // check if this needs to be done } /// @custom:legacy @@ -166,7 +138,6 @@ contract L1StandardBridge is StandardBridge, ISemver { ) external virtual - onlyEOA { _initiateERC20Deposit(_l1Token, _l2Token, msg.sender, msg.sender, _amount, _minGasLimit, _extraData); } @@ -195,24 +166,6 @@ contract L1StandardBridge is StandardBridge, ISemver { _initiateERC20Deposit(_l1Token, _l2Token, msg.sender, _to, _amount, _minGasLimit, _extraData); } - /// @custom:legacy - /// @notice Finalizes a withdrawal of ETH from L2. - /// @param _from Address of the withdrawer on L2. - /// @param _to Address of the recipient on L1. - /// @param _amount Amount of ETH to withdraw. - /// @param _extraData Optional data forwarded from L2. - function finalizeETHWithdrawal( - address _from, - address _to, - uint256 _amount, - bytes calldata _extraData - ) - external - payable - { - finalizeBridgeETH(_from, _to, _amount, _extraData); - } - /// @custom:legacy /// @notice Finalizes a withdrawal of ERC20 tokens from L2. /// @param _l1Token Address of the token on L1. @@ -232,6 +185,8 @@ contract L1StandardBridge is StandardBridge, ISemver { external { finalizeBridgeERC20(_l1Token, _l2Token, _from, _to, _amount, _extraData); + // update total supply + // warnning check there is no reentrancy } /// @custom:legacy @@ -241,15 +196,6 @@ contract L1StandardBridge is StandardBridge, ISemver { return address(otherBridge); } - /// @notice Internal function for initiating an ETH deposit. - /// @param _from Address of the sender on L1. - /// @param _to Address of the recipient on L2. - /// @param _minGasLimit Minimum gas limit for the deposit message on L2. - /// @param _extraData Optional data to forward to L2. - function _initiateETHDeposit(address _from, address _to, uint32 _minGasLimit, bytes memory _extraData) internal { - _initiateBridgeETH(_from, _to, msg.value, _minGasLimit, _extraData); - } - /// @notice Internal function for initiating an ERC20 deposit. /// @param _l1Token Address of the L1 token being deposited. /// @param _l2Token Address of the corresponding token on L2. @@ -272,38 +218,6 @@ contract L1StandardBridge is StandardBridge, ISemver { _initiateBridgeERC20(_l1Token, _l2Token, _from, _to, _amount, _minGasLimit, _extraData); } - /// @inheritdoc StandardBridge - /// @notice Emits the legacy ETHDepositInitiated event followed by the ETHBridgeInitiated event. - /// This is necessary for backwards compatibility with the legacy bridge. - function _emitETHBridgeInitiated( - address _from, - address _to, - uint256 _amount, - bytes memory _extraData - ) - internal - override - { - emit ETHDepositInitiated(_from, _to, _amount, _extraData); - super._emitETHBridgeInitiated(_from, _to, _amount, _extraData); - } - - /// @inheritdoc StandardBridge - /// @notice Emits the legacy ERC20DepositInitiated event followed by the ERC20BridgeInitiated - /// event. This is necessary for backwards compatibility with the legacy bridge. - function _emitETHBridgeFinalized( - address _from, - address _to, - uint256 _amount, - bytes memory _extraData - ) - internal - override - { - emit ETHWithdrawalFinalized(_from, _to, _amount, _extraData); - super._emitETHBridgeFinalized(_from, _to, _amount, _extraData); - } - /// @inheritdoc StandardBridge /// @notice Emits the legacy ERC20WithdrawalFinalized event followed by the ERC20BridgeFinalized /// event. This is necessary for backwards compatibility with the legacy bridge. diff --git a/packages/contracts-bedrock/src/L2/L2StandardBridge.sol b/packages/contracts-bedrock/src/L2/L2StandardBridge.sol index 1472d0fd9e8..2d326f81aef 100644 --- a/packages/contracts-bedrock/src/L2/L2StandardBridge.sol +++ b/packages/contracts-bedrock/src/L2/L2StandardBridge.sol @@ -4,7 +4,6 @@ pragma solidity 0.8.15; import { Predeploys } from "src/libraries/Predeploys.sol"; import { StandardBridge } from "src/universal/StandardBridge.sol"; import { ISemver } from "src/universal/ISemver.sol"; -import { OptimismMintableERC20 } from "src/universal/OptimismMintableERC20.sol"; import { CrossDomainMessenger } from "src/universal/CrossDomainMessenger.sol"; import { L1Block } from "src/L2/L1Block.sol"; @@ -56,26 +55,21 @@ contract L2StandardBridge is StandardBridge, ISemver { string public constant version = "1.10.0"; /// @notice Constructs the L2StandardBridge contract. - constructor() StandardBridge() { - initialize({ _otherBridge: StandardBridge(payable(address(0))) }); + constructor(address _l1USDC, address _l2USDC) StandardBridge() { + initialize({ _otherBridge: StandardBridge(payable(address(0))), _l1USDC: _l1USDC, _l2USDC: _l2USDC }); } /// @notice Initializer. /// @param _otherBridge Contract for the corresponding bridge on the other chain. - function initialize(StandardBridge _otherBridge) public initializer { + function initialize(StandardBridge _otherBridge, address _l1USDC, address _l2USDC) public initializer { __StandardBridge_init({ _messenger: CrossDomainMessenger(Predeploys.L2_CROSS_DOMAIN_MESSENGER), - _otherBridge: _otherBridge + _otherBridge: _otherBridge, + _l1USDC: _l1USDC, + _l2USDC: _l2USDC }); } - /// @notice Allows EOAs to bridge ETH by sending directly to the bridge. - receive() external payable override onlyEOA { - _initiateWithdrawal( - Predeploys.LEGACY_ERC20_ETH, msg.sender, msg.sender, msg.value, RECEIVE_DEFAULT_GAS_LIMIT, bytes("") - ); - } - /// @inheritdoc StandardBridge function gasPayingToken() internal view override returns (address addr_, uint8 decimals_) { (addr_, decimals_) = L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).gasPayingToken(); @@ -83,8 +77,6 @@ contract L2StandardBridge is StandardBridge, ISemver { /// @custom:legacy /// @notice Initiates a withdrawal from L2 to L1. - /// This function only works with OptimismMintableERC20 tokens or ether. Use the - /// `bridgeERC20` function to bridge native L2 tokens to L1. /// Subject to be deprecated in the future. /// @param _l2Token Address of the L2 token to withdraw. /// @param _amount Amount of the L2 token to withdraw. @@ -107,12 +99,6 @@ contract L2StandardBridge is StandardBridge, ISemver { /// @custom:legacy /// @notice Initiates a withdrawal from L2 to L1 to a target account on L1. - /// Note that if ETH is sent to a contract on L1 and the call fails, then that ETH will - /// be locked in the L1StandardBridge. ETH may be recoverable if the call can be - /// successfully replayed by increasing the amount of gas supplied to the call. If the - /// call will fail for any amount of gas, then the ETH will be locked permanently. - /// This function only works with OptimismMintableERC20 tokens or ether. Use the - /// `bridgeERC20To` function to bridge native L2 tokens to L1. /// Subject to be deprecated in the future. /// @param _l2Token Address of the L2 token to withdraw. /// @param _to Recipient account on L1. @@ -159,44 +145,8 @@ contract L2StandardBridge is StandardBridge, ISemver { ) internal { - if (_l2Token == Predeploys.LEGACY_ERC20_ETH) { - _initiateBridgeETH(_from, _to, _amount, _minGasLimit, _extraData); - } else { - address l1Token = OptimismMintableERC20(_l2Token).l1Token(); - _initiateBridgeERC20(_l2Token, l1Token, _from, _to, _amount, _minGasLimit, _extraData); - } - } - - /// @notice Emits the legacy WithdrawalInitiated event followed by the ETHBridgeInitiated event. - /// This is necessary for backwards compatibility with the legacy bridge. - /// @inheritdoc StandardBridge - function _emitETHBridgeInitiated( - address _from, - address _to, - uint256 _amount, - bytes memory _extraData - ) - internal - override - { - emit WithdrawalInitiated(address(0), Predeploys.LEGACY_ERC20_ETH, _from, _to, _amount, _extraData); - super._emitETHBridgeInitiated(_from, _to, _amount, _extraData); - } - - /// @notice Emits the legacy DepositFinalized event followed by the ETHBridgeFinalized event. - /// This is necessary for backwards compatibility with the legacy bridge. - /// @inheritdoc StandardBridge - function _emitETHBridgeFinalized( - address _from, - address _to, - uint256 _amount, - bytes memory _extraData - ) - internal - override - { - emit DepositFinalized(address(0), Predeploys.LEGACY_ERC20_ETH, _from, _to, _amount, _extraData); - super._emitETHBridgeFinalized(_from, _to, _amount, _extraData); + address l1Token = l1USDC; + _initiateBridgeERC20(_l2Token, l1Token, _from, _to, _amount, _minGasLimit, _extraData); } /// @notice Emits the legacy WithdrawalInitiated event followed by the ERC20BridgeInitiated diff --git a/packages/contracts-bedrock/src/universal/StandardBridge.sol b/packages/contracts-bedrock/src/universal/StandardBridge.sol index 140aba531e6..e7e93ce8af9 100644 --- a/packages/contracts-bedrock/src/universal/StandardBridge.sol +++ b/packages/contracts-bedrock/src/universal/StandardBridge.sol @@ -2,13 +2,10 @@ pragma solidity 0.8.15; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import { ERC165Checker } from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; import { Address } from "@openzeppelin/contracts/utils/Address.sol"; import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import { SafeCall } from "src/libraries/SafeCall.sol"; -import { IOptimismMintableERC20, ILegacyMintableERC20 } from "src/universal/IOptimismMintableERC20.sol"; import { CrossDomainMessenger } from "src/universal/CrossDomainMessenger.sol"; -import { OptimismMintableERC20 } from "src/universal/OptimismMintableERC20.sol"; import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; import { Constants } from "src/libraries/Constants.sol"; @@ -23,19 +20,16 @@ abstract contract StandardBridge is Initializable { /// @notice The L2 gas limit set when eth is depoisited using the receive() function. uint32 internal constant RECEIVE_DEFAULT_GAS_LIMIT = 200_000; - /// @custom:legacy - /// @custom:spacer messenger - /// @notice Spacer for backwards compatibility. - bytes30 private spacer_0_2_30; - - /// @custom:legacy - /// @custom:spacer l2TokenBridge - /// @notice Spacer for backwards compatibility. - address private spacer_1_0_20; - /// @notice Mapping that stores deposits for a given pair of local and remote tokens. mapping(address => mapping(address => uint256)) public deposits; + /// @notice The address of L1 USDC address. + // solhint-disable-next-line var-name-mixedcase + address public immutable l1USDC; + + /// @notice The address of L2 USDC address. + address public immutable l2USDC; + /// @notice Messenger contract on this domain. /// @custom:network-specific CrossDomainMessenger public messenger; @@ -49,20 +43,6 @@ abstract contract StandardBridge is Initializable { /// would be a multiple of 50. uint256[45] private __gap; - /// @notice Emitted when an ETH bridge is initiated to the other chain. - /// @param from Address of the sender. - /// @param to Address of the receiver. - /// @param amount Amount of ETH sent. - /// @param extraData Extra data sent with the transaction. - event ETHBridgeInitiated(address indexed from, address indexed to, uint256 amount, bytes extraData); - - /// @notice Emitted when an ETH bridge is finalized on this chain. - /// @param from Address of the sender. - /// @param to Address of the receiver. - /// @param amount Amount of ETH sent. - /// @param extraData Extra data sent with the transaction. - event ETHBridgeFinalized(address indexed from, address indexed to, uint256 amount, bytes extraData); - /// @notice Emitted when an ERC20 bridge is initiated to the other chain. /// @param localToken Address of the ERC20 on this chain. /// @param remoteToken Address of the ERC20 on the remote chain. @@ -117,19 +97,19 @@ abstract contract StandardBridge is Initializable { /// @param _otherBridge Contract for the other StandardBridge contract. function __StandardBridge_init( CrossDomainMessenger _messenger, - StandardBridge _otherBridge + StandardBridge _otherBridge, + address _l1USDC, + address _l2USDC ) internal onlyInitializing { messenger = _messenger; otherBridge = _otherBridge; + l1USDC = _l1USDC; + l2USDC = _l2USDC; } - /// @notice Allows EOAs to bridge ETH by sending directly to the bridge. - /// Must be implemented by contracts that inherit. - receive() external payable virtual; - /// @notice Returns the address of the custom gas token and the token's decimals. function gasPayingToken() internal view virtual returns (address, uint8); @@ -163,31 +143,6 @@ abstract contract StandardBridge is Initializable { return false; } - /// @notice Sends ETH to the sender's address on the other chain. - /// @param _minGasLimit Minimum amount of gas that the bridge can be relayed with. - /// @param _extraData Extra data to be sent with the transaction. Note that the recipient will - /// not be triggered with this data, but it will be emitted and can be used - /// to identify the transaction. - function bridgeETH(uint32 _minGasLimit, bytes calldata _extraData) public payable onlyEOA { - _initiateBridgeETH(msg.sender, msg.sender, msg.value, _minGasLimit, _extraData); - } - - /// @notice Sends ETH to a receiver's address on the other chain. Note that if ETH is sent to a - /// smart contract and the call fails, the ETH will be temporarily locked in the - /// StandardBridge on the other chain until the call is replayed. If the call cannot be - /// replayed with any amount of gas (call always reverts), then the ETH will be - /// permanently locked in the StandardBridge on the other chain. ETH will also - /// be locked if the receiver is the other bridge, because finalizeBridgeETH will revert - /// in that case. - /// @param _to Address of the receiver. - /// @param _minGasLimit Minimum amount of gas that the bridge can be relayed with. - /// @param _extraData Extra data to be sent with the transaction. Note that the recipient will - /// not be triggered with this data, but it will be emitted and can be used - /// to identify the transaction. - function bridgeETHTo(address _to, uint32 _minGasLimit, bytes calldata _extraData) public payable { - _initiateBridgeETH(msg.sender, _to, msg.value, _minGasLimit, _extraData); - } - /// @notice Sends ERC20 tokens to the sender's address on the other chain. /// @param _localToken Address of the ERC20 on this chain. /// @param _remoteToken Address of the corresponding token on the remote chain. @@ -233,38 +188,6 @@ abstract contract StandardBridge is Initializable { _initiateBridgeERC20(_localToken, _remoteToken, msg.sender, _to, _amount, _minGasLimit, _extraData); } - /// @notice Finalizes an ETH bridge on this chain. Can only be triggered by the other - /// StandardBridge contract on the remote chain. - /// @param _from Address of the sender. - /// @param _to Address of the receiver. - /// @param _amount Amount of ETH being bridged. - /// @param _extraData Extra data to be sent with the transaction. Note that the recipient will - /// not be triggered with this data, but it will be emitted and can be used - /// to identify the transaction. - function finalizeBridgeETH( - address _from, - address _to, - uint256 _amount, - bytes calldata _extraData - ) - public - payable - onlyOtherBridge - { - require(paused() == false, "StandardBridge: paused"); - require(isCustomGasToken() == false, "StandardBridge: cannot bridge ETH with custom gas token"); - require(msg.value == _amount, "StandardBridge: amount sent does not match amount required"); - require(_to != address(this), "StandardBridge: cannot send to self"); - require(_to != address(messenger), "StandardBridge: cannot send to messenger"); - - // Emit the correct events. By default this will be _amount, but child - // contracts may override this function in order to emit legacy events as well. - _emitETHBridgeFinalized(_from, _to, _amount, _extraData); - - bool success = SafeCall.call(_to, gasleft(), _amount, hex""); - require(success, "StandardBridge: ETH transfer failed"); - } - /// @notice Finalizes an ERC20 bridge on this chain. Can only be triggered by the other /// StandardBridge contract on the remote chain. /// @param _localToken Address of the ERC20 on this chain. @@ -287,54 +210,18 @@ abstract contract StandardBridge is Initializable { onlyOtherBridge { require(paused() == false, "StandardBridge: paused"); - if (_isOptimismMintableERC20(_localToken)) { - require( - _isCorrectTokenPair(_localToken, _remoteToken), - "StandardBridge: wrong remote token for Optimism Mintable ERC20 local token" - ); - - OptimismMintableERC20(_localToken).mint(_to, _amount); - } else { - deposits[_localToken][_remoteToken] = deposits[_localToken][_remoteToken] - _amount; - IERC20(_localToken).safeTransfer(_to, _amount); - } + require( + _isCorrectTokenPair(_localToken, _remoteToken), + "StandardBridge: wrong remote token for Optimism Mintable ERC20 local token" + ); + deposits[_localToken][_remoteToken] = deposits[_localToken][_remoteToken] - _amount; + IERC20(_localToken).safeTransfer(_to, _amount); // Emit the correct events. By default this will be ERC20BridgeFinalized, but child // contracts may override this function in order to emit legacy events as well. _emitERC20BridgeFinalized(_localToken, _remoteToken, _from, _to, _amount, _extraData); } - /// @notice Initiates a bridge of ETH through the CrossDomainMessenger. - /// @param _from Address of the sender. - /// @param _to Address of the receiver. - /// @param _amount Amount of ETH being bridged. - /// @param _minGasLimit Minimum amount of gas that the bridge can be relayed with. - /// @param _extraData Extra data to be sent with the transaction. Note that the recipient will - /// not be triggered with this data, but it will be emitted and can be used - /// to identify the transaction. - function _initiateBridgeETH( - address _from, - address _to, - uint256 _amount, - uint32 _minGasLimit, - bytes memory _extraData - ) - internal - { - require(isCustomGasToken() == false, "StandardBridge: cannot bridge ETH with custom gas token"); - require(msg.value == _amount, "StandardBridge: bridging ETH must include sufficient ETH value"); - - // Emit the correct events. By default this will be _amount, but child - // contracts may override this function in order to emit legacy events as well. - _emitETHBridgeInitiated(_from, _to, _amount, _extraData); - - messenger.sendMessage{ value: _amount }({ - _target: address(otherBridge), - _message: abi.encodeWithSelector(this.finalizeBridgeETH.selector, _from, _to, _amount, _extraData), - _minGasLimit: _minGasLimit - }); - } - /// @notice Sends ERC20 tokens to a receiver's address on the other chain. /// @param _localToken Address of the ERC20 on this chain. /// @param _remoteToken Address of the corresponding token on the remote chain. @@ -356,18 +243,13 @@ abstract contract StandardBridge is Initializable { internal { require(msg.value == 0, "StandardBridge: cannot send value"); - - if (_isOptimismMintableERC20(_localToken)) { - require( - _isCorrectTokenPair(_localToken, _remoteToken), - "StandardBridge: wrong remote token for Optimism Mintable ERC20 local token" - ); - - OptimismMintableERC20(_localToken).burn(_from, _amount); - } else { - IERC20(_localToken).safeTransferFrom(_from, address(this), _amount); - deposits[_localToken][_remoteToken] = deposits[_localToken][_remoteToken] + _amount; - } + require(paused() == false, "StandardBridge: paused"); + require( + _isCorrectTokenPair(_localToken, _remoteToken), + "StandardBridge: wrong remote token for Optimism Mintable ERC20 local token" + ); + IERC20(_localToken).safeTransferFrom(_from, address(this), _amount); + deposits[_localToken][_remoteToken] = deposits[_localToken][_remoteToken] + _amount; // Emit the correct events. By default this will be ERC20BridgeInitiated, but child // contracts may override this function in order to emit legacy events as well. @@ -391,63 +273,19 @@ abstract contract StandardBridge is Initializable { }); } - /// @notice Checks if a given address is an OptimismMintableERC20. Not perfect, but good enough. - /// Just the way we like it. - /// @param _token Address of the token to check. - /// @return True if the token is an OptimismMintableERC20. - function _isOptimismMintableERC20(address _token) internal view returns (bool) { - return ERC165Checker.supportsInterface(_token, type(ILegacyMintableERC20).interfaceId) - || ERC165Checker.supportsInterface(_token, type(IOptimismMintableERC20).interfaceId); - } - - /// @notice Checks if the "other token" is the correct pair token for the OptimismMintableERC20. - /// Calls can be saved in the future by combining this logic with - /// `_isOptimismMintableERC20`. - /// @param _mintableToken OptimismMintableERC20 to check against. - /// @param _otherToken Pair token to check. - /// @return True if the other token is the correct pair token for the OptimismMintableERC20. + /** + * @notice Checks if the "other token" is the correct pair token for the OptimismMintableERC20. + * Calls can be saved in the future by combining this logic with + * `_isOptimismMintableERC20`. + * + * @param _mintableToken OptimismMintableERC20 to check against. + * @param _otherToken Pair token to check. + * + * @return True if the other token is the correct pair token for the OptimismMintableERC20. + */ function _isCorrectTokenPair(address _mintableToken, address _otherToken) internal view returns (bool) { - if (ERC165Checker.supportsInterface(_mintableToken, type(ILegacyMintableERC20).interfaceId)) { - return _otherToken == ILegacyMintableERC20(_mintableToken).l1Token(); - } else { - return _otherToken == IOptimismMintableERC20(_mintableToken).remoteToken(); - } - } - - /// @notice Emits the ETHBridgeInitiated event and if necessary the appropriate legacy event - /// when an ETH bridge is finalized on this chain. - /// @param _from Address of the sender. - /// @param _to Address of the receiver. - /// @param _amount Amount of ETH sent. - /// @param _extraData Extra data sent with the transaction. - function _emitETHBridgeInitiated( - address _from, - address _to, - uint256 _amount, - bytes memory _extraData - ) - internal - virtual - { - emit ETHBridgeInitiated(_from, _to, _amount, _extraData); - } - - /// @notice Emits the ETHBridgeFinalized and if necessary the appropriate legacy event when an - /// ETH bridge is finalized on this chain. - /// @param _from Address of the sender. - /// @param _to Address of the receiver. - /// @param _amount Amount of ETH sent. - /// @param _extraData Extra data sent with the transaction. - function _emitETHBridgeFinalized( - address _from, - address _to, - uint256 _amount, - bytes memory _extraData - ) - internal - virtual - { - emit ETHBridgeFinalized(_from, _to, _amount, _extraData); + return + ((_mintableToken == l1USDC && _otherToken == l2USDC) || (_mintableToken == l2USDC && _otherToken == l1USDC)); } /// @notice Emits the ERC20BridgeInitiated event and if necessary the appropriate legacy