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 }