github.com/ethereum-optimism/optimism@v1.7.2/packages/contracts-bedrock/test/L2/CrossDomainOwnable3.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  
     7  // Libraries
     8  import { Hashing } from "src/libraries/Hashing.sol";
     9  import { Encoding } from "src/libraries/Encoding.sol";
    10  import { Bytes32AddressLib } from "@rari-capital/solmate/src/utils/Bytes32AddressLib.sol";
    11  
    12  // Target contract dependencies
    13  import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol";
    14  
    15  // Target contract
    16  import { CrossDomainOwnable3 } from "src/L2/CrossDomainOwnable3.sol";
    17  
    18  contract XDomainSetter3 is CrossDomainOwnable3 {
    19      uint256 public value;
    20  
    21      function set(uint256 _value) external onlyOwner {
    22          value = _value;
    23      }
    24  }
    25  
    26  contract CrossDomainOwnable3_Test is Bridge_Initializer {
    27      XDomainSetter3 setter;
    28  
    29      /// @dev CrossDomainOwnable3.sol transferOwnership event
    30      event OwnershipTransferred(address indexed previousOwner, address indexed newOwner, bool isLocal);
    31  
    32      /// @dev Sets up the test suite.
    33      function setUp() public override {
    34          super.setUp();
    35          vm.prank(alice);
    36          setter = new XDomainSetter3();
    37      }
    38  
    39      /// @dev Tests that the constructor sets the correct variables.
    40      function test_constructor_succeeds() public {
    41          assertEq(setter.owner(), alice);
    42          assertEq(setter.isLocal(), true);
    43      }
    44  
    45      /// @dev Tests that `set` reverts when the caller is not the owner.
    46      function test_localOnlyOwner_notOwner_reverts() public {
    47          vm.prank(bob);
    48          vm.expectRevert("CrossDomainOwnable3: caller is not the owner");
    49          setter.set(1);
    50      }
    51  
    52      /// @dev Tests that `transferOwnership` reverts when the caller is not the owner.
    53      function test_transferOwnership_notOwner_reverts() public {
    54          vm.prank(bob);
    55          vm.expectRevert("CrossDomainOwnable3: caller is not the owner");
    56          setter.transferOwnership({ _owner: bob, _isLocal: true });
    57      }
    58  
    59      /// @dev Tests that the `XDomainSetter3` contract reverts after the ownership
    60      ///      has been transferred to a new owner.
    61      function test_crossDomainOnlyOwner_notOwner_reverts() public {
    62          vm.expectEmit(true, true, true, true);
    63  
    64          // OpenZeppelin Ownable.sol transferOwnership event
    65          emit OwnershipTransferred(alice, alice);
    66  
    67          // CrossDomainOwnable3.sol transferOwnership event
    68          emit OwnershipTransferred(alice, alice, false);
    69  
    70          vm.prank(setter.owner());
    71          setter.transferOwnership({ _owner: alice, _isLocal: false });
    72  
    73          // set the xDomainMsgSender storage slot
    74          bytes32 key = bytes32(uint256(204));
    75          bytes32 value = Bytes32AddressLib.fillLast12Bytes(bob);
    76          vm.store(address(l2CrossDomainMessenger), key, value);
    77  
    78          vm.prank(address(l2CrossDomainMessenger));
    79          vm.expectRevert("CrossDomainOwnable3: caller is not the owner");
    80          setter.set(1);
    81      }
    82  
    83      /// @dev Tests that a relayed message to the `XDomainSetter3` contract reverts
    84      ///      after its ownership has been transferred to a new owner.
    85      function test_crossDomainOnlyOwner_notOwner2_reverts() public {
    86          vm.expectEmit(true, true, true, true);
    87  
    88          // OpenZeppelin Ownable.sol transferOwnership event
    89          emit OwnershipTransferred(alice, alice);
    90  
    91          // CrossDomainOwnable3.sol transferOwnership event
    92          emit OwnershipTransferred(alice, alice, false);
    93  
    94          vm.prank(setter.owner());
    95          setter.transferOwnership({ _owner: alice, _isLocal: false });
    96  
    97          assertEq(setter.isLocal(), false);
    98  
    99          uint240 nonce = 0;
   100          address sender = bob;
   101          address target = address(setter);
   102          uint256 value = 0;
   103          uint256 minGasLimit = 0;
   104          bytes memory message = abi.encodeWithSelector(XDomainSetter3.set.selector, 1);
   105  
   106          bytes32 hash = Hashing.hashCrossDomainMessage(
   107              Encoding.encodeVersionedNonce(nonce, 1), sender, target, value, minGasLimit, message
   108          );
   109  
   110          // It should be a failed message. The revert is caught,
   111          // so we cannot expectRevert here.
   112          vm.expectEmit(true, true, true, true, address(l2CrossDomainMessenger));
   113          emit FailedRelayedMessage(hash);
   114  
   115          vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger)));
   116          l2CrossDomainMessenger.relayMessage(
   117              Encoding.encodeVersionedNonce(nonce, 1), sender, target, value, minGasLimit, message
   118          );
   119  
   120          assertEq(setter.value(), 0);
   121      }
   122  
   123      /// @dev Tests that the `XDomainSetter3` contract reverts for a non-messenger
   124      ///      caller after the ownership has been transferred to a new owner.
   125      function test_crossDomainOnlyOwner_notMessenger_reverts() public {
   126          vm.expectEmit(true, true, true, true);
   127  
   128          // OpenZeppelin Ownable.sol transferOwnership event
   129          emit OwnershipTransferred(alice, alice);
   130  
   131          // CrossDomainOwnable3.sol transferOwnership event
   132          emit OwnershipTransferred(alice, alice, false);
   133  
   134          vm.prank(setter.owner());
   135          setter.transferOwnership({ _owner: alice, _isLocal: false });
   136  
   137          vm.prank(bob);
   138          vm.expectRevert("CrossDomainOwnable3: caller is not the messenger");
   139          setter.set(1);
   140      }
   141  
   142      /// @dev Tests that `transferOwnership` reverts for ownership transfers
   143      ///      to the zero address when set locally.
   144      function test_transferOwnership_zeroAddress_reverts() public {
   145          vm.prank(setter.owner());
   146          vm.expectRevert("CrossDomainOwnable3: new owner is the zero address");
   147          setter.transferOwnership({ _owner: address(0), _isLocal: true });
   148      }
   149  
   150      /// @dev Tests that `transferOwnership` reverts for ownership transfers
   151      ///      to the zero address.
   152      function test_transferOwnership_noLocalZeroAddress_reverts() public {
   153          vm.prank(setter.owner());
   154          vm.expectRevert("Ownable: new owner is the zero address");
   155          setter.transferOwnership(address(0));
   156      }
   157  
   158      /// @dev Tests that `onlyOwner` allows the owner to call a protected
   159      ///      function locally.
   160      function test_localOnlyOwner_succeeds() public {
   161          assertEq(setter.isLocal(), true);
   162          vm.prank(setter.owner());
   163          setter.set(1);
   164          assertEq(setter.value(), 1);
   165      }
   166  
   167      /// @dev Tests that `transferOwnership` succeeds when the caller is the
   168      ///      owner and the ownership is transferred locally.
   169      function test_localTransferOwnership_succeeds() public {
   170          vm.expectEmit(true, true, true, true, address(setter));
   171          emit OwnershipTransferred(alice, bob);
   172          emit OwnershipTransferred(alice, bob, true);
   173  
   174          vm.prank(setter.owner());
   175          setter.transferOwnership({ _owner: bob, _isLocal: true });
   176  
   177          assertEq(setter.isLocal(), true);
   178  
   179          vm.prank(bob);
   180          setter.set(2);
   181          assertEq(setter.value(), 2);
   182      }
   183  
   184      /// @dev The existing transferOwnership(address) method still
   185      ///      exists on the contract.
   186      function test_transferOwnershipNoLocal_succeeds() public {
   187          bool isLocal = setter.isLocal();
   188  
   189          vm.expectEmit(true, true, true, true, address(setter));
   190          emit OwnershipTransferred(alice, bob);
   191  
   192          vm.prank(setter.owner());
   193          setter.transferOwnership(bob);
   194  
   195          // isLocal has not changed
   196          assertEq(setter.isLocal(), isLocal);
   197  
   198          vm.prank(bob);
   199          setter.set(2);
   200          assertEq(setter.value(), 2);
   201      }
   202  
   203      /// @dev Tests that `transferOwnership` succeeds when the caller is the
   204      ///      owner and the ownership is transferred non-locally.
   205      function test_crossDomainTransferOwnership_succeeds() public {
   206          vm.expectEmit(true, true, true, true, address(setter));
   207          emit OwnershipTransferred(alice, bob);
   208          emit OwnershipTransferred(alice, bob, false);
   209  
   210          vm.prank(setter.owner());
   211          setter.transferOwnership({ _owner: bob, _isLocal: false });
   212  
   213          assertEq(setter.isLocal(), false);
   214  
   215          // Simulate the L2 execution where the call is coming from
   216          // the L1CrossDomainMessenger
   217          vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger)));
   218          l2CrossDomainMessenger.relayMessage(
   219              Encoding.encodeVersionedNonce(1, 1),
   220              bob,
   221              address(setter),
   222              0,
   223              0,
   224              abi.encodeWithSelector(XDomainSetter3.set.selector, 2)
   225          );
   226  
   227          assertEq(setter.value(), 2);
   228      }
   229  }