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

     1  // SPDX-License-Identifier: MIT
     2  pragma solidity 0.8.15;
     3  
     4  // Testing utilities
     5  import { Bridge_Initializer } from "test/setup/Bridge_Initializer.sol";
     6  import { Reverter, ConfigurableCaller } from "test/mocks/Callers.sol";
     7  
     8  // Libraries
     9  import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol";
    10  import { Predeploys } from "src/libraries/Predeploys.sol";
    11  import { Hashing } from "src/libraries/Hashing.sol";
    12  import { Encoding } from "src/libraries/Encoding.sol";
    13  import { Constants } from "src/libraries/Constants.sol";
    14  
    15  // Target contract dependencies
    16  import { L1CrossDomainMessenger } from "src/L1/L1CrossDomainMessenger.sol";
    17  import { OptimismPortal } from "src/L1/OptimismPortal.sol";
    18  import { SuperchainConfig } from "src/L1/SuperchainConfig.sol";
    19  
    20  contract L1CrossDomainMessenger_Test is Bridge_Initializer {
    21      /// @dev The receiver address
    22      address recipient = address(0xabbaacdc);
    23  
    24      /// @dev The storage slot of the l2Sender
    25      uint256 constant senderSlotIndex = 50;
    26  
    27      /// @dev Tests that the implementation is initialized correctly.
    28      /// @notice Marked virtual to be overridden in
    29      ///         test/kontrol/deployment/DeploymentSummary.t.sol
    30      function test_constructor_succeeds() external virtual {
    31          L1CrossDomainMessenger impl = L1CrossDomainMessenger(deploy.mustGetAddress("L1CrossDomainMessenger"));
    32          assertEq(address(impl.superchainConfig()), address(0));
    33          assertEq(address(impl.PORTAL()), address(0));
    34          assertEq(address(impl.portal()), address(0));
    35          assertEq(address(impl.OTHER_MESSENGER()), Predeploys.L2_CROSS_DOMAIN_MESSENGER);
    36          assertEq(address(impl.otherMessenger()), Predeploys.L2_CROSS_DOMAIN_MESSENGER);
    37      }
    38  
    39      /// @dev Tests that the proxy is initialized correctly.
    40      function test_initialize_succeeds() external {
    41          assertEq(address(l1CrossDomainMessenger.superchainConfig()), address(superchainConfig));
    42          assertEq(address(l1CrossDomainMessenger.PORTAL()), address(optimismPortal));
    43          assertEq(address(l1CrossDomainMessenger.portal()), address(optimismPortal));
    44          assertEq(address(l1CrossDomainMessenger.OTHER_MESSENGER()), Predeploys.L2_CROSS_DOMAIN_MESSENGER);
    45          assertEq(address(l1CrossDomainMessenger.otherMessenger()), Predeploys.L2_CROSS_DOMAIN_MESSENGER);
    46      }
    47  
    48      /// @dev Tests that the version can be decoded from the message nonce.
    49      function test_messageVersion_succeeds() external {
    50          (, uint16 version) = Encoding.decodeVersionedNonce(l1CrossDomainMessenger.messageNonce());
    51          assertEq(version, l1CrossDomainMessenger.MESSAGE_VERSION());
    52      }
    53  
    54      /// @dev Tests that the sendMessage function is able to send a single message.
    55      /// TODO: this same test needs to be done with the legacy message type
    56      ///       by setting the message version to 0
    57      function test_sendMessage_succeeds() external {
    58          // deposit transaction on the optimism portal should be called
    59          vm.expectCall(
    60              address(optimismPortal),
    61              abi.encodeWithSelector(
    62                  OptimismPortal.depositTransaction.selector,
    63                  Predeploys.L2_CROSS_DOMAIN_MESSENGER,
    64                  0,
    65                  l1CrossDomainMessenger.baseGas(hex"ff", 100),
    66                  false,
    67                  Encoding.encodeCrossDomainMessage(
    68                      l1CrossDomainMessenger.messageNonce(), alice, recipient, 0, 100, hex"ff"
    69                  )
    70              )
    71          );
    72  
    73          // TransactionDeposited event
    74          vm.expectEmit(address(optimismPortal));
    75          emitTransactionDeposited(
    76              AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger)),
    77              Predeploys.L2_CROSS_DOMAIN_MESSENGER,
    78              0,
    79              0,
    80              l1CrossDomainMessenger.baseGas(hex"ff", 100),
    81              false,
    82              Encoding.encodeCrossDomainMessage(l1CrossDomainMessenger.messageNonce(), alice, recipient, 0, 100, hex"ff")
    83          );
    84  
    85          // SentMessage event
    86          vm.expectEmit(address(l1CrossDomainMessenger));
    87          emit SentMessage(recipient, alice, hex"ff", l1CrossDomainMessenger.messageNonce(), 100);
    88  
    89          // SentMessageExtension1 event
    90          vm.expectEmit(address(l1CrossDomainMessenger));
    91          emit SentMessageExtension1(alice, 0);
    92  
    93          vm.prank(alice);
    94          l1CrossDomainMessenger.sendMessage(recipient, hex"ff", uint32(100));
    95      }
    96  
    97      /// @dev Tests that the sendMessage function is able to send
    98      ///      the same message twice.
    99      function test_sendMessage_twice_succeeds() external {
   100          uint256 nonce = l1CrossDomainMessenger.messageNonce();
   101          l1CrossDomainMessenger.sendMessage(recipient, hex"aa", uint32(500_000));
   102          l1CrossDomainMessenger.sendMessage(recipient, hex"aa", uint32(500_000));
   103          // the nonce increments for each message sent
   104          assertEq(nonce + 2, l1CrossDomainMessenger.messageNonce());
   105      }
   106  
   107      /// @dev Tests that the xDomainMessageSender reverts when not set.
   108      function test_xDomainSender_notSet_reverts() external {
   109          vm.expectRevert("CrossDomainMessenger: xDomainMessageSender is not set");
   110          l1CrossDomainMessenger.xDomainMessageSender();
   111      }
   112  
   113      /// @dev Tests that the relayMessage function reverts when
   114      ///      the message version is not 0 or 1.
   115      /// @notice Marked virtual to be overridden in
   116      ///         test/kontrol/deployment/DeploymentSummary.t.sol
   117      function test_relayMessage_v2_reverts() external virtual {
   118          address target = address(0xabcd);
   119          address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;
   120  
   121          // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.
   122          vm.store(address(optimismPortal), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));
   123  
   124          // Expect a revert.
   125          vm.expectRevert("CrossDomainMessenger: only version 0 or 1 messages are supported at this time");
   126  
   127          // Try to relay a v2 message.
   128          vm.prank(address(optimismPortal));
   129          l2CrossDomainMessenger.relayMessage(
   130              Encoding.encodeVersionedNonce({ _nonce: 0, _version: 2 }), // nonce
   131              sender,
   132              target,
   133              0, // value
   134              0,
   135              hex"1111"
   136          );
   137      }
   138  
   139      /// @dev Tests that the relayMessage function is able to relay a message
   140      ///      successfully by calling the target contract.
   141      function test_relayMessage_succeeds() external {
   142          address target = address(0xabcd);
   143          address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;
   144  
   145          vm.expectCall(target, hex"1111");
   146  
   147          // set the value of op.l2Sender() to be the L2 Cross Domain Messenger.
   148          vm.store(address(optimismPortal), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));
   149          vm.prank(address(optimismPortal));
   150  
   151          vm.expectEmit(address(l1CrossDomainMessenger));
   152  
   153          bytes32 hash = Hashing.hashCrossDomainMessage(
   154              Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), sender, target, 0, 0, hex"1111"
   155          );
   156  
   157          emit RelayedMessage(hash);
   158  
   159          l1CrossDomainMessenger.relayMessage(
   160              Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), // nonce
   161              sender,
   162              target,
   163              0, // value
   164              0,
   165              hex"1111"
   166          );
   167  
   168          // the message hash is in the successfulMessages mapping
   169          assert(l1CrossDomainMessenger.successfulMessages(hash));
   170          // it is not in the received messages mapping
   171          assertEq(l1CrossDomainMessenger.failedMessages(hash), false);
   172      }
   173  
   174      /// @dev Tests that relayMessage reverts if attempting to relay a message
   175      ///      sent to an L1 system contract.
   176      function test_relayMessage_toSystemContract_reverts() external {
   177          // set the target to be the OptimismPortal
   178          address target = address(optimismPortal);
   179          address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;
   180          bytes memory message = hex"1111";
   181  
   182          vm.prank(address(optimismPortal));
   183          vm.expectRevert("CrossDomainMessenger: message cannot be replayed");
   184          l1CrossDomainMessenger.relayMessage(
   185              Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), sender, target, 0, 0, message
   186          );
   187  
   188          vm.store(address(optimismPortal), 0, bytes32(abi.encode(sender)));
   189          vm.expectRevert("CrossDomainMessenger: message cannot be replayed");
   190          l1CrossDomainMessenger.relayMessage(
   191              Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), sender, target, 0, 0, message
   192          );
   193      }
   194  
   195      /// @dev Tests that the relayMessage function reverts if eth is
   196      ///      sent from a contract other than the standard bridge.
   197      function test_replayMessage_withValue_reverts() external {
   198          address target = address(0xabcd);
   199          address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;
   200          bytes memory message = hex"1111";
   201  
   202          vm.expectRevert("CrossDomainMessenger: value must be zero unless message is from a system address");
   203          l1CrossDomainMessenger.relayMessage{ value: 100 }(
   204              Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), sender, target, 0, 0, message
   205          );
   206      }
   207  
   208      /// @dev Tests that the xDomainMessageSender is reset to the original value
   209      ///      after a message is relayed.
   210      function test_xDomainMessageSender_reset_succeeds() external {
   211          vm.expectRevert("CrossDomainMessenger: xDomainMessageSender is not set");
   212          l1CrossDomainMessenger.xDomainMessageSender();
   213  
   214          address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;
   215  
   216          vm.store(address(optimismPortal), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));
   217          vm.prank(address(optimismPortal));
   218          l1CrossDomainMessenger.relayMessage(
   219              Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), address(0), address(0), 0, 0, hex""
   220          );
   221  
   222          vm.expectRevert("CrossDomainMessenger: xDomainMessageSender is not set");
   223          l1CrossDomainMessenger.xDomainMessageSender();
   224      }
   225  
   226      /// @dev Tests that relayMessage should successfully call the target contract after
   227      ///      the first message fails and ETH is stuck, but the second message succeeds
   228      ///      with a version 1 message.
   229      function test_relayMessage_retryAfterFailure_succeeds() external {
   230          address target = address(0xabcd);
   231          address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;
   232          uint256 value = 100;
   233  
   234          vm.expectCall(target, hex"1111");
   235  
   236          bytes32 hash = Hashing.hashCrossDomainMessage(
   237              Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), sender, target, value, 0, hex"1111"
   238          );
   239  
   240          vm.store(address(optimismPortal), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));
   241          vm.etch(target, address(new Reverter()).code);
   242          vm.deal(address(optimismPortal), value);
   243          vm.prank(address(optimismPortal));
   244          l1CrossDomainMessenger.relayMessage{ value: value }(
   245              Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), // nonce
   246              sender,
   247              target,
   248              value,
   249              0,
   250              hex"1111"
   251          );
   252  
   253          assertEq(address(l1CrossDomainMessenger).balance, value);
   254          assertEq(address(target).balance, 0);
   255          assertEq(l1CrossDomainMessenger.successfulMessages(hash), false);
   256          assertEq(l1CrossDomainMessenger.failedMessages(hash), true);
   257  
   258          vm.expectEmit(address(l1CrossDomainMessenger));
   259  
   260          emit RelayedMessage(hash);
   261  
   262          vm.etch(target, address(0).code);
   263          vm.prank(address(sender));
   264          l1CrossDomainMessenger.relayMessage(
   265              Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), // nonce
   266              sender,
   267              target,
   268              value,
   269              0,
   270              hex"1111"
   271          );
   272  
   273          assertEq(address(l1CrossDomainMessenger).balance, 0);
   274          assertEq(address(target).balance, value);
   275          assertEq(l1CrossDomainMessenger.successfulMessages(hash), true);
   276          assertEq(l1CrossDomainMessenger.failedMessages(hash), true);
   277      }
   278  
   279      /// @dev Tests that relayMessage should successfully call the target contract after
   280      ///      the first message fails and ETH is stuck, but the second message succeeds
   281      ///      with a legacy message.
   282      function test_relayMessage_legacy_succeeds() external {
   283          address target = address(0xabcd);
   284          address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;
   285  
   286          // Compute the message hash.
   287          bytes32 hash = Hashing.hashCrossDomainMessageV1(
   288              // Using a legacy nonce with version 0.
   289              Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }),
   290              sender,
   291              target,
   292              0,
   293              0,
   294              hex"1111"
   295          );
   296  
   297          // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.
   298          vm.store(address(optimismPortal), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));
   299  
   300          // Target should be called with expected data.
   301          vm.expectCall(target, hex"1111");
   302  
   303          // Expect RelayedMessage event to be emitted.
   304          vm.expectEmit(address(l1CrossDomainMessenger));
   305          emit RelayedMessage(hash);
   306  
   307          // Relay the message.
   308          vm.prank(address(optimismPortal));
   309          l1CrossDomainMessenger.relayMessage(
   310              Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce
   311              sender,
   312              target,
   313              0, // value
   314              0,
   315              hex"1111"
   316          );
   317  
   318          // Message was successfully relayed.
   319          assertEq(l1CrossDomainMessenger.successfulMessages(hash), true);
   320          assertEq(l1CrossDomainMessenger.failedMessages(hash), false);
   321      }
   322  
   323      /// @dev Tests that relayMessage should revert if the message is already replayed.
   324      function test_relayMessage_legacyOldReplay_reverts() external {
   325          address target = address(0xabcd);
   326          address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;
   327  
   328          // Compute the message hash.
   329          bytes32 hash = Hashing.hashCrossDomainMessageV1(
   330              // Using a legacy nonce with version 0.
   331              Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }),
   332              sender,
   333              target,
   334              0,
   335              0,
   336              hex"1111"
   337          );
   338  
   339          // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.
   340          vm.store(address(optimismPortal), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));
   341          // Mark legacy message as already relayed.
   342          uint256 successfulMessagesSlot = 203;
   343          bytes32 oldHash = Hashing.hashCrossDomainMessageV0(target, sender, hex"1111", 0);
   344          bytes32 slot = keccak256(abi.encode(oldHash, successfulMessagesSlot));
   345          vm.store(address(l1CrossDomainMessenger), slot, bytes32(uint256(1)));
   346  
   347          // Expect revert.
   348          vm.expectRevert("CrossDomainMessenger: legacy withdrawal already relayed");
   349  
   350          // Relay the message.
   351          vm.prank(address(optimismPortal));
   352          l1CrossDomainMessenger.relayMessage(
   353              Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce
   354              sender,
   355              target,
   356              0, // value
   357              0,
   358              hex"1111"
   359          );
   360  
   361          // Message was not relayed.
   362          assertEq(l1CrossDomainMessenger.successfulMessages(hash), false);
   363          assertEq(l1CrossDomainMessenger.failedMessages(hash), false);
   364      }
   365  
   366      /// @dev Tests that relayMessage can be retried after a failure with a legacy message.
   367      function test_relayMessage_legacyRetryAfterFailure_succeeds() external {
   368          address target = address(0xabcd);
   369          address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;
   370          uint256 value = 100;
   371  
   372          // Compute the message hash.
   373          bytes32 hash = Hashing.hashCrossDomainMessageV1(
   374              // Using a legacy nonce with version 0.
   375              Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }),
   376              sender,
   377              target,
   378              value,
   379              0,
   380              hex"1111"
   381          );
   382  
   383          // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.
   384          vm.store(address(optimismPortal), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));
   385  
   386          // Turn the target into a Reverter.
   387          vm.etch(target, address(new Reverter()).code);
   388  
   389          // Target should be called with expected data.
   390          vm.expectCall(target, hex"1111");
   391  
   392          // Expect FailedRelayedMessage event to be emitted.
   393          vm.expectEmit(address(l1CrossDomainMessenger));
   394          emit FailedRelayedMessage(hash);
   395  
   396          // Relay the message.
   397          vm.deal(address(optimismPortal), value);
   398          vm.prank(address(optimismPortal));
   399          l1CrossDomainMessenger.relayMessage{ value: value }(
   400              Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce
   401              sender,
   402              target,
   403              value,
   404              0,
   405              hex"1111"
   406          );
   407  
   408          // Message failed.
   409          assertEq(address(l1CrossDomainMessenger).balance, value);
   410          assertEq(address(target).balance, 0);
   411          assertEq(l1CrossDomainMessenger.successfulMessages(hash), false);
   412          assertEq(l1CrossDomainMessenger.failedMessages(hash), true);
   413  
   414          // Make the target not revert anymore.
   415          vm.etch(target, address(0).code);
   416  
   417          // Target should be called with expected data.
   418          vm.expectCall(target, hex"1111");
   419  
   420          // Expect RelayedMessage event to be emitted.
   421          vm.expectEmit(address(l1CrossDomainMessenger));
   422          emit RelayedMessage(hash);
   423  
   424          // Retry the message.
   425          vm.prank(address(sender));
   426          l1CrossDomainMessenger.relayMessage(
   427              Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce
   428              sender,
   429              target,
   430              value,
   431              0,
   432              hex"1111"
   433          );
   434  
   435          // Message was successfully relayed.
   436          assertEq(address(l1CrossDomainMessenger).balance, 0);
   437          assertEq(address(target).balance, value);
   438          assertEq(l1CrossDomainMessenger.successfulMessages(hash), true);
   439          assertEq(l1CrossDomainMessenger.failedMessages(hash), true);
   440      }
   441  
   442      /// @dev Tests that relayMessage cannot be retried after success with a legacy message.
   443      function test_relayMessage_legacyRetryAfterSuccess_reverts() external {
   444          address target = address(0xabcd);
   445          address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;
   446          uint256 value = 100;
   447  
   448          // Compute the message hash.
   449          bytes32 hash = Hashing.hashCrossDomainMessageV1(
   450              // Using a legacy nonce with version 0.
   451              Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }),
   452              sender,
   453              target,
   454              value,
   455              0,
   456              hex"1111"
   457          );
   458  
   459          // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.
   460          vm.store(address(optimismPortal), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));
   461  
   462          // Target should be called with expected data.
   463          vm.expectCall(target, hex"1111");
   464  
   465          // Expect RelayedMessage event to be emitted.
   466          vm.expectEmit(address(l1CrossDomainMessenger));
   467          emit RelayedMessage(hash);
   468  
   469          // Relay the message.
   470          vm.deal(address(optimismPortal), value);
   471          vm.prank(address(optimismPortal));
   472          l1CrossDomainMessenger.relayMessage{ value: value }(
   473              Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce
   474              sender,
   475              target,
   476              value,
   477              0,
   478              hex"1111"
   479          );
   480  
   481          // Message was successfully relayed.
   482          assertEq(address(l1CrossDomainMessenger).balance, 0);
   483          assertEq(address(target).balance, value);
   484          assertEq(l1CrossDomainMessenger.successfulMessages(hash), true);
   485          assertEq(l1CrossDomainMessenger.failedMessages(hash), false);
   486  
   487          // Expect a revert.
   488          vm.expectRevert("CrossDomainMessenger: message cannot be replayed");
   489  
   490          // Retry the message.
   491          vm.prank(address(sender));
   492          l1CrossDomainMessenger.relayMessage(
   493              Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce
   494              sender,
   495              target,
   496              value,
   497              0,
   498              hex"1111"
   499          );
   500      }
   501  
   502      /// @dev Tests that relayMessage cannot be called after a failure and a successful replay.
   503      function test_relayMessage_legacyRetryAfterFailureThenSuccess_reverts() external {
   504          address target = address(0xabcd);
   505          address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;
   506          uint256 value = 100;
   507  
   508          // Compute the message hash.
   509          bytes32 hash = Hashing.hashCrossDomainMessageV1(
   510              // Using a legacy nonce with version 0.
   511              Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }),
   512              sender,
   513              target,
   514              value,
   515              0,
   516              hex"1111"
   517          );
   518  
   519          // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.
   520          vm.store(address(optimismPortal), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));
   521  
   522          // Turn the target into a Reverter.
   523          vm.etch(target, address(new Reverter()).code);
   524  
   525          // Target should be called with expected data.
   526          vm.expectCall(target, hex"1111");
   527  
   528          // Relay the message.
   529          vm.deal(address(optimismPortal), value);
   530          vm.prank(address(optimismPortal));
   531          l1CrossDomainMessenger.relayMessage{ value: value }(
   532              Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce
   533              sender,
   534              target,
   535              value,
   536              0,
   537              hex"1111"
   538          );
   539  
   540          // Message failed.
   541          assertEq(address(l1CrossDomainMessenger).balance, value);
   542          assertEq(address(target).balance, 0);
   543          assertEq(l1CrossDomainMessenger.successfulMessages(hash), false);
   544          assertEq(l1CrossDomainMessenger.failedMessages(hash), true);
   545  
   546          // Make the target not revert anymore.
   547          vm.etch(target, address(0).code);
   548  
   549          // Target should be called with expected data.
   550          vm.expectCall(target, hex"1111");
   551  
   552          // Expect RelayedMessage event to be emitted.
   553          vm.expectEmit(address(l1CrossDomainMessenger));
   554          emit RelayedMessage(hash);
   555  
   556          // Retry the message
   557          vm.prank(address(sender));
   558          l1CrossDomainMessenger.relayMessage(
   559              Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce
   560              sender,
   561              target,
   562              value,
   563              0,
   564              hex"1111"
   565          );
   566  
   567          // Message was successfully relayed.
   568          assertEq(address(l1CrossDomainMessenger).balance, 0);
   569          assertEq(address(target).balance, value);
   570          assertEq(l1CrossDomainMessenger.successfulMessages(hash), true);
   571          assertEq(l1CrossDomainMessenger.failedMessages(hash), true);
   572  
   573          // Expect a revert.
   574          vm.expectRevert("CrossDomainMessenger: message has already been relayed");
   575  
   576          // Retry the message again.
   577          vm.prank(address(sender));
   578          l1CrossDomainMessenger.relayMessage(
   579              Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce
   580              sender,
   581              target,
   582              value,
   583              0,
   584              hex"1111"
   585          );
   586      }
   587  
   588      /// @dev Tests that the relayMessage function is able to relay a message
   589      ///      successfully by calling the target contract.
   590      function test_relayMessage_paused_reverts() external {
   591          vm.prank(superchainConfig.guardian());
   592          superchainConfig.pause("identifier");
   593          vm.expectRevert("CrossDomainMessenger: paused");
   594  
   595          l1CrossDomainMessenger.relayMessage(
   596              Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), // nonce
   597              address(0),
   598              address(0),
   599              0, // value
   600              0,
   601              hex"1111"
   602          );
   603      }
   604  
   605      /// @dev Tests that the superchain config is called by the messengers paused function
   606      function test_pause_callsSuperchainConfig_succeeds() external {
   607          vm.expectCall(address(superchainConfig), abi.encodeWithSelector(SuperchainConfig.paused.selector));
   608          l1CrossDomainMessenger.paused();
   609      }
   610  
   611      /// @dev Tests that changing the superchain config paused status changes the return value of the messenger
   612      function test_pause_matchesSuperchainConfig_succeeds() external {
   613          assertFalse(l1CrossDomainMessenger.paused());
   614          assertEq(l1CrossDomainMessenger.paused(), superchainConfig.paused());
   615  
   616          vm.prank(superchainConfig.guardian());
   617          superchainConfig.pause("identifier");
   618  
   619          assertTrue(l1CrossDomainMessenger.paused());
   620          assertEq(l1CrossDomainMessenger.paused(), superchainConfig.paused());
   621      }
   622  }
   623  
   624  /// @dev A regression test against a reentrancy vulnerability in the CrossDomainMessenger contract, which
   625  ///      was possible by intercepting and sandwhiching a signed Safe Transaction to upgrade it.
   626  contract L1CrossDomainMessenger_ReinitReentryTest is Bridge_Initializer {
   627      bool attacked;
   628  
   629      // Common values used across functions
   630      uint256 constant messageValue = 50;
   631      bytes constant selector = abi.encodeWithSelector(this.reinitAndReenter.selector);
   632      address sender;
   633      bytes32 hash;
   634      address target;
   635  
   636      function setUp() public override {
   637          super.setUp();
   638          target = address(this);
   639          sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;
   640          hash = Hashing.hashCrossDomainMessage(
   641              Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), sender, target, messageValue, 0, selector
   642          );
   643          vm.deal(address(l1CrossDomainMessenger), messageValue * 2);
   644      }
   645  
   646      /// @dev This method will be called by the relayed message, and will attempt to reenter the relayMessage function
   647      ///      exactly once.
   648      function reinitAndReenter() public payable {
   649          // only attempt the attack once
   650          if (!attacked) {
   651              attacked = true;
   652              // set initialized to false
   653              vm.store(address(l1CrossDomainMessenger), 0, bytes32(uint256(0)));
   654  
   655              // call the initializer function
   656              l1CrossDomainMessenger.initialize(SuperchainConfig(superchainConfig), OptimismPortal(optimismPortal));
   657  
   658              // attempt to re-replay the withdrawal
   659              vm.expectEmit(address(l1CrossDomainMessenger));
   660              emit FailedRelayedMessage(hash);
   661              l1CrossDomainMessenger.relayMessage(
   662                  Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), // nonce
   663                  sender,
   664                  target,
   665                  messageValue,
   666                  0,
   667                  selector
   668              );
   669          }
   670      }
   671  
   672      /// @dev Tests that the relayMessage function cannot be reentered by calling the `initialize()` function within the
   673      ///      relayed message.
   674      function test_relayMessage_replayStraddlingReinit_reverts() external {
   675          uint256 balanceBeforeThis = address(this).balance;
   676          uint256 balanceBeforeMessenger = address(l1CrossDomainMessenger).balance;
   677  
   678          // A requisite for the attack is that the message has already been attempted and written to the failedMessages
   679          // mapping, so that it can be replayed.
   680          vm.store(address(l1CrossDomainMessenger), keccak256(abi.encode(hash, 206)), bytes32(uint256(1)));
   681          assertTrue(l1CrossDomainMessenger.failedMessages(hash));
   682  
   683          vm.expectEmit(address(l1CrossDomainMessenger));
   684          emit FailedRelayedMessage(hash);
   685          l1CrossDomainMessenger.relayMessage(
   686              Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), // nonce
   687              sender,
   688              target,
   689              messageValue,
   690              0,
   691              selector
   692          );
   693  
   694          // The message hash is not in the successfulMessages mapping.
   695          assertFalse(l1CrossDomainMessenger.successfulMessages(hash));
   696          // The balance of this contract is unchanged.
   697          assertEq(address(this).balance, balanceBeforeThis);
   698          // The balance of the messenger contract is unchanged.
   699          assertEq(address(l1CrossDomainMessenger).balance, balanceBeforeMessenger);
   700      }
   701  }