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

     1  // SPDX-License-Identifier: MIT
     2  pragma solidity 0.8.15;
     3  
     4  // Testing utilities
     5  import { stdError } from "forge-std/Test.sol";
     6  import { CommonTest } from "test/setup/CommonTest.sol";
     7  import { NextImpl } from "test/mocks/NextImpl.sol";
     8  import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol";
     9  
    10  // Libraries
    11  import { Types } from "src/libraries/Types.sol";
    12  import { Constants } from "src/libraries/Constants.sol";
    13  
    14  // Target contract dependencies
    15  import { Proxy } from "src/universal/Proxy.sol";
    16  
    17  // Target contract
    18  import { L2OutputOracle } from "src/L1/L2OutputOracle.sol";
    19  
    20  contract L2OutputOracle_constructor_Test is CommonTest {
    21      /// @dev Tests that constructor sets the initial values correctly.
    22      function test_constructor_succeeds() external {
    23          L2OutputOracle oracleImpl = new L2OutputOracle();
    24  
    25          assertEq(oracleImpl.SUBMISSION_INTERVAL(), 1);
    26          assertEq(oracleImpl.submissionInterval(), 1);
    27          assertEq(oracleImpl.L2_BLOCK_TIME(), 1);
    28          assertEq(oracleImpl.l2BlockTime(), 1);
    29          assertEq(oracleImpl.latestBlockNumber(), 0);
    30          assertEq(oracleImpl.startingBlockNumber(), 0);
    31          assertEq(oracleImpl.startingTimestamp(), 0);
    32          assertEq(oracleImpl.PROPOSER(), address(0));
    33          assertEq(oracleImpl.proposer(), address(0));
    34          assertEq(oracleImpl.CHALLENGER(), address(0));
    35          assertEq(oracleImpl.challenger(), address(0));
    36          assertEq(oracleImpl.finalizationPeriodSeconds(), 0);
    37          assertEq(oracleImpl.FINALIZATION_PERIOD_SECONDS(), 0);
    38      }
    39  
    40      /// @dev Tests that the proxy is initialized with the correct values.
    41      function test_initialize_succeeds() external {
    42          address proposer = deploy.cfg().l2OutputOracleProposer();
    43          address challenger = deploy.cfg().l2OutputOracleChallenger();
    44          uint256 submissionInterval = deploy.cfg().l2OutputOracleSubmissionInterval();
    45          uint256 startingBlockNumber = deploy.cfg().l2OutputOracleStartingBlockNumber();
    46          uint256 startingTimestamp = deploy.cfg().l2OutputOracleStartingTimestamp();
    47          uint256 l2BlockTime = deploy.cfg().l2BlockTime();
    48          uint256 finalizationPeriodSeconds = deploy.cfg().finalizationPeriodSeconds();
    49  
    50          assertEq(l2OutputOracle.SUBMISSION_INTERVAL(), submissionInterval);
    51          assertEq(l2OutputOracle.submissionInterval(), submissionInterval);
    52          assertEq(l2OutputOracle.L2_BLOCK_TIME(), l2BlockTime);
    53          assertEq(l2OutputOracle.l2BlockTime(), l2BlockTime);
    54          assertEq(l2OutputOracle.latestBlockNumber(), startingBlockNumber);
    55          assertEq(l2OutputOracle.startingBlockNumber(), startingBlockNumber);
    56          assertEq(l2OutputOracle.startingTimestamp(), startingTimestamp);
    57          assertEq(l2OutputOracle.finalizationPeriodSeconds(), finalizationPeriodSeconds);
    58          assertEq(l2OutputOracle.PROPOSER(), proposer);
    59          assertEq(l2OutputOracle.proposer(), proposer);
    60          assertEq(l2OutputOracle.CHALLENGER(), challenger);
    61          assertEq(l2OutputOracle.FINALIZATION_PERIOD_SECONDS(), finalizationPeriodSeconds);
    62          assertEq(l2OutputOracle.challenger(), challenger);
    63      }
    64  }
    65  
    66  contract L2OutputOracle_getter_Test is CommonTest {
    67      bytes32 proposedOutput1 = keccak256(abi.encode(1));
    68  
    69      /// @dev Tests that `latestBlockNumber` returns the correct value.
    70      function test_latestBlockNumber_succeeds() external {
    71          uint256 proposedNumber = l2OutputOracle.nextBlockNumber();
    72  
    73          // Roll to after the block number we'll propose
    74          warpToProposeTime(proposedNumber);
    75          vm.prank(deploy.cfg().l2OutputOracleProposer());
    76          l2OutputOracle.proposeL2Output(proposedOutput1, proposedNumber, 0, 0);
    77          assertEq(l2OutputOracle.latestBlockNumber(), proposedNumber);
    78      }
    79  
    80      /// @dev Tests that `getL2Output` returns the correct value.
    81      function test_getL2Output_succeeds() external {
    82          uint256 nextBlockNumber = l2OutputOracle.nextBlockNumber();
    83          uint256 nextOutputIndex = l2OutputOracle.nextOutputIndex();
    84          warpToProposeTime(nextBlockNumber);
    85          vm.prank(deploy.cfg().l2OutputOracleProposer());
    86          l2OutputOracle.proposeL2Output(proposedOutput1, nextBlockNumber, 0, 0);
    87  
    88          Types.OutputProposal memory proposal = l2OutputOracle.getL2Output(nextOutputIndex);
    89          assertEq(proposal.outputRoot, proposedOutput1);
    90          assertEq(proposal.timestamp, block.timestamp);
    91  
    92          // The block number is larger than the latest proposed output:
    93          vm.expectRevert(stdError.indexOOBError);
    94          l2OutputOracle.getL2Output(nextOutputIndex + 1);
    95      }
    96  
    97      /// @dev Tests that `getL2OutputIndexAfter` returns the correct value
    98      ///      when the input is the exact block number of the proposal.
    99      function test_getL2OutputIndexAfter_sameBlock_succeeds() external {
   100          bytes32 output1 = keccak256(abi.encode(1));
   101          uint256 nextBlockNumber1 = l2OutputOracle.nextBlockNumber();
   102          warpToProposeTime(nextBlockNumber1);
   103          vm.prank(deploy.cfg().l2OutputOracleProposer());
   104          l2OutputOracle.proposeL2Output(output1, nextBlockNumber1, 0, 0);
   105  
   106          // Querying with exact same block as proposed returns the proposal.
   107          uint256 index1 = l2OutputOracle.getL2OutputIndexAfter(nextBlockNumber1);
   108          assertEq(index1, 0);
   109      }
   110  
   111      /// @dev Tests that `getL2OutputIndexAfter` returns the correct value
   112      ///      when the input is the previous block number of the proposal.
   113      function test_getL2OutputIndexAfter_previousBlock_succeeds() external {
   114          bytes32 output1 = keccak256(abi.encode(1));
   115          uint256 nextBlockNumber1 = l2OutputOracle.nextBlockNumber();
   116          warpToProposeTime(nextBlockNumber1);
   117          vm.prank(deploy.cfg().l2OutputOracleProposer());
   118          l2OutputOracle.proposeL2Output(output1, nextBlockNumber1, 0, 0);
   119  
   120          // Querying with previous block returns the proposal too.
   121          uint256 index1 = l2OutputOracle.getL2OutputIndexAfter(nextBlockNumber1 - 1);
   122          assertEq(index1, 0);
   123      }
   124  
   125      /// @dev Tests that `getL2OutputIndexAfter` returns the correct value.
   126      function test_getL2OutputIndexAfter_multipleOutputsExist_succeeds() external {
   127          bytes32 output1 = keccak256(abi.encode(1));
   128          uint256 nextBlockNumber1 = l2OutputOracle.nextBlockNumber();
   129          warpToProposeTime(nextBlockNumber1);
   130          vm.prank(deploy.cfg().l2OutputOracleProposer());
   131          l2OutputOracle.proposeL2Output(output1, nextBlockNumber1, 0, 0);
   132  
   133          bytes32 output2 = keccak256(abi.encode(2));
   134          uint256 nextBlockNumber2 = l2OutputOracle.nextBlockNumber();
   135          warpToProposeTime(nextBlockNumber2);
   136          vm.prank(deploy.cfg().l2OutputOracleProposer());
   137          l2OutputOracle.proposeL2Output(output2, nextBlockNumber2, 0, 0);
   138  
   139          bytes32 output3 = keccak256(abi.encode(3));
   140          uint256 nextBlockNumber3 = l2OutputOracle.nextBlockNumber();
   141          warpToProposeTime(nextBlockNumber3);
   142          vm.prank(deploy.cfg().l2OutputOracleProposer());
   143          l2OutputOracle.proposeL2Output(output3, nextBlockNumber3, 0, 0);
   144  
   145          bytes32 output4 = keccak256(abi.encode(4));
   146          uint256 nextBlockNumber4 = l2OutputOracle.nextBlockNumber();
   147          warpToProposeTime(nextBlockNumber4);
   148          vm.prank(deploy.cfg().l2OutputOracleProposer());
   149          l2OutputOracle.proposeL2Output(output4, nextBlockNumber4, 0, 0);
   150  
   151          // Querying with a block number between the first and second proposal
   152          uint256 index1 = l2OutputOracle.getL2OutputIndexAfter(nextBlockNumber1 + 1);
   153          assertEq(index1, 1);
   154  
   155          // Querying with a block number between the second and third proposal
   156          uint256 index2 = l2OutputOracle.getL2OutputIndexAfter(nextBlockNumber2 + 1);
   157          assertEq(index2, 2);
   158  
   159          // Querying with a block number between the third and fourth proposal
   160          uint256 index3 = l2OutputOracle.getL2OutputIndexAfter(nextBlockNumber3 + 1);
   161          assertEq(index3, 3);
   162      }
   163  
   164      /// @dev Tests that `getL2OutputIndexAfter` reverts when no output exists.
   165      function test_getL2OutputIndexAfter_noOutputsExis_reverts() external {
   166          vm.expectRevert("L2OutputOracle: cannot get output as no outputs have been proposed yet");
   167          l2OutputOracle.getL2OutputIndexAfter(0);
   168      }
   169  
   170      /// @dev Tests that `nextBlockNumber` returns the correct value.
   171      function test_nextBlockNumber_succeeds() external {
   172          assertEq(
   173              l2OutputOracle.nextBlockNumber(),
   174              // The return value should match this arithmetic
   175              l2OutputOracle.latestBlockNumber() + l2OutputOracle.SUBMISSION_INTERVAL()
   176          );
   177      }
   178  
   179      /// @dev Tests that `computeL2Timestamp` returns the correct value.
   180      function test_computeL2Timestamp_succeeds() external {
   181          uint256 startingBlockNumber = deploy.cfg().l2OutputOracleStartingBlockNumber();
   182          uint256 startingTimestamp = deploy.cfg().l2OutputOracleStartingTimestamp();
   183          uint256 l2BlockTime = deploy.cfg().l2BlockTime();
   184  
   185          // reverts if timestamp is too low
   186          vm.expectRevert(stdError.arithmeticError);
   187          l2OutputOracle.computeL2Timestamp(startingBlockNumber - 1);
   188  
   189          // check timestamp for the very first block
   190          assertEq(l2OutputOracle.computeL2Timestamp(startingBlockNumber), startingTimestamp);
   191  
   192          // check timestamp for the first block after the starting block
   193          assertEq(l2OutputOracle.computeL2Timestamp(startingBlockNumber + 1), startingTimestamp + l2BlockTime);
   194  
   195          // check timestamp for some other block number
   196          assertEq(
   197              l2OutputOracle.computeL2Timestamp(startingBlockNumber + 96024), startingTimestamp + l2BlockTime * 96024
   198          );
   199      }
   200  }
   201  
   202  contract L2OutputOracle_proposeL2Output_Test is CommonTest {
   203      /// @dev Test that `proposeL2Output` succeeds for a valid input
   204      ///      and when a block hash and number are not specified.
   205      function test_proposeL2Output_proposeAnotherOutput_succeeds() public {
   206          proposeAnotherOutput();
   207      }
   208  
   209      /// @dev Tests that `proposeL2Output` succeeds when given valid input and
   210      ///      when a block hash and number are specified for reorg protection.
   211      function test_proposeWithBlockhashAndHeight_succeeds() external {
   212          // Get the number and hash of a previous block in the chain
   213          uint256 prevL1BlockNumber = block.number - 1;
   214          bytes32 prevL1BlockHash = blockhash(prevL1BlockNumber);
   215  
   216          uint256 nextBlockNumber = l2OutputOracle.nextBlockNumber();
   217          warpToProposeTime(nextBlockNumber);
   218          vm.prank(deploy.cfg().l2OutputOracleProposer());
   219          l2OutputOracle.proposeL2Output(nonZeroHash, nextBlockNumber, prevL1BlockHash, prevL1BlockNumber);
   220      }
   221  
   222      /// @dev Tests that `proposeL2Output` reverts when called by a party
   223      ///      that is not the proposer.
   224      function test_proposeL2Output_notProposer_reverts() external {
   225          uint256 nextBlockNumber = l2OutputOracle.nextBlockNumber();
   226          warpToProposeTime(nextBlockNumber);
   227  
   228          vm.prank(address(128));
   229          vm.expectRevert("L2OutputOracle: only the proposer address can propose new outputs");
   230          l2OutputOracle.proposeL2Output(nonZeroHash, nextBlockNumber, 0, 0);
   231      }
   232  
   233      /// @dev Tests that `proposeL2Output` reverts when given a zero blockhash.
   234      function test_proposeL2Output_emptyOutput_reverts() external {
   235          bytes32 outputToPropose = bytes32(0);
   236          uint256 nextBlockNumber = l2OutputOracle.nextBlockNumber();
   237          warpToProposeTime(nextBlockNumber);
   238          vm.prank(deploy.cfg().l2OutputOracleProposer());
   239          vm.expectRevert("L2OutputOracle: L2 output proposal cannot be the zero hash");
   240          l2OutputOracle.proposeL2Output(outputToPropose, nextBlockNumber, 0, 0);
   241      }
   242  
   243      /// @dev Tests that `proposeL2Output` reverts when given a block number
   244      ///      that does not match the next expected block number.
   245      function test_proposeL2Output_unexpectedBlockNumber_reverts() external {
   246          uint256 nextBlockNumber = l2OutputOracle.nextBlockNumber();
   247          warpToProposeTime(nextBlockNumber);
   248          vm.prank(deploy.cfg().l2OutputOracleProposer());
   249          vm.expectRevert("L2OutputOracle: block number must be equal to next expected block number");
   250          l2OutputOracle.proposeL2Output(nonZeroHash, nextBlockNumber - 1, 0, 0);
   251      }
   252  
   253      /// @dev Tests that `proposeL2Output` reverts when given a block number
   254      ///      that has a timestamp in the future.
   255      function test_proposeL2Output_futureTimetamp_reverts() external {
   256          uint256 nextBlockNumber = l2OutputOracle.nextBlockNumber();
   257          uint256 nextTimestamp = l2OutputOracle.computeL2Timestamp(nextBlockNumber);
   258          vm.warp(nextTimestamp);
   259          vm.prank(deploy.cfg().l2OutputOracleProposer());
   260          vm.expectRevert("L2OutputOracle: cannot propose L2 output in the future");
   261          l2OutputOracle.proposeL2Output(nonZeroHash, nextBlockNumber, 0, 0);
   262      }
   263  
   264      /// @dev Tests that `proposeL2Output` reverts when given a block number
   265      ///      whose hash does not match the given block hash.
   266      function test_proposeL2Output_wrongFork_reverts() external {
   267          uint256 nextBlockNumber = l2OutputOracle.nextBlockNumber();
   268          warpToProposeTime(nextBlockNumber);
   269          vm.prank(deploy.cfg().l2OutputOracleProposer());
   270          vm.expectRevert("L2OutputOracle: block hash does not match the hash at the expected height");
   271          l2OutputOracle.proposeL2Output(nonZeroHash, nextBlockNumber, bytes32(uint256(0x01)), block.number);
   272      }
   273  
   274      /// @dev Tests that `proposeL2Output` reverts when given a block number
   275      ///      whose block hash does not match the given block hash.
   276      function test_proposeL2Output_unmatchedBlockhash_reverts() external {
   277          // Move ahead to block 100 so that we can reference historical blocks
   278          vm.roll(100);
   279  
   280          // Get the number and hash of a previous block in the chain
   281          uint256 l1BlockNumber = block.number - 1;
   282          bytes32 l1BlockHash = blockhash(l1BlockNumber);
   283  
   284          uint256 nextBlockNumber = l2OutputOracle.nextBlockNumber();
   285          warpToProposeTime(nextBlockNumber);
   286          vm.prank(deploy.cfg().l2OutputOracleProposer());
   287  
   288          // This will fail when foundry no longer returns zerod block hashes
   289          vm.expectRevert("L2OutputOracle: block hash does not match the hash at the expected height");
   290          l2OutputOracle.proposeL2Output(nonZeroHash, nextBlockNumber, l1BlockHash, l1BlockNumber - 1);
   291      }
   292  }
   293  
   294  contract L2OutputOracle_deleteOutputs_Test is CommonTest {
   295      /// @dev Tests that `deleteL2Outputs` succeeds for a single output.
   296      function test_deleteOutputs_singleOutput_succeeds() external {
   297          proposeAnotherOutput();
   298          proposeAnotherOutput();
   299  
   300          uint256 latestBlockNumber = l2OutputOracle.latestBlockNumber();
   301          uint256 latestOutputIndex = l2OutputOracle.latestOutputIndex();
   302          Types.OutputProposal memory newLatestOutput = l2OutputOracle.getL2Output(latestOutputIndex - 1);
   303  
   304          vm.prank(l2OutputOracle.CHALLENGER());
   305          vm.prank(l2OutputOracle.challenger());
   306          vm.expectEmit(true, true, false, false);
   307          emit OutputsDeleted(latestOutputIndex + 1, latestOutputIndex);
   308          l2OutputOracle.deleteL2Outputs(latestOutputIndex);
   309  
   310          // validate latestBlockNumber has been reduced
   311          uint256 latestBlockNumberAfter = l2OutputOracle.latestBlockNumber();
   312          uint256 latestOutputIndexAfter = l2OutputOracle.latestOutputIndex();
   313          uint256 submissionInterval = deploy.cfg().l2OutputOracleSubmissionInterval();
   314          assertEq(latestBlockNumber - submissionInterval, latestBlockNumberAfter);
   315  
   316          // validate that the new latest output is as expected.
   317          Types.OutputProposal memory proposal = l2OutputOracle.getL2Output(latestOutputIndexAfter);
   318          assertEq(newLatestOutput.outputRoot, proposal.outputRoot);
   319          assertEq(newLatestOutput.timestamp, proposal.timestamp);
   320      }
   321  
   322      /// @dev Tests that `deleteL2Outputs` succeeds for multiple outputs.
   323      function test_deleteOutputs_multipleOutputs_succeeds() external {
   324          proposeAnotherOutput();
   325          proposeAnotherOutput();
   326          proposeAnotherOutput();
   327          proposeAnotherOutput();
   328  
   329          uint256 latestBlockNumber = l2OutputOracle.latestBlockNumber();
   330          uint256 latestOutputIndex = l2OutputOracle.latestOutputIndex();
   331          Types.OutputProposal memory newLatestOutput = l2OutputOracle.getL2Output(latestOutputIndex - 3);
   332  
   333          vm.prank(l2OutputOracle.CHALLENGER());
   334          vm.prank(l2OutputOracle.challenger());
   335          vm.expectEmit(true, true, false, false);
   336          emit OutputsDeleted(latestOutputIndex + 1, latestOutputIndex - 2);
   337          l2OutputOracle.deleteL2Outputs(latestOutputIndex - 2);
   338  
   339          // validate latestBlockNumber has been reduced
   340          uint256 latestBlockNumberAfter = l2OutputOracle.latestBlockNumber();
   341          uint256 latestOutputIndexAfter = l2OutputOracle.latestOutputIndex();
   342          uint256 submissionInterval = deploy.cfg().l2OutputOracleSubmissionInterval();
   343          assertEq(latestBlockNumber - submissionInterval * 3, latestBlockNumberAfter);
   344  
   345          // validate that the new latest output is as expected.
   346          Types.OutputProposal memory proposal = l2OutputOracle.getL2Output(latestOutputIndexAfter);
   347          assertEq(newLatestOutput.outputRoot, proposal.outputRoot);
   348          assertEq(newLatestOutput.timestamp, proposal.timestamp);
   349      }
   350  
   351      /// @dev Tests that `deleteL2Outputs` reverts when not called by the challenger.
   352      function test_deleteL2Outputs_ifNotChallenger_reverts() external {
   353          uint256 latestBlockNumber = l2OutputOracle.latestBlockNumber();
   354  
   355          vm.expectRevert("L2OutputOracle: only the challenger address can delete outputs");
   356          l2OutputOracle.deleteL2Outputs(latestBlockNumber);
   357      }
   358  
   359      /// @dev Tests that `deleteL2Outputs` reverts for a non-existant output index.
   360      function test_deleteL2Outputs_nonExistent_reverts() external {
   361          proposeAnotherOutput();
   362  
   363          uint256 latestBlockNumber = l2OutputOracle.latestBlockNumber();
   364  
   365          vm.prank(l2OutputOracle.CHALLENGER());
   366          vm.prank(l2OutputOracle.challenger());
   367          vm.expectRevert("L2OutputOracle: cannot delete outputs after the latest output index");
   368          l2OutputOracle.deleteL2Outputs(latestBlockNumber + 1);
   369      }
   370  
   371      /// @dev Tests that `deleteL2Outputs` reverts when trying to delete outputs
   372      ///      after the latest output index.
   373      function test_deleteL2Outputs_afterLatest_reverts() external {
   374          proposeAnotherOutput();
   375          proposeAnotherOutput();
   376          proposeAnotherOutput();
   377  
   378          // Delete the latest two outputs
   379          uint256 latestOutputIndex = l2OutputOracle.latestOutputIndex();
   380          vm.prank(l2OutputOracle.CHALLENGER());
   381          vm.prank(l2OutputOracle.challenger());
   382          l2OutputOracle.deleteL2Outputs(latestOutputIndex - 2);
   383  
   384          // Now try to delete the same output again
   385          vm.prank(l2OutputOracle.CHALLENGER());
   386          vm.prank(l2OutputOracle.challenger());
   387          vm.expectRevert("L2OutputOracle: cannot delete outputs after the latest output index");
   388          l2OutputOracle.deleteL2Outputs(latestOutputIndex - 2);
   389      }
   390  
   391      /// @dev Tests that `deleteL2Outputs` reverts for finalized outputs.
   392      function test_deleteL2Outputs_finalized_reverts() external {
   393          proposeAnotherOutput();
   394  
   395          // Warp past the finalization period + 1 second
   396          vm.warp(block.timestamp + l2OutputOracle.FINALIZATION_PERIOD_SECONDS() + 1);
   397  
   398          uint256 latestOutputIndex = l2OutputOracle.latestOutputIndex();
   399  
   400          // Try to delete a finalized output
   401          vm.prank(l2OutputOracle.CHALLENGER());
   402          vm.prank(l2OutputOracle.challenger());
   403          vm.expectRevert("L2OutputOracle: cannot delete outputs that have already been finalized");
   404          l2OutputOracle.deleteL2Outputs(latestOutputIndex);
   405      }
   406  }
   407  
   408  contract L2OutputOracleUpgradeable_Test is CommonTest {
   409      /// @dev Tests that the proxy can be successfully upgraded.
   410      function test_upgrading_succeeds() external {
   411          Proxy proxy = Proxy(deploy.mustGetAddress("L2OutputOracleProxy"));
   412          // Check an unused slot before upgrading.
   413          bytes32 slot21Before = vm.load(address(l2OutputOracle), bytes32(uint256(21)));
   414          assertEq(bytes32(0), slot21Before);
   415  
   416          NextImpl nextImpl = new NextImpl();
   417          vm.startPrank(EIP1967Helper.getAdmin(address(proxy)));
   418          // Reviewer note: the NextImpl() still uses reinitializer. If we want to remove that, we'll need to use a
   419          //   two step upgrade with the Storage lib.
   420          proxy.upgradeToAndCall(address(nextImpl), abi.encodeWithSelector(NextImpl.initialize.selector, 2));
   421          assertEq(proxy.implementation(), address(nextImpl));
   422  
   423          // Verify that the NextImpl contract initialized its values according as expected
   424          bytes32 slot21After = vm.load(address(l2OutputOracle), bytes32(uint256(21)));
   425          bytes32 slot21Expected = NextImpl(address(l2OutputOracle)).slot21Init();
   426          assertEq(slot21Expected, slot21After);
   427      }
   428  
   429      /// @dev Tests that initialize reverts if the submissionInterval is zero.
   430      function test_initialize_submissionInterval_reverts() external {
   431          // Reset the initialized field in the 0th storage slot
   432          // so that initialize can be called again.
   433          vm.store(address(l2OutputOracle), bytes32(uint256(0)), bytes32(uint256(0)));
   434  
   435          uint256 l2BlockTime = deploy.cfg().l2BlockTime();
   436          uint256 startingBlockNumber = deploy.cfg().l2OutputOracleStartingBlockNumber();
   437          uint256 startingTimestamp = deploy.cfg().l2OutputOracleStartingTimestamp();
   438          address proposer = deploy.cfg().l2OutputOracleProposer();
   439          address challenger = deploy.cfg().l2OutputOracleChallenger();
   440          uint256 finalizationPeriodSeconds = deploy.cfg().finalizationPeriodSeconds();
   441  
   442          vm.expectRevert("L2OutputOracle: submission interval must be greater than 0");
   443          l2OutputOracle.initialize({
   444              _submissionInterval: 0,
   445              _l2BlockTime: l2BlockTime,
   446              _startingBlockNumber: startingBlockNumber,
   447              _startingTimestamp: startingTimestamp,
   448              _proposer: proposer,
   449              _challenger: challenger,
   450              _finalizationPeriodSeconds: finalizationPeriodSeconds
   451          });
   452      }
   453  
   454      /// @dev Tests that initialize reverts if the l2BlockTime is invalid.
   455      function test_initialize_l2BlockTimeZero_reverts() external {
   456          // Reset the initialized field in the 0th storage slot
   457          // so that initialize can be called again.
   458          vm.store(address(l2OutputOracle), bytes32(uint256(0)), bytes32(uint256(0)));
   459  
   460          uint256 submissionInterval = deploy.cfg().l2OutputOracleSubmissionInterval();
   461          uint256 startingBlockNumber = deploy.cfg().l2OutputOracleStartingBlockNumber();
   462          uint256 startingTimestamp = deploy.cfg().l2OutputOracleStartingTimestamp();
   463          address proposer = deploy.cfg().l2OutputOracleProposer();
   464          address challenger = deploy.cfg().l2OutputOracleChallenger();
   465          uint256 finalizationPeriodSeconds = deploy.cfg().finalizationPeriodSeconds();
   466  
   467          vm.expectRevert("L2OutputOracle: L2 block time must be greater than 0");
   468          l2OutputOracle.initialize({
   469              _submissionInterval: submissionInterval,
   470              _l2BlockTime: 0,
   471              _startingBlockNumber: startingBlockNumber,
   472              _startingTimestamp: startingTimestamp,
   473              _proposer: proposer,
   474              _challenger: challenger,
   475              _finalizationPeriodSeconds: finalizationPeriodSeconds
   476          });
   477      }
   478  
   479      /// @dev Tests that initialize reverts if the starting timestamp is invalid.
   480      function test_initialize_badTimestamp_reverts() external {
   481          // Reset the initialized field in the 0th storage slot
   482          // so that initialize can be called again.
   483          vm.store(address(l2OutputOracle), bytes32(uint256(0)), bytes32(uint256(0)));
   484  
   485          uint256 submissionInterval = deploy.cfg().l2OutputOracleSubmissionInterval();
   486          uint256 l2BlockTime = deploy.cfg().l2BlockTime();
   487          uint256 startingBlockNumber = deploy.cfg().l2OutputOracleStartingBlockNumber();
   488          address proposer = deploy.cfg().l2OutputOracleProposer();
   489          address challenger = deploy.cfg().l2OutputOracleChallenger();
   490          uint256 finalizationPeriodSeconds = deploy.cfg().finalizationPeriodSeconds();
   491  
   492          vm.expectRevert("L2OutputOracle: starting L2 timestamp must be less than current time");
   493          l2OutputOracle.initialize({
   494              _submissionInterval: submissionInterval,
   495              _l2BlockTime: l2BlockTime,
   496              _startingBlockNumber: startingBlockNumber,
   497              _startingTimestamp: block.timestamp + 1,
   498              _proposer: proposer,
   499              _challenger: challenger,
   500              _finalizationPeriodSeconds: finalizationPeriodSeconds
   501          });
   502      }
   503  }