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

     1  // SPDX-License-Identifier: MIT
     2  pragma solidity 0.8.15;
     3  
     4  // Testing utilities
     5  import { CommonTest } from "test/setup/CommonTest.sol";
     6  import { Reverter } from "test/mocks/Callers.sol";
     7  import { StandardBridge } from "src/universal/StandardBridge.sol";
     8  import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol";
     9  
    10  // Libraries
    11  import { Predeploys } from "src/libraries/Predeploys.sol";
    12  
    13  // Target contract dependencies
    14  import { FeeVault } from "src/universal/FeeVault.sol";
    15  
    16  // Target contract
    17  import { SequencerFeeVault } from "src/L2/SequencerFeeVault.sol";
    18  
    19  contract SequencerFeeVault_Test is CommonTest {
    20      address recipient;
    21  
    22      /// @dev Sets up the test suite.
    23      function setUp() public override {
    24          super.setUp();
    25          recipient = deploy.cfg().sequencerFeeVaultRecipient();
    26      }
    27  
    28      /// @dev Tests that the minimum withdrawal amount is correct.
    29      function test_minWithdrawalAmount_succeeds() external {
    30          assertEq(sequencerFeeVault.MIN_WITHDRAWAL_AMOUNT(), deploy.cfg().sequencerFeeVaultMinimumWithdrawalAmount());
    31      }
    32  
    33      /// @dev Tests that the l1 fee wallet is correct.
    34      function test_constructor_succeeds() external {
    35          assertEq(sequencerFeeVault.l1FeeWallet(), recipient);
    36      }
    37  
    38      /// @dev Tests that the fee vault is able to receive ETH.
    39      function test_receive_succeeds() external {
    40          uint256 balance = address(sequencerFeeVault).balance;
    41  
    42          vm.prank(alice);
    43          (bool success,) = address(sequencerFeeVault).call{ value: 100 }(hex"");
    44  
    45          assertEq(success, true);
    46          assertEq(address(sequencerFeeVault).balance, balance + 100);
    47      }
    48  
    49      /// @dev Tests that `withdraw` reverts if the balance is less than the minimum
    50      ///      withdrawal amount.
    51      function test_withdraw_notEnough_reverts() external {
    52          assert(address(sequencerFeeVault).balance < sequencerFeeVault.MIN_WITHDRAWAL_AMOUNT());
    53  
    54          vm.expectRevert("FeeVault: withdrawal amount must be greater than minimum withdrawal amount");
    55          sequencerFeeVault.withdraw();
    56      }
    57  
    58      /// @dev Tests that `withdraw` successfully initiates a withdrawal to L1.
    59      function test_withdraw_toL1_succeeds() external {
    60          uint256 amount = sequencerFeeVault.MIN_WITHDRAWAL_AMOUNT() + 1;
    61          vm.deal(address(sequencerFeeVault), amount);
    62  
    63          // No ether has been withdrawn yet
    64          assertEq(sequencerFeeVault.totalProcessed(), 0);
    65  
    66          vm.expectEmit(address(Predeploys.SEQUENCER_FEE_WALLET));
    67          emit Withdrawal(address(sequencerFeeVault).balance, sequencerFeeVault.RECIPIENT(), address(this));
    68          vm.expectEmit(address(Predeploys.SEQUENCER_FEE_WALLET));
    69          emit Withdrawal(
    70              address(sequencerFeeVault).balance,
    71              sequencerFeeVault.RECIPIENT(),
    72              address(this),
    73              FeeVault.WithdrawalNetwork.L1
    74          );
    75  
    76          // The entire vault's balance is withdrawn
    77          vm.expectCall(
    78              Predeploys.L2_STANDARD_BRIDGE,
    79              address(sequencerFeeVault).balance,
    80              abi.encodeWithSelector(
    81                  StandardBridge.bridgeETHTo.selector, sequencerFeeVault.l1FeeWallet(), 35_000, bytes("")
    82              )
    83          );
    84  
    85          sequencerFeeVault.withdraw();
    86  
    87          // The withdrawal was successful
    88          assertEq(sequencerFeeVault.totalProcessed(), amount);
    89          assertEq(address(sequencerFeeVault).balance, 0);
    90          assertEq(Predeploys.L2_TO_L1_MESSAGE_PASSER.balance, amount);
    91      }
    92  }
    93  
    94  contract SequencerFeeVault_L2Withdrawal_Test is CommonTest {
    95      /// @dev a cache for the config fee recipient
    96      address recipient;
    97  
    98      /// @dev Sets up the test suite.
    99      function setUp() public override {
   100          super.setUp();
   101  
   102          // Alter the deployment to use WithdrawalNetwork.L2
   103          vm.etch(
   104              EIP1967Helper.getImplementation(Predeploys.SEQUENCER_FEE_WALLET),
   105              address(
   106                  new SequencerFeeVault(
   107                      deploy.cfg().sequencerFeeVaultRecipient(),
   108                      deploy.cfg().sequencerFeeVaultMinimumWithdrawalAmount(),
   109                      FeeVault.WithdrawalNetwork.L2
   110                  )
   111              ).code
   112          );
   113  
   114          recipient = deploy.cfg().sequencerFeeVaultRecipient();
   115      }
   116  
   117      /// @dev Tests that `withdraw` successfully initiates a withdrawal to L2.
   118      function test_withdraw_toL2_succeeds() external {
   119          uint256 amount = sequencerFeeVault.MIN_WITHDRAWAL_AMOUNT() + 1;
   120          vm.deal(address(sequencerFeeVault), amount);
   121  
   122          // No ether has been withdrawn yet
   123          assertEq(sequencerFeeVault.totalProcessed(), 0);
   124  
   125          vm.expectEmit(address(Predeploys.SEQUENCER_FEE_WALLET));
   126          emit Withdrawal(address(sequencerFeeVault).balance, sequencerFeeVault.RECIPIENT(), address(this));
   127          vm.expectEmit(address(Predeploys.SEQUENCER_FEE_WALLET));
   128          emit Withdrawal(
   129              address(sequencerFeeVault).balance,
   130              sequencerFeeVault.RECIPIENT(),
   131              address(this),
   132              FeeVault.WithdrawalNetwork.L2
   133          );
   134  
   135          // The entire vault's balance is withdrawn
   136          vm.expectCall(recipient, address(sequencerFeeVault).balance, bytes(""));
   137  
   138          sequencerFeeVault.withdraw();
   139  
   140          // The withdrawal was successful
   141          assertEq(sequencerFeeVault.totalProcessed(), amount);
   142          assertEq(address(sequencerFeeVault).balance, 0);
   143          assertEq(recipient.balance, amount);
   144      }
   145  
   146      /// @dev Tests that `withdraw` fails if the Recipient reverts. This also serves to simulate
   147      ///     a situation where insufficient gas is provided to the RECIPIENT.
   148      function test_withdraw_toL2recipientReverts_fails() external {
   149          uint256 amount = sequencerFeeVault.MIN_WITHDRAWAL_AMOUNT();
   150  
   151          vm.deal(address(sequencerFeeVault), amount);
   152          // No ether has been withdrawn yet
   153          assertEq(sequencerFeeVault.totalProcessed(), 0);
   154  
   155          // Ensure the RECIPIENT reverts
   156          vm.etch(sequencerFeeVault.RECIPIENT(), type(Reverter).runtimeCode);
   157  
   158          // The entire vault's balance is withdrawn
   159          vm.expectCall(recipient, address(sequencerFeeVault).balance, bytes(""));
   160          vm.expectRevert("FeeVault: failed to send ETH to L2 fee recipient");
   161          sequencerFeeVault.withdraw();
   162          assertEq(sequencerFeeVault.totalProcessed(), 0);
   163      }
   164  }