github.com/ethereum-optimism/optimism@v1.7.2/packages/contracts-bedrock/test/L2/L2CrossDomainMessenger.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  import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol";
     8  
     9  // Libraries
    10  import { Hashing } from "src/libraries/Hashing.sol";
    11  import { Encoding } from "src/libraries/Encoding.sol";
    12  import { Types } from "src/libraries/Types.sol";
    13  
    14  // Target contract dependencies
    15  import { L2CrossDomainMessenger } from "src/L2/L2CrossDomainMessenger.sol";
    16  import { L2ToL1MessagePasser } from "src/L2/L2ToL1MessagePasser.sol";
    17  import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol";
    18  
    19  contract L2CrossDomainMessenger_Test is Bridge_Initializer {
    20      /// @dev Receiver address for testing
    21      address recipient = address(0xabbaacdc);
    22  
    23      /// @dev Tests that the implementation is initialized correctly.
    24      function test_constructor_succeeds() external {
    25          L2CrossDomainMessenger impl =
    26              L2CrossDomainMessenger(EIP1967Helper.getImplementation(deploy.mustGetAddress("L2CrossDomainMessenger")));
    27          assertEq(address(impl.OTHER_MESSENGER()), address(0));
    28          assertEq(address(impl.otherMessenger()), address(0));
    29          assertEq(address(impl.l1CrossDomainMessenger()), address(0));
    30      }
    31  
    32      /// @dev Tests that the proxy is initialized correctly.
    33      function test_initialize_succeeds() external {
    34          assertEq(address(l2CrossDomainMessenger.OTHER_MESSENGER()), address(l1CrossDomainMessenger));
    35          assertEq(address(l2CrossDomainMessenger.otherMessenger()), address(l1CrossDomainMessenger));
    36          assertEq(address(l2CrossDomainMessenger.l1CrossDomainMessenger()), address(l1CrossDomainMessenger));
    37      }
    38  
    39      /// @dev Tests that `messageNonce` can be decoded correctly.
    40      function test_messageVersion_succeeds() external {
    41          (, uint16 version) = Encoding.decodeVersionedNonce(l2CrossDomainMessenger.messageNonce());
    42          assertEq(version, l2CrossDomainMessenger.MESSAGE_VERSION());
    43      }
    44  
    45      /// @dev Tests that `sendMessage` executes successfully.
    46      function test_sendMessage_succeeds() external {
    47          bytes memory xDomainCallData =
    48              Encoding.encodeCrossDomainMessage(l2CrossDomainMessenger.messageNonce(), alice, recipient, 0, 100, hex"ff");
    49          vm.expectCall(
    50              address(l2ToL1MessagePasser),
    51              abi.encodeWithSelector(
    52                  L2ToL1MessagePasser.initiateWithdrawal.selector,
    53                  address(l1CrossDomainMessenger),
    54                  l2CrossDomainMessenger.baseGas(hex"ff", 100),
    55                  xDomainCallData
    56              )
    57          );
    58  
    59          // MessagePassed event
    60          vm.expectEmit(true, true, true, true);
    61          emit MessagePassed(
    62              l2ToL1MessagePasser.messageNonce(),
    63              address(l2CrossDomainMessenger),
    64              address(l1CrossDomainMessenger),
    65              0,
    66              l2CrossDomainMessenger.baseGas(hex"ff", 100),
    67              xDomainCallData,
    68              Hashing.hashWithdrawal(
    69                  Types.WithdrawalTransaction({
    70                      nonce: l2ToL1MessagePasser.messageNonce(),
    71                      sender: address(l2CrossDomainMessenger),
    72                      target: address(l1CrossDomainMessenger),
    73                      value: 0,
    74                      gasLimit: l2CrossDomainMessenger.baseGas(hex"ff", 100),
    75                      data: xDomainCallData
    76                  })
    77              )
    78          );
    79  
    80          vm.prank(alice);
    81          l2CrossDomainMessenger.sendMessage(recipient, hex"ff", uint32(100));
    82      }
    83  
    84      /// @dev Tests that `sendMessage` can be called twice and that
    85      ///      the nonce increments correctly.
    86      function test_sendMessage_twice_succeeds() external {
    87          uint256 nonce = l2CrossDomainMessenger.messageNonce();
    88          l2CrossDomainMessenger.sendMessage(recipient, hex"aa", uint32(500_000));
    89          l2CrossDomainMessenger.sendMessage(recipient, hex"aa", uint32(500_000));
    90          // the nonce increments for each message sent
    91          assertEq(nonce + 2, l2CrossDomainMessenger.messageNonce());
    92      }
    93  
    94      /// @dev Tests that `sendMessage` reverts if the recipient is the zero address.
    95      function test_xDomainSender_senderNotSet_reverts() external {
    96          vm.expectRevert("CrossDomainMessenger: xDomainMessageSender is not set");
    97          l2CrossDomainMessenger.xDomainMessageSender();
    98      }
    99  
   100      /// @dev Tests that `sendMessage` reverts if the message version is not supported.
   101      function test_relayMessage_v2_reverts() external {
   102          address target = address(0xabcd);
   103          address sender = address(l1CrossDomainMessenger);
   104          address caller = AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger));
   105  
   106          // Expect a revert.
   107          vm.expectRevert("CrossDomainMessenger: only version 0 or 1 messages are supported at this time");
   108  
   109          // Try to relay a v2 message.
   110          vm.prank(caller);
   111          l2CrossDomainMessenger.relayMessage(
   112              Encoding.encodeVersionedNonce(0, 2), // nonce
   113              sender,
   114              target,
   115              0, // value
   116              0,
   117              hex"1111"
   118          );
   119      }
   120  
   121      /// @dev Tests that `relayMessage` executes successfully.
   122      function test_relayMessage_succeeds() external {
   123          address target = address(0xabcd);
   124          address sender = address(l1CrossDomainMessenger);
   125          address caller = AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger));
   126  
   127          vm.expectCall(target, hex"1111");
   128  
   129          vm.prank(caller);
   130  
   131          vm.expectEmit(true, true, true, true);
   132  
   133          bytes32 hash =
   134              Hashing.hashCrossDomainMessage(Encoding.encodeVersionedNonce(0, 1), sender, target, 0, 0, hex"1111");
   135  
   136          emit RelayedMessage(hash);
   137  
   138          l2CrossDomainMessenger.relayMessage(
   139              Encoding.encodeVersionedNonce(0, 1), // nonce
   140              sender,
   141              target,
   142              0, // value
   143              0,
   144              hex"1111"
   145          );
   146  
   147          // the message hash is in the successfulMessages mapping
   148          assert(l2CrossDomainMessenger.successfulMessages(hash));
   149          // it is not in the received messages mapping
   150          assertEq(l2CrossDomainMessenger.failedMessages(hash), false);
   151      }
   152  
   153      /// @dev Tests that `relayMessage` reverts if attempting to relay
   154      ///      a message sent to an L1 system contract.
   155      function test_relayMessage_toSystemContract_reverts() external {
   156          address target = address(l2ToL1MessagePasser);
   157          address sender = address(l1CrossDomainMessenger);
   158          address caller = AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger));
   159          bytes memory message = hex"1111";
   160  
   161          vm.prank(caller);
   162          vm.expectRevert("CrossDomainMessenger: message cannot be replayed");
   163          l1CrossDomainMessenger.relayMessage(Encoding.encodeVersionedNonce(0, 1), sender, target, 0, 0, message);
   164      }
   165  
   166      /// @dev Tests that `relayMessage` correctly resets the `xDomainMessageSender`
   167      ///      to the original value after a message is relayed.
   168      function test_xDomainMessageSender_reset_succeeds() external {
   169          vm.expectRevert("CrossDomainMessenger: xDomainMessageSender is not set");
   170          l2CrossDomainMessenger.xDomainMessageSender();
   171  
   172          address caller = AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger));
   173          vm.prank(caller);
   174          l2CrossDomainMessenger.relayMessage(Encoding.encodeVersionedNonce(0, 1), address(0), address(0), 0, 0, hex"");
   175  
   176          vm.expectRevert("CrossDomainMessenger: xDomainMessageSender is not set");
   177          l2CrossDomainMessenger.xDomainMessageSender();
   178      }
   179  
   180      /// @dev Tests that `relayMessage` is able to send a successful call
   181      ///      to the target contract after the first message fails and ETH
   182      ///      gets stuck, but the second message succeeds.
   183      function test_relayMessage_retry_succeeds() external {
   184          address target = address(0xabcd);
   185          address sender = address(l1CrossDomainMessenger);
   186          address caller = AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger));
   187          uint256 value = 100;
   188  
   189          bytes32 hash =
   190              Hashing.hashCrossDomainMessage(Encoding.encodeVersionedNonce(0, 1), sender, target, value, 0, hex"1111");
   191  
   192          vm.etch(target, address(new Reverter()).code);
   193          vm.deal(address(caller), value);
   194          vm.prank(caller);
   195          l2CrossDomainMessenger.relayMessage{ value: value }(
   196              Encoding.encodeVersionedNonce(0, 1), // nonce
   197              sender,
   198              target,
   199              value,
   200              0,
   201              hex"1111"
   202          );
   203  
   204          assertEq(address(l2CrossDomainMessenger).balance, value);
   205          assertEq(address(target).balance, 0);
   206          assertEq(l2CrossDomainMessenger.successfulMessages(hash), false);
   207          assertEq(l2CrossDomainMessenger.failedMessages(hash), true);
   208  
   209          vm.expectEmit(true, true, true, true);
   210  
   211          emit RelayedMessage(hash);
   212  
   213          vm.etch(target, address(0).code);
   214          vm.prank(address(sender));
   215          l2CrossDomainMessenger.relayMessage(
   216              Encoding.encodeVersionedNonce(0, 1), // nonce
   217              sender,
   218              target,
   219              value,
   220              0,
   221              hex"1111"
   222          );
   223  
   224          assertEq(address(l2CrossDomainMessenger).balance, 0);
   225          assertEq(address(target).balance, value);
   226          assertEq(l2CrossDomainMessenger.successfulMessages(hash), true);
   227          assertEq(l2CrossDomainMessenger.failedMessages(hash), true);
   228      }
   229  }