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 }