github.com/ethereum-optimism/optimism@v1.7.2/packages/contracts-bedrock/test/L1/L1StandardBridge.t.sol (about)

     1  // SPDX-License-Identifier: MIT
     2  pragma solidity 0.8.15;
     3  
     4  // Testing utilities
     5  import { stdStorage, StdStorage } from "forge-std/Test.sol";
     6  import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
     7  import { Bridge_Initializer } from "test/setup/Bridge_Initializer.sol";
     8  
     9  // Libraries
    10  import { Predeploys } from "src/libraries/Predeploys.sol";
    11  
    12  // Target contract dependencies
    13  import { StandardBridge } from "src/universal/StandardBridge.sol";
    14  import { L1StandardBridge } from "src/L1/L1StandardBridge.sol";
    15  import { L2StandardBridge } from "src/L2/L2StandardBridge.sol";
    16  import { CrossDomainMessenger } from "src/universal/CrossDomainMessenger.sol";
    17  import { SuperchainConfig } from "src/L1/SuperchainConfig.sol";
    18  import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol";
    19  
    20  // Target contract
    21  import { OptimismPortal } from "src/L1/OptimismPortal.sol";
    22  
    23  contract L1StandardBridge_Getter_Test is Bridge_Initializer {
    24      /// @dev Test that the accessors return the correct initialized values.
    25      function test_getters_succeeds() external view {
    26          assert(l1StandardBridge.l2TokenBridge() == address(l2StandardBridge));
    27          assert(l1StandardBridge.OTHER_BRIDGE() == l2StandardBridge);
    28          assert(l1StandardBridge.messenger() == l1CrossDomainMessenger);
    29          assert(l1StandardBridge.MESSENGER() == l1CrossDomainMessenger);
    30      }
    31  }
    32  
    33  contract L1StandardBridge_Initialize_Test is Bridge_Initializer {
    34      /// @dev Test that the constructor sets the correct values.
    35      /// @notice Marked virtual to be overridden in
    36      ///         test/kontrol/deployment/DeploymentSummary.t.sol
    37      function test_constructor_succeeds() external virtual {
    38          L1StandardBridge impl = L1StandardBridge(deploy.mustGetAddress("L1StandardBridge"));
    39          assertEq(address(impl.superchainConfig()), address(0));
    40          assertEq(address(impl.MESSENGER()), address(0));
    41          assertEq(address(impl.messenger()), address(0));
    42          assertEq(address(impl.OTHER_BRIDGE()), Predeploys.L2_STANDARD_BRIDGE);
    43          assertEq(address(impl.otherBridge()), Predeploys.L2_STANDARD_BRIDGE);
    44          assertEq(address(l2StandardBridge), Predeploys.L2_STANDARD_BRIDGE);
    45      }
    46  
    47      /// @dev Test that the initialize function sets the correct values.
    48      function test_initialize_succeeds() external {
    49          assertEq(address(l1StandardBridge.superchainConfig()), address(superchainConfig));
    50          assertEq(address(l1StandardBridge.MESSENGER()), address(l1CrossDomainMessenger));
    51          assertEq(address(l1StandardBridge.messenger()), address(l1CrossDomainMessenger));
    52          assertEq(address(l1StandardBridge.OTHER_BRIDGE()), Predeploys.L2_STANDARD_BRIDGE);
    53          assertEq(address(l1StandardBridge.otherBridge()), Predeploys.L2_STANDARD_BRIDGE);
    54          assertEq(address(l2StandardBridge), Predeploys.L2_STANDARD_BRIDGE);
    55      }
    56  }
    57  
    58  contract L1StandardBridge_Pause_Test is Bridge_Initializer {
    59      /// @dev Verifies that the `paused` accessor returns the same value as the `paused` function of the
    60      ///      `superchainConfig`.
    61      function test_paused_succeeds() external {
    62          assertEq(l1StandardBridge.paused(), superchainConfig.paused());
    63      }
    64  
    65      /// @dev Ensures that the `paused` function of the bridge contract actually calls the `paused` function of the
    66      ///      `superchainConfig`.
    67      function test_pause_callsSuperchainConfig_succeeds() external {
    68          vm.expectCall(address(superchainConfig), abi.encodeWithSelector(SuperchainConfig.paused.selector));
    69          l1StandardBridge.paused();
    70      }
    71  
    72      /// @dev Checks that the `paused` state of the bridge matches the `paused` state of the `superchainConfig` after
    73      ///      it's been changed.
    74      function test_pause_matchesSuperchainConfig_succeeds() external {
    75          assertFalse(l1StandardBridge.paused());
    76          assertEq(l1StandardBridge.paused(), superchainConfig.paused());
    77  
    78          vm.prank(superchainConfig.guardian());
    79          superchainConfig.pause("identifier");
    80  
    81          assertTrue(l1StandardBridge.paused());
    82          assertEq(l1StandardBridge.paused(), superchainConfig.paused());
    83      }
    84  }
    85  
    86  contract L1StandardBridge_Pause_TestFail is Bridge_Initializer {
    87      /// @dev Sets up the test by pausing the bridge, giving ether to the bridge and mocking
    88      ///      the calls to the xDomainMessageSender so that it returns the correct value.
    89      function setUp() public override {
    90          super.setUp();
    91          vm.prank(superchainConfig.guardian());
    92          superchainConfig.pause("identifier");
    93          assertTrue(l1StandardBridge.paused());
    94  
    95          vm.deal(address(l1StandardBridge.messenger()), 1 ether);
    96  
    97          vm.mockCall(
    98              address(l1StandardBridge.messenger()),
    99              abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),
   100              abi.encode(address(l1StandardBridge.otherBridge()))
   101          );
   102      }
   103  
   104      /// @dev Confirms that the `finalizeBridgeETH` function reverts when the bridge is paused.
   105      function test_pause_finalizeBridgeETH_reverts() external {
   106          vm.prank(address(l1StandardBridge.messenger()));
   107          vm.expectRevert("StandardBridge: paused");
   108          l1StandardBridge.finalizeBridgeETH{ value: 100 }({
   109              _from: address(2),
   110              _to: address(3),
   111              _amount: 100,
   112              _extraData: hex""
   113          });
   114      }
   115  
   116      /// @dev Confirms that the `finalizeETHWithdrawal` function reverts when the bridge is paused.
   117      function test_pause_finalizeETHWithdrawal_reverts() external {
   118          vm.prank(address(l1StandardBridge.messenger()));
   119          vm.expectRevert("StandardBridge: paused");
   120          l1StandardBridge.finalizeETHWithdrawal{ value: 100 }({
   121              _from: address(2),
   122              _to: address(3),
   123              _amount: 100,
   124              _extraData: hex""
   125          });
   126      }
   127  
   128      /// @dev Confirms that the `finalizeERC20Withdrawal` function reverts when the bridge is paused.
   129      function test_pause_finalizeERC20Withdrawal_reverts() external {
   130          vm.prank(address(l1StandardBridge.messenger()));
   131          vm.expectRevert("StandardBridge: paused");
   132          l1StandardBridge.finalizeERC20Withdrawal({
   133              _l1Token: address(0),
   134              _l2Token: address(0),
   135              _from: address(0),
   136              _to: address(0),
   137              _amount: 0,
   138              _extraData: hex""
   139          });
   140      }
   141  
   142      /// @dev Confirms that the `finalizeBridgeERC20` function reverts when the bridge is paused.
   143      function test_pause_finalizeBridgeERC20_reverts() external {
   144          vm.prank(address(l1StandardBridge.messenger()));
   145          vm.expectRevert("StandardBridge: paused");
   146          l1StandardBridge.finalizeBridgeERC20({
   147              _localToken: address(0),
   148              _remoteToken: address(0),
   149              _from: address(0),
   150              _to: address(0),
   151              _amount: 0,
   152              _extraData: hex""
   153          });
   154      }
   155  }
   156  
   157  contract L1StandardBridge_Initialize_TestFail is Bridge_Initializer { }
   158  
   159  contract L1StandardBridge_Receive_Test is Bridge_Initializer {
   160      /// @dev Tests receive bridges ETH successfully.
   161      function test_receive_succeeds() external {
   162          assertEq(address(optimismPortal).balance, 0);
   163  
   164          // The legacy event must be emitted for backwards compatibility
   165          vm.expectEmit(address(l1StandardBridge));
   166          emit ETHDepositInitiated(alice, alice, 100, hex"");
   167  
   168          vm.expectEmit(address(l1StandardBridge));
   169          emit ETHBridgeInitiated(alice, alice, 100, hex"");
   170  
   171          vm.expectCall(
   172              address(l1CrossDomainMessenger),
   173              abi.encodeWithSelector(
   174                  CrossDomainMessenger.sendMessage.selector,
   175                  address(l2StandardBridge),
   176                  abi.encodeWithSelector(StandardBridge.finalizeBridgeETH.selector, alice, alice, 100, hex""),
   177                  200_000
   178              )
   179          );
   180  
   181          vm.prank(alice, alice);
   182          (bool success,) = address(l1StandardBridge).call{ value: 100 }(hex"");
   183          assertEq(success, true);
   184          assertEq(address(optimismPortal).balance, 100);
   185      }
   186  }
   187  
   188  contract L1StandardBridge_Receive_TestFail { }
   189  
   190  contract PreBridgeETH is Bridge_Initializer {
   191      /// @dev Asserts the expected calls and events for bridging ETH depending
   192      ///      on whether the bridge call is legacy or not.
   193      function _preBridgeETH(bool isLegacy) internal {
   194          assertEq(address(optimismPortal).balance, 0);
   195          uint256 nonce = l1CrossDomainMessenger.messageNonce();
   196          uint256 version = 0; // Internal constant in the OptimismPortal: DEPOSIT_VERSION
   197          address l1MessengerAliased = AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger));
   198  
   199          bytes memory message =
   200              abi.encodeWithSelector(StandardBridge.finalizeBridgeETH.selector, alice, alice, 500, hex"dead");
   201  
   202          if (isLegacy) {
   203              vm.expectCall(
   204                  address(l1StandardBridge),
   205                  500,
   206                  abi.encodeWithSelector(l1StandardBridge.depositETH.selector, 50000, hex"dead")
   207              );
   208          } else {
   209              vm.expectCall(
   210                  address(l1StandardBridge),
   211                  500,
   212                  abi.encodeWithSelector(l1StandardBridge.bridgeETH.selector, 50000, hex"dead")
   213              );
   214          }
   215          vm.expectCall(
   216              address(l1CrossDomainMessenger),
   217              500,
   218              abi.encodeWithSelector(CrossDomainMessenger.sendMessage.selector, address(l2StandardBridge), message, 50000)
   219          );
   220  
   221          bytes memory innerMessage = abi.encodeWithSelector(
   222              CrossDomainMessenger.relayMessage.selector,
   223              nonce,
   224              address(l1StandardBridge),
   225              address(l2StandardBridge),
   226              500,
   227              50000,
   228              message
   229          );
   230  
   231          uint64 baseGas = l1CrossDomainMessenger.baseGas(message, 50000);
   232          vm.expectCall(
   233              address(optimismPortal),
   234              500,
   235              abi.encodeWithSelector(
   236                  OptimismPortal.depositTransaction.selector,
   237                  address(l2CrossDomainMessenger),
   238                  500,
   239                  baseGas,
   240                  false,
   241                  innerMessage
   242              )
   243          );
   244  
   245          bytes memory opaqueData = abi.encodePacked(uint256(500), uint256(500), baseGas, false, innerMessage);
   246  
   247          vm.expectEmit(address(l1StandardBridge));
   248          emit ETHDepositInitiated(alice, alice, 500, hex"dead");
   249  
   250          vm.expectEmit(address(l1StandardBridge));
   251          emit ETHBridgeInitiated(alice, alice, 500, hex"dead");
   252  
   253          // OptimismPortal emits a TransactionDeposited event on `depositTransaction` call
   254          vm.expectEmit(address(optimismPortal));
   255          emit TransactionDeposited(l1MessengerAliased, address(l2CrossDomainMessenger), version, opaqueData);
   256  
   257          // SentMessage event emitted by the CrossDomainMessenger
   258          vm.expectEmit(address(l1CrossDomainMessenger));
   259          emit SentMessage(address(l2StandardBridge), address(l1StandardBridge), message, nonce, 50000);
   260  
   261          // SentMessageExtension1 event emitted by the CrossDomainMessenger
   262          vm.expectEmit(address(l1CrossDomainMessenger));
   263          emit SentMessageExtension1(address(l1StandardBridge), 500);
   264  
   265          vm.prank(alice, alice);
   266      }
   267  }
   268  
   269  contract L1StandardBridge_DepositETH_Test is PreBridgeETH {
   270      /// @dev Tests that depositing ETH succeeds.
   271      ///      Emits ETHDepositInitiated and ETHBridgeInitiated events.
   272      ///      Calls depositTransaction on the OptimismPortal.
   273      ///      Only EOA can call depositETH.
   274      ///      ETH ends up in the optimismPortal.
   275      function test_depositETH_succeeds() external {
   276          _preBridgeETH({ isLegacy: true });
   277          l1StandardBridge.depositETH{ value: 500 }(50000, hex"dead");
   278          assertEq(address(optimismPortal).balance, 500);
   279      }
   280  }
   281  
   282  contract L1StandardBridge_BridgeETH_Test is PreBridgeETH {
   283      /// @dev Tests that bridging ETH succeeds.
   284      ///      Emits ETHDepositInitiated and ETHBridgeInitiated events.
   285      ///      Calls depositTransaction on the OptimismPortal.
   286      ///      Only EOA can call bridgeETH.
   287      ///      ETH ends up in the optimismPortal.
   288      function test_bridgeETH_succeeds() external {
   289          _preBridgeETH({ isLegacy: false });
   290          l1StandardBridge.bridgeETH{ value: 500 }(50000, hex"dead");
   291          assertEq(address(optimismPortal).balance, 500);
   292      }
   293  }
   294  
   295  contract L1StandardBridge_DepositETH_TestFail is Bridge_Initializer {
   296      /// @dev Tests that depositing ETH reverts if the call is not from an EOA.
   297      function test_depositETH_notEoa_reverts() external {
   298          vm.etch(alice, address(L1Token).code);
   299          vm.expectRevert("StandardBridge: function can only be called from an EOA");
   300          vm.prank(alice);
   301          l1StandardBridge.depositETH{ value: 1 }(300, hex"");
   302      }
   303  }
   304  
   305  contract PreBridgeETHTo is Bridge_Initializer {
   306      /// @dev Asserts the expected calls and events for bridging ETH to a different
   307      ///      address depending on whether the bridge call is legacy or not.
   308      function _preBridgeETHTo(bool isLegacy) internal {
   309          assertEq(address(optimismPortal).balance, 0);
   310          uint256 nonce = l1CrossDomainMessenger.messageNonce();
   311          uint256 version = 0; // Internal constant in the OptimismPortal: DEPOSIT_VERSION
   312          address l1MessengerAliased = AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger));
   313  
   314          if (isLegacy) {
   315              vm.expectCall(
   316                  address(l1StandardBridge),
   317                  600,
   318                  abi.encodeWithSelector(l1StandardBridge.depositETHTo.selector, bob, 60000, hex"dead")
   319              );
   320          } else {
   321              vm.expectCall(
   322                  address(l1StandardBridge),
   323                  600,
   324                  abi.encodeWithSelector(l1StandardBridge.bridgeETHTo.selector, bob, 60000, hex"dead")
   325              );
   326          }
   327  
   328          bytes memory message =
   329              abi.encodeWithSelector(StandardBridge.finalizeBridgeETH.selector, alice, bob, 600, hex"dead");
   330  
   331          // the L1 bridge should call
   332          // L1CrossDomainMessenger.sendMessage
   333          vm.expectCall(
   334              address(l1CrossDomainMessenger),
   335              abi.encodeWithSelector(CrossDomainMessenger.sendMessage.selector, address(l2StandardBridge), message, 60000)
   336          );
   337  
   338          bytes memory innerMessage = abi.encodeWithSelector(
   339              CrossDomainMessenger.relayMessage.selector,
   340              nonce,
   341              address(l1StandardBridge),
   342              address(l2StandardBridge),
   343              600,
   344              60000,
   345              message
   346          );
   347  
   348          uint64 baseGas = l1CrossDomainMessenger.baseGas(message, 60000);
   349          vm.expectCall(
   350              address(optimismPortal),
   351              abi.encodeWithSelector(
   352                  OptimismPortal.depositTransaction.selector,
   353                  address(l2CrossDomainMessenger),
   354                  600,
   355                  baseGas,
   356                  false,
   357                  innerMessage
   358              )
   359          );
   360  
   361          bytes memory opaqueData = abi.encodePacked(uint256(600), uint256(600), baseGas, false, innerMessage);
   362  
   363          vm.expectEmit(address(l1StandardBridge));
   364          emit ETHDepositInitiated(alice, bob, 600, hex"dead");
   365  
   366          vm.expectEmit(address(l1StandardBridge));
   367          emit ETHBridgeInitiated(alice, bob, 600, hex"dead");
   368  
   369          // OptimismPortal emits a TransactionDeposited event on `depositTransaction` call
   370          vm.expectEmit(address(optimismPortal));
   371          emit TransactionDeposited(l1MessengerAliased, address(l2CrossDomainMessenger), version, opaqueData);
   372  
   373          // SentMessage event emitted by the CrossDomainMessenger
   374          vm.expectEmit(address(l1CrossDomainMessenger));
   375          emit SentMessage(address(l2StandardBridge), address(l1StandardBridge), message, nonce, 60000);
   376  
   377          // SentMessageExtension1 event emitted by the CrossDomainMessenger
   378          vm.expectEmit(address(l1CrossDomainMessenger));
   379          emit SentMessageExtension1(address(l1StandardBridge), 600);
   380  
   381          // deposit eth to bob
   382          vm.prank(alice, alice);
   383      }
   384  }
   385  
   386  contract L1StandardBridge_DepositETHTo_Test is PreBridgeETHTo {
   387      /// @dev Tests that depositing ETH to a different address succeeds.
   388      ///      Emits ETHDepositInitiated event.
   389      ///      Calls depositTransaction on the OptimismPortal.
   390      ///      EOA or contract can call depositETHTo.
   391      ///      ETH ends up in the optimismPortal.
   392      function test_depositETHTo_succeeds() external {
   393          _preBridgeETHTo({ isLegacy: true });
   394          l1StandardBridge.depositETHTo{ value: 600 }(bob, 60000, hex"dead");
   395          assertEq(address(optimismPortal).balance, 600);
   396      }
   397  }
   398  
   399  contract L1StandardBridge_BridgeETHTo_Test is PreBridgeETHTo {
   400      /// @dev Tests that bridging ETH to a different address succeeds.
   401      ///      Emits ETHDepositInitiated and ETHBridgeInitiated events.
   402      ///      Calls depositTransaction on the OptimismPortal.
   403      ///      Only EOA can call bridgeETHTo.
   404      ///      ETH ends up in the optimismPortal.
   405      function test_bridgeETHTo_succeeds() external {
   406          _preBridgeETHTo({ isLegacy: false });
   407          l1StandardBridge.bridgeETHTo{ value: 600 }(bob, 60000, hex"dead");
   408          assertEq(address(optimismPortal).balance, 600);
   409      }
   410  }
   411  
   412  contract L1StandardBridge_DepositETHTo_TestFail is Bridge_Initializer { }
   413  
   414  contract L1StandardBridge_DepositERC20_Test is Bridge_Initializer {
   415      using stdStorage for StdStorage;
   416  
   417      // depositERC20
   418      // - updates bridge.deposits
   419      // - emits ERC20DepositInitiated
   420      // - calls optimismPortal.depositTransaction
   421      // - only callable by EOA
   422  
   423      /// @dev Tests that depositing ERC20 to the bridge succeeds.
   424      ///      Bridge deposits are updated.
   425      ///      Emits ERC20DepositInitiated event.
   426      ///      Calls depositTransaction on the OptimismPortal.
   427      ///      Only EOA can call depositERC20.
   428      function test_depositERC20_succeeds() external {
   429          uint256 nonce = l1CrossDomainMessenger.messageNonce();
   430          uint256 version = 0; // Internal constant in the OptimismPortal: DEPOSIT_VERSION
   431          address l1MessengerAliased = AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger));
   432  
   433          // Deal Alice's ERC20 State
   434          deal(address(L1Token), alice, 100000, true);
   435          vm.prank(alice);
   436          L1Token.approve(address(l1StandardBridge), type(uint256).max);
   437  
   438          // The l1StandardBridge should transfer alice's tokens to itself
   439          vm.expectCall(
   440              address(L1Token), abi.encodeWithSelector(ERC20.transferFrom.selector, alice, address(l1StandardBridge), 100)
   441          );
   442  
   443          bytes memory message = abi.encodeWithSelector(
   444              StandardBridge.finalizeBridgeERC20.selector, address(L2Token), address(L1Token), alice, alice, 100, hex""
   445          );
   446  
   447          // the L1 bridge should call L1CrossDomainMessenger.sendMessage
   448          vm.expectCall(
   449              address(l1CrossDomainMessenger),
   450              abi.encodeWithSelector(CrossDomainMessenger.sendMessage.selector, address(l2StandardBridge), message, 10000)
   451          );
   452  
   453          bytes memory innerMessage = abi.encodeWithSelector(
   454              CrossDomainMessenger.relayMessage.selector,
   455              nonce,
   456              address(l1StandardBridge),
   457              address(l2StandardBridge),
   458              0,
   459              10000,
   460              message
   461          );
   462  
   463          uint64 baseGas = l1CrossDomainMessenger.baseGas(message, 10000);
   464          vm.expectCall(
   465              address(optimismPortal),
   466              abi.encodeWithSelector(
   467                  OptimismPortal.depositTransaction.selector,
   468                  address(l2CrossDomainMessenger),
   469                  0,
   470                  baseGas,
   471                  false,
   472                  innerMessage
   473              )
   474          );
   475  
   476          bytes memory opaqueData = abi.encodePacked(uint256(0), uint256(0), baseGas, false, innerMessage);
   477  
   478          // Should emit both the bedrock and legacy events
   479          vm.expectEmit(address(l1StandardBridge));
   480          emit ERC20DepositInitiated(address(L1Token), address(L2Token), alice, alice, 100, hex"");
   481  
   482          vm.expectEmit(address(l1StandardBridge));
   483          emit ERC20BridgeInitiated(address(L1Token), address(L2Token), alice, alice, 100, hex"");
   484  
   485          // OptimismPortal emits a TransactionDeposited event on `depositTransaction` call
   486          vm.expectEmit(address(optimismPortal));
   487          emit TransactionDeposited(l1MessengerAliased, address(l2CrossDomainMessenger), version, opaqueData);
   488  
   489          // SentMessage event emitted by the CrossDomainMessenger
   490          vm.expectEmit(address(l1CrossDomainMessenger));
   491          emit SentMessage(address(l2StandardBridge), address(l1StandardBridge), message, nonce, 10000);
   492  
   493          // SentMessageExtension1 event emitted by the CrossDomainMessenger
   494          vm.expectEmit(address(l1CrossDomainMessenger));
   495          emit SentMessageExtension1(address(l1StandardBridge), 0);
   496  
   497          vm.prank(alice);
   498          l1StandardBridge.depositERC20(address(L1Token), address(L2Token), 100, 10000, hex"");
   499          assertEq(l1StandardBridge.deposits(address(L1Token), address(L2Token)), 100);
   500      }
   501  }
   502  
   503  contract L1StandardBridge_DepositERC20_TestFail is Bridge_Initializer {
   504      /// @dev Tests that depositing an ERC20 to the bridge reverts
   505      ///      if the caller is not an EOA.
   506      function test_depositERC20_notEoa_reverts() external {
   507          // turn alice into a contract
   508          vm.etch(alice, hex"ffff");
   509  
   510          vm.expectRevert("StandardBridge: function can only be called from an EOA");
   511          vm.prank(alice, alice);
   512          l1StandardBridge.depositERC20(address(0), address(0), 100, 100, hex"");
   513      }
   514  }
   515  
   516  contract L1StandardBridge_DepositERC20To_Test is Bridge_Initializer {
   517      /// @dev Tests that depositing ERC20 to the bridge succeeds when
   518      ///      sent to a different address.
   519      ///      Bridge deposits are updated.
   520      ///      Emits ERC20DepositInitiated event.
   521      ///      Calls depositTransaction on the OptimismPortal.
   522      ///      Contracts can call depositERC20.
   523      function test_depositERC20To_succeeds() external {
   524          uint256 nonce = l1CrossDomainMessenger.messageNonce();
   525          uint256 version = 0; // Internal constant in the OptimismPortal: DEPOSIT_VERSION
   526          address l1MessengerAliased = AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger));
   527  
   528          bytes memory message = abi.encodeWithSelector(
   529              StandardBridge.finalizeBridgeERC20.selector, address(L2Token), address(L1Token), alice, bob, 1000, hex""
   530          );
   531  
   532          bytes memory innerMessage = abi.encodeWithSelector(
   533              CrossDomainMessenger.relayMessage.selector,
   534              nonce,
   535              address(l1StandardBridge),
   536              address(l2StandardBridge),
   537              0,
   538              10000,
   539              message
   540          );
   541  
   542          uint64 baseGas = l1CrossDomainMessenger.baseGas(message, 10000);
   543          bytes memory opaqueData = abi.encodePacked(uint256(0), uint256(0), baseGas, false, innerMessage);
   544  
   545          deal(address(L1Token), alice, 100000, true);
   546  
   547          vm.prank(alice);
   548          L1Token.approve(address(l1StandardBridge), type(uint256).max);
   549  
   550          // Should emit both the bedrock and legacy events
   551          vm.expectEmit(address(l1StandardBridge));
   552          emit ERC20DepositInitiated(address(L1Token), address(L2Token), alice, bob, 1000, hex"");
   553  
   554          vm.expectEmit(address(l1StandardBridge));
   555          emit ERC20BridgeInitiated(address(L1Token), address(L2Token), alice, bob, 1000, hex"");
   556  
   557          // OptimismPortal emits a TransactionDeposited event on `depositTransaction` call
   558          vm.expectEmit(address(optimismPortal));
   559          emit TransactionDeposited(l1MessengerAliased, address(l2CrossDomainMessenger), version, opaqueData);
   560  
   561          // SentMessage event emitted by the CrossDomainMessenger
   562          vm.expectEmit(address(l1CrossDomainMessenger));
   563          emit SentMessage(address(l2StandardBridge), address(l1StandardBridge), message, nonce, 10000);
   564  
   565          // SentMessageExtension1 event emitted by the CrossDomainMessenger
   566          vm.expectEmit(address(l1CrossDomainMessenger));
   567          emit SentMessageExtension1(address(l1StandardBridge), 0);
   568  
   569          // the L1 bridge should call L1CrossDomainMessenger.sendMessage
   570          vm.expectCall(
   571              address(l1CrossDomainMessenger),
   572              abi.encodeWithSelector(CrossDomainMessenger.sendMessage.selector, address(l2StandardBridge), message, 10000)
   573          );
   574          // The L1 XDM should call OptimismPortal.depositTransaction
   575          vm.expectCall(
   576              address(optimismPortal),
   577              abi.encodeWithSelector(
   578                  OptimismPortal.depositTransaction.selector,
   579                  address(l2CrossDomainMessenger),
   580                  0,
   581                  baseGas,
   582                  false,
   583                  innerMessage
   584              )
   585          );
   586          vm.expectCall(
   587              address(L1Token),
   588              abi.encodeWithSelector(ERC20.transferFrom.selector, alice, address(l1StandardBridge), 1000)
   589          );
   590  
   591          vm.prank(alice);
   592          l1StandardBridge.depositERC20To(address(L1Token), address(L2Token), bob, 1000, 10000, hex"");
   593  
   594          assertEq(l1StandardBridge.deposits(address(L1Token), address(L2Token)), 1000);
   595      }
   596  }
   597  
   598  contract L1StandardBridge_FinalizeETHWithdrawal_Test is Bridge_Initializer {
   599      using stdStorage for StdStorage;
   600  
   601      /// @dev Tests that finalizing an ETH withdrawal succeeds.
   602      ///      Emits ETHWithdrawalFinalized event.
   603      ///      Only callable by the L2 bridge.
   604      function test_finalizeETHWithdrawal_succeeds() external {
   605          uint256 aliceBalance = alice.balance;
   606  
   607          vm.expectEmit(address(l1StandardBridge));
   608          emit ETHWithdrawalFinalized(alice, alice, 100, hex"");
   609  
   610          vm.expectEmit(address(l1StandardBridge));
   611          emit ETHBridgeFinalized(alice, alice, 100, hex"");
   612  
   613          vm.expectCall(alice, hex"");
   614  
   615          vm.mockCall(
   616              address(l1StandardBridge.messenger()),
   617              abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),
   618              abi.encode(address(l1StandardBridge.OTHER_BRIDGE()))
   619          );
   620          // ensure that the messenger has ETH to call with
   621          vm.deal(address(l1StandardBridge.messenger()), 100);
   622          vm.prank(address(l1StandardBridge.messenger()));
   623          l1StandardBridge.finalizeETHWithdrawal{ value: 100 }(alice, alice, 100, hex"");
   624  
   625          assertEq(address(l1StandardBridge.messenger()).balance, 0);
   626          assertEq(aliceBalance + 100, alice.balance);
   627      }
   628  }
   629  
   630  contract L1StandardBridge_FinalizeETHWithdrawal_TestFail is Bridge_Initializer { }
   631  
   632  contract L1StandardBridge_FinalizeERC20Withdrawal_Test is Bridge_Initializer {
   633      using stdStorage for StdStorage;
   634  
   635      /// @dev Tests that finalizing an ERC20 withdrawal succeeds.
   636      ///      Bridge deposits are updated.
   637      ///      Emits ERC20WithdrawalFinalized event.
   638      ///      Only callable by the L2 bridge.
   639      function test_finalizeERC20Withdrawal_succeeds() external {
   640          deal(address(L1Token), address(l1StandardBridge), 100, true);
   641  
   642          uint256 slot = stdstore.target(address(l1StandardBridge)).sig("deposits(address,address)").with_key(
   643              address(L1Token)
   644          ).with_key(address(L2Token)).find();
   645  
   646          // Give the L1 bridge some ERC20 tokens
   647          vm.store(address(l1StandardBridge), bytes32(slot), bytes32(uint256(100)));
   648          assertEq(l1StandardBridge.deposits(address(L1Token), address(L2Token)), 100);
   649  
   650          vm.expectEmit(address(l1StandardBridge));
   651          emit ERC20WithdrawalFinalized(address(L1Token), address(L2Token), alice, alice, 100, hex"");
   652  
   653          vm.expectEmit(address(l1StandardBridge));
   654          emit ERC20BridgeFinalized(address(L1Token), address(L2Token), alice, alice, 100, hex"");
   655  
   656          vm.expectCall(address(L1Token), abi.encodeWithSelector(ERC20.transfer.selector, alice, 100));
   657  
   658          vm.mockCall(
   659              address(l1StandardBridge.messenger()),
   660              abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),
   661              abi.encode(address(l1StandardBridge.OTHER_BRIDGE()))
   662          );
   663          vm.prank(address(l1StandardBridge.messenger()));
   664          l1StandardBridge.finalizeERC20Withdrawal(address(L1Token), address(L2Token), alice, alice, 100, hex"");
   665  
   666          assertEq(L1Token.balanceOf(address(l1StandardBridge)), 0);
   667          assertEq(L1Token.balanceOf(address(alice)), 100);
   668      }
   669  }
   670  
   671  contract L1StandardBridge_FinalizeERC20Withdrawal_TestFail is Bridge_Initializer {
   672      /// @dev Tests that finalizing an ERC20 withdrawal reverts if the caller is not the L2 bridge.
   673      function test_finalizeERC20Withdrawal_notMessenger_reverts() external {
   674          vm.mockCall(
   675              address(l1StandardBridge.messenger()),
   676              abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),
   677              abi.encode(address(l1StandardBridge.OTHER_BRIDGE()))
   678          );
   679          vm.prank(address(28));
   680          vm.expectRevert("StandardBridge: function can only be called from the other bridge");
   681          l1StandardBridge.finalizeERC20Withdrawal(address(L1Token), address(L2Token), alice, alice, 100, hex"");
   682      }
   683  
   684      /// @dev Tests that finalizing an ERC20 withdrawal reverts if the caller is not the L2 bridge.
   685      function test_finalizeERC20Withdrawal_notOtherBridge_reverts() external {
   686          vm.mockCall(
   687              address(l1StandardBridge.messenger()),
   688              abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),
   689              abi.encode(address(address(0)))
   690          );
   691          vm.prank(address(l1StandardBridge.messenger()));
   692          vm.expectRevert("StandardBridge: function can only be called from the other bridge");
   693          l1StandardBridge.finalizeERC20Withdrawal(address(L1Token), address(L2Token), alice, alice, 100, hex"");
   694      }
   695  }
   696  
   697  contract L1StandardBridge_FinalizeBridgeETH_Test is Bridge_Initializer {
   698      /// @dev Tests that finalizing bridged ETH succeeds.
   699      function test_finalizeBridgeETH_succeeds() external {
   700          address messenger = address(l1StandardBridge.messenger());
   701          vm.mockCall(
   702              messenger,
   703              abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),
   704              abi.encode(address(l1StandardBridge.OTHER_BRIDGE()))
   705          );
   706          vm.deal(messenger, 100);
   707          vm.prank(messenger);
   708  
   709          vm.expectEmit(address(l1StandardBridge));
   710          emit ETHBridgeFinalized(alice, alice, 100, hex"");
   711  
   712          l1StandardBridge.finalizeBridgeETH{ value: 100 }(alice, alice, 100, hex"");
   713      }
   714  }
   715  
   716  contract L1StandardBridge_FinalizeBridgeETH_TestFail is Bridge_Initializer {
   717      /// @dev Tests that finalizing bridged ETH reverts if the amount is incorrect.
   718      function test_finalizeBridgeETH_incorrectValue_reverts() external {
   719          address messenger = address(l1StandardBridge.messenger());
   720          vm.mockCall(
   721              messenger,
   722              abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),
   723              abi.encode(address(l1StandardBridge.OTHER_BRIDGE()))
   724          );
   725          vm.deal(messenger, 100);
   726          vm.prank(messenger);
   727          vm.expectRevert("StandardBridge: amount sent does not match amount required");
   728          l1StandardBridge.finalizeBridgeETH{ value: 50 }(alice, alice, 100, hex"");
   729      }
   730  
   731      /// @dev Tests that finalizing bridged ETH reverts if the destination is the L1 bridge.
   732      function test_finalizeBridgeETH_sendToSelf_reverts() external {
   733          address messenger = address(l1StandardBridge.messenger());
   734          vm.mockCall(
   735              messenger,
   736              abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),
   737              abi.encode(address(l1StandardBridge.OTHER_BRIDGE()))
   738          );
   739          vm.deal(messenger, 100);
   740          vm.prank(messenger);
   741          vm.expectRevert("StandardBridge: cannot send to self");
   742          l1StandardBridge.finalizeBridgeETH{ value: 100 }(alice, address(l1StandardBridge), 100, hex"");
   743      }
   744  
   745      /// @dev Tests that finalizing bridged ETH reverts if the destination is the messenger.
   746      function test_finalizeBridgeETH_sendToMessenger_reverts() external {
   747          address messenger = address(l1StandardBridge.messenger());
   748          vm.mockCall(
   749              messenger,
   750              abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),
   751              abi.encode(address(l1StandardBridge.OTHER_BRIDGE()))
   752          );
   753          vm.deal(messenger, 100);
   754          vm.prank(messenger);
   755          vm.expectRevert("StandardBridge: cannot send to messenger");
   756          l1StandardBridge.finalizeBridgeETH{ value: 100 }(alice, messenger, 100, hex"");
   757      }
   758  }