Commit 7e6eb9b2 authored by Maurelian's avatar Maurelian Committed by GitHub

getL2Output reverts if not found (#2979)

* feat(bedrock): getL2Output reverts if not found

feat(bedrock): Handle error on empty output in Portal

feat(ctb): use isOutputFinalized in finalizeWithdrawalTx

* ctb: Remove extraneous abi encoding

Revert "feat(ctb): use isOutputFinalized in finalizeWithdrawalTx"

This reverts commit 4d4e89d4f624b8cbd95c1ad2800027bfe561c213.

ctb: getL2Output returns the next output for a block

ctb: Fix error message style
parent 8bd7abde
---
'@eth-optimism/contracts-bedrock': patch
---
The output oracle's getL2Output function now reverts when no output is returned
This diff is collapsed.
This diff is collapsed.
...@@ -39,17 +39,17 @@ L1CrossDomainMessenger_Test:testCannot_L1MessengerPause() (gas: 24494) ...@@ -39,17 +39,17 @@ L1CrossDomainMessenger_Test:testCannot_L1MessengerPause() (gas: 24494)
L1CrossDomainMessenger_Test:testCannot_L1MessengerUnpause() (gas: 24530) L1CrossDomainMessenger_Test:testCannot_L1MessengerUnpause() (gas: 24530)
L1CrossDomainMessenger_Test:test_L1MessengerMessageVersion() (gas: 24704) L1CrossDomainMessenger_Test:test_L1MessengerMessageVersion() (gas: 24704)
L1CrossDomainMessenger_Test:test_L1MessengerPause() (gas: 47993) L1CrossDomainMessenger_Test:test_L1MessengerPause() (gas: 47993)
L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageFirstStuckSecondSucceeds() (gas: 201871) L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageFirstStuckSecondSucceeds() (gas: 201937)
L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageRevertsOnReentrancy() (gas: 195009) L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageRevertsOnReentrancy() (gas: 195075)
L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageSucceeds() (gas: 77751) L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageSucceeds() (gas: 77817)
L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageToSystemContract() (gas: 67873) L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageToSystemContract() (gas: 67939)
L1CrossDomainMessenger_Test:test_L1MessengerRelayShouldRevertIfPaused() (gas: 60448) L1CrossDomainMessenger_Test:test_L1MessengerRelayShouldRevertIfPaused() (gas: 60448)
L1CrossDomainMessenger_Test:test_L1MessengerReplayMessageWithValue() (gas: 38160) L1CrossDomainMessenger_Test:test_L1MessengerReplayMessageWithValue() (gas: 38160)
L1CrossDomainMessenger_Test:test_L1MessengerSendMessage() (gas: 298101) L1CrossDomainMessenger_Test:test_L1MessengerSendMessage() (gas: 298101)
L1CrossDomainMessenger_Test:test_L1MessengerTwiceSendMessage() (gas: 1489673) L1CrossDomainMessenger_Test:test_L1MessengerTwiceSendMessage() (gas: 1489673)
L1CrossDomainMessenger_Test:test_L1MessengerUnpause() (gas: 40852) L1CrossDomainMessenger_Test:test_L1MessengerUnpause() (gas: 40852)
L1CrossDomainMessenger_Test:test_L1MessengerXDomainSenderReverts() (gas: 24313) L1CrossDomainMessenger_Test:test_L1MessengerXDomainSenderReverts() (gas: 24313)
L1CrossDomainMessenger_Test:test_L1MessengerxDomainMessageSenderResets() (gas: 86298) L1CrossDomainMessenger_Test:test_L1MessengerxDomainMessageSenderResets() (gas: 86364)
L1StandardBridge_Test:test_depositERC20() (gas: 578548) L1StandardBridge_Test:test_depositERC20() (gas: 578548)
L1StandardBridge_Test:test_depositERC20To() (gas: 580752) L1StandardBridge_Test:test_depositERC20To() (gas: 580752)
L1StandardBridge_Test:test_depositETH() (gas: 372464) L1StandardBridge_Test:test_depositETH() (gas: 372464)
...@@ -76,9 +76,9 @@ L2CrossDomainMessenger_Test:test_L2MessengerTwiceSendMessage() (gas: 133074) ...@@ -76,9 +76,9 @@ L2CrossDomainMessenger_Test:test_L2MessengerTwiceSendMessage() (gas: 133074)
L2CrossDomainMessenger_Test:test_L2MessengerXDomainSenderReverts() (gas: 10612) L2CrossDomainMessenger_Test:test_L2MessengerXDomainSenderReverts() (gas: 10612)
L2CrossDomainMessenger_Test:test_L2MessengerxDomainMessageSenderResets() (gas: 54893) L2CrossDomainMessenger_Test:test_L2MessengerxDomainMessageSenderResets() (gas: 54893)
L2OutputOracleTest:testCannot_ProposeWithUnmatchedBlockhash() (gas: 26829) L2OutputOracleTest:testCannot_ProposeWithUnmatchedBlockhash() (gas: 26829)
L2OutputOracleTest:testCannot_deleteL2Output_ifNotOwner() (gas: 24842) L2OutputOracleTest:testCannot_deleteL2Output_ifNotOwner() (gas: 25097)
L2OutputOracleTest:testCannot_deleteL2Output_withWrongRoot() (gas: 91177) L2OutputOracleTest:testCannot_deleteL2Output_withWrongRoot() (gas: 91432)
L2OutputOracleTest:testCannot_deleteL2Output_withWrongTime() (gas: 87171) L2OutputOracleTest:testCannot_deleteL2Output_withWrongTime() (gas: 87426)
L2OutputOracleTest:testCannot_proposeEmptyOutput() (gas: 24128) L2OutputOracleTest:testCannot_proposeEmptyOutput() (gas: 24128)
L2OutputOracleTest:testCannot_proposeFutureTimetamp() (gas: 26097) L2OutputOracleTest:testCannot_proposeFutureTimetamp() (gas: 26097)
L2OutputOracleTest:testCannot_proposeL2OutputIfNotProposer() (gas: 23564) L2OutputOracleTest:testCannot_proposeL2OutputIfNotProposer() (gas: 23564)
...@@ -86,9 +86,9 @@ L2OutputOracleTest:testCannot_proposeOnWrongFork() (gas: 26424) ...@@ -86,9 +86,9 @@ L2OutputOracleTest:testCannot_proposeOnWrongFork() (gas: 26424)
L2OutputOracleTest:testCannot_proposeUnexpectedBlockNumber() (gas: 25983) L2OutputOracleTest:testCannot_proposeUnexpectedBlockNumber() (gas: 25983)
L2OutputOracleTest:test_changeProposer() (gas: 56052) L2OutputOracleTest:test_changeProposer() (gas: 56052)
L2OutputOracleTest:test_computeL2Timestamp() (gas: 30288) L2OutputOracleTest:test_computeL2Timestamp() (gas: 30288)
L2OutputOracleTest:test_constructor() (gas: 48791) L2OutputOracleTest:test_constructor() (gas: 49046)
L2OutputOracleTest:test_deleteOutput() (gas: 76611) L2OutputOracleTest:test_deleteOutput() (gas: 77223)
L2OutputOracleTest:test_getL2Output() (gas: 82934) L2OutputOracleTest:test_getL2Output() (gas: 88514)
L2OutputOracleTest:test_latestBlockNumber() (gas: 76284) L2OutputOracleTest:test_latestBlockNumber() (gas: 76284)
L2OutputOracleTest:test_nextBlockNumber() (gas: 15232) L2OutputOracleTest:test_nextBlockNumber() (gas: 15232)
L2OutputOracleTest:test_proposeWithBlockhashAndHeight() (gas: 75046) L2OutputOracleTest:test_proposeWithBlockhashAndHeight() (gas: 75046)
...@@ -96,7 +96,7 @@ L2OutputOracleTest:test_proposingAnotherOutput() (gas: 76881) ...@@ -96,7 +96,7 @@ L2OutputOracleTest:test_proposingAnotherOutput() (gas: 76881)
L2OutputOracleTest:test_updateOwner() (gas: 34580) L2OutputOracleTest:test_updateOwner() (gas: 34580)
L2OutputOracleUpgradeable_Test:test_cannotInitImpl() (gas: 19428) L2OutputOracleUpgradeable_Test:test_cannotInitImpl() (gas: 19428)
L2OutputOracleUpgradeable_Test:test_cannotInitProxy() (gas: 24427) L2OutputOracleUpgradeable_Test:test_cannotInitProxy() (gas: 24427)
L2OutputOracleUpgradeable_Test:test_initValuesOnProxy() (gas: 38831) L2OutputOracleUpgradeable_Test:test_initValuesOnProxy() (gas: 39086)
L2OutputOracleUpgradeable_Test:test_upgrading() (gas: 230843) L2OutputOracleUpgradeable_Test:test_upgrading() (gas: 230843)
L2StandardBridge_Test:test_ERC20BridgeFailed_whenLocalTokenIsBridge() (gas: 132769) L2StandardBridge_Test:test_ERC20BridgeFailed_whenLocalTokenIsBridge() (gas: 132769)
L2StandardBridge_Test:test_cannotWithdrawEthWithoutSendingIt() (gas: 21622) L2StandardBridge_Test:test_cannotWithdrawEthWithoutSendingIt() (gas: 21622)
...@@ -133,14 +133,14 @@ OptimismMintableTokenFactory_Test:test_bridge() (gas: 7663) ...@@ -133,14 +133,14 @@ OptimismMintableTokenFactory_Test:test_bridge() (gas: 7663)
OptimismMintableTokenFactory_Test:test_createStandardL2Token() (gas: 1113127) OptimismMintableTokenFactory_Test:test_createStandardL2Token() (gas: 1113127)
OptimismMintableTokenFactory_Test:test_createStandardL2TokenSameTwice() (gas: 2209165) OptimismMintableTokenFactory_Test:test_createStandardL2TokenSameTwice() (gas: 2209165)
OptimismMintableTokenFactory_Test:test_createStandardL2TokenShouldRevertIfRemoteIsZero() (gas: 9398) OptimismMintableTokenFactory_Test:test_createStandardL2TokenShouldRevertIfRemoteIsZero() (gas: 9398)
OptimismPortalUpgradeable_Test:test_cannotInitImpl() (gas: 10708) OptimismPortalUpgradeable_Test:test_cannotInitImpl() (gas: 10686)
OptimismPortalUpgradeable_Test:test_cannotInitProxy() (gas: 15684) OptimismPortalUpgradeable_Test:test_cannotInitProxy() (gas: 15662)
OptimismPortalUpgradeable_Test:test_initValuesOnProxy() (gas: 15967) OptimismPortalUpgradeable_Test:test_initValuesOnProxy() (gas: 15967)
OptimismPortalUpgradeable_Test:test_upgrading() (gas: 230843) OptimismPortalUpgradeable_Test:test_upgrading() (gas: 230843)
OptimismPortal_Test:test_OptimismPortalConstructor() (gas: 17275) OptimismPortal_Test:test_OptimismPortalConstructor() (gas: 17341)
OptimismPortal_Test:test_OptimismPortalContractCreationReverts() (gas: 14215) OptimismPortal_Test:test_OptimismPortalContractCreationReverts() (gas: 14215)
OptimismPortal_Test:test_OptimismPortalReceiveEth() (gas: 127503) OptimismPortal_Test:test_OptimismPortalReceiveEth() (gas: 127503)
OptimismPortal_Test:test_cannotVerifyRecentWithdrawal() (gas: 31946) OptimismPortal_Test:test_cannotFinalizeRecentWithdrawal() (gas: 24754)
OptimismPortal_Test:test_depositTransaction_NoValueContract() (gas: 76654) OptimismPortal_Test:test_depositTransaction_NoValueContract() (gas: 76654)
OptimismPortal_Test:test_depositTransaction_NoValueEOA() (gas: 77108) OptimismPortal_Test:test_depositTransaction_NoValueEOA() (gas: 77108)
OptimismPortal_Test:test_depositTransaction_createWithZeroValueForContract() (gas: 76659) OptimismPortal_Test:test_depositTransaction_createWithZeroValueForContract() (gas: 76659)
...@@ -148,10 +148,10 @@ OptimismPortal_Test:test_depositTransaction_createWithZeroValueForEOA() (gas: 76 ...@@ -148,10 +148,10 @@ OptimismPortal_Test:test_depositTransaction_createWithZeroValueForEOA() (gas: 76
OptimismPortal_Test:test_depositTransaction_withEthValueAndContractContractCreation() (gas: 83680) OptimismPortal_Test:test_depositTransaction_withEthValueAndContractContractCreation() (gas: 83680)
OptimismPortal_Test:test_depositTransaction_withEthValueAndEOAContractCreation() (gas: 75845) OptimismPortal_Test:test_depositTransaction_withEthValueAndEOAContractCreation() (gas: 75845)
OptimismPortal_Test:test_depositTransaction_withEthValueFromContract() (gas: 83384) OptimismPortal_Test:test_depositTransaction_withEthValueFromContract() (gas: 83384)
OptimismPortal_Test:test_depositTransaction_withEthValueFromEOA() (gas: 84154) OptimismPortal_Test:test_depositTransaction_withEthValueFromEOA() (gas: 84132)
OptimismPortal_Test:test_invalidWithdrawalProof() (gas: 45218) OptimismPortal_Test:test_invalidWithdrawalProof() (gas: 37266)
OptimismPortal_Test:test_isOutputFinalized() (gas: 132035) OptimismPortal_Test:test_isBlockFinalized() (gas: 113725)
OptimismPortal_Test:test_simple_isOutputFinalized() (gas: 24019) OptimismPortal_Test:test_simple_isBlockFinalized() (gas: 26652)
Proxy_Test:test_clashingFunctionSignatures() (gas: 101427) Proxy_Test:test_clashingFunctionSignatures() (gas: 101427)
Proxy_Test:test_implementationKey() (gas: 20942) Proxy_Test:test_implementationKey() (gas: 20942)
Proxy_Test:test_implementationProxyCallIfNotAdmin() (gas: 30021) Proxy_Test:test_implementationProxyCallIfNotAdmin() (gas: 30021)
......
...@@ -260,13 +260,35 @@ contract L2OutputOracle is OwnableUpgradeable, Semver { ...@@ -260,13 +260,35 @@ contract L2OutputOracle is OwnableUpgradeable, Semver {
} }
/** /**
* @notice Returns the L2 output proposal given a target L2 block number. * @notice Returns the L2 output proposal associated with a target L2 block number. If the
* Returns a null output proposal if none is found. * L2 block number provided is between checkpoints, this function will rerutn the next
* proposal for the next checkpoint.
* Reverts if the output proposal is either not found, or predates
* the STARTING_BLOCK_NUMBER.
* *
* @param _l2BlockNumber The L2 block number of the target block. * @param _l2BlockNumber The L2 block number of the target block.
*/ */
function getL2Output(uint256 _l2BlockNumber) external view returns (OutputProposal memory) { function getL2Output(uint256 _l2BlockNumber) external view returns (OutputProposal memory) {
return l2Outputs[_l2BlockNumber]; require(
_l2BlockNumber >= STARTING_BLOCK_NUMBER,
"L2OutputOracle: block number cannot be less than the starting block number."
);
// Find the distance between _l2BlockNumber, and the checkpoint block before it.
uint256 offset = (_l2BlockNumber - STARTING_BLOCK_NUMBER) % SUBMISSION_INTERVAL;
// If the offset is zero, then the _l2BlockNumber should be checkpointed.
// Otherwise, we'll look up the next block that will be checkpointed.
uint256 lookupBlockNumber = offset == 0
? _l2BlockNumber
: _l2BlockNumber + (SUBMISSION_INTERVAL - offset);
OutputProposal memory output = l2Outputs[lookupBlockNumber];
require(
output.outputRoot != bytes32(0),
"L2OutputOracle: No output found for that block number."
);
return output;
} }
/** /**
......
...@@ -169,33 +169,28 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver { ...@@ -169,33 +169,28 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver {
} }
/** /**
* @notice Determine if an L2 Output is finalized. * @notice Determine if a given block number is finalized. Reverts if the call to
* L2_ORACLE.getL2Output reverts. Returns a boolean otherwise.
* *
* @param _l2BlockNumber The number of the L2 block. * @param _l2BlockNumber The number of the L2 block.
*/ */
function isBlockFinalized(uint256 _l2BlockNumber) external view returns (bool) {
function isOutputFinalized(uint256 _l2BlockNumber) external view returns (bool) {
L2OutputOracle.OutputProposal memory proposal = L2_ORACLE.getL2Output(_l2BlockNumber); L2OutputOracle.OutputProposal memory proposal = L2_ORACLE.getL2Output(_l2BlockNumber);
if (proposal.outputRoot == bytes32(uint256(0))) { return _isOutputFinalized(proposal);
uint256 interval = L2_ORACLE.SUBMISSION_INTERVAL(); }
uint256 startingBlockNumber = L2_ORACLE.STARTING_BLOCK_NUMBER();
/**
// Prevent underflow * @notice Determine if an L2 Output is finalized.
if (startingBlockNumber > _l2BlockNumber) { *
return false; * @param _proposal The output proposal to check.
} */
function _isOutputFinalized(L2OutputOracle.OutputProposal memory _proposal)
// Find the distance between the _l2BlockNumber, and the checkpoint block before it. internal
uint256 offset = (_l2BlockNumber - startingBlockNumber) % interval; view
// Look up the checkpoint block after it. returns (bool)
proposal = L2_ORACLE.getL2Output(_l2BlockNumber + (interval - offset)); {
// False if that block is not yet proposed. return block.timestamp > _proposal.timestamp + FINALIZATION_PERIOD_SECONDS;
if (proposal.outputRoot == bytes32(uint256(0))) {
return false;
}
}
return block.timestamp > proposal.timestamp + FINALIZATION_PERIOD_SECONDS;
} }
/** /**
...@@ -235,17 +230,15 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver { ...@@ -235,17 +230,15 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver {
"OptimismPortal: you cannot send messages to the portal contract" "OptimismPortal: you cannot send messages to the portal contract"
); );
// Get the output root. // Get the output root. This will fail if there is no
// output root for the given block number.
L2OutputOracle.OutputProposal memory proposal = L2_ORACLE.getL2Output(_l2BlockNumber); L2OutputOracle.OutputProposal memory proposal = L2_ORACLE.getL2Output(_l2BlockNumber);
// Ensure that enough time has passed since the proposal was submitted before allowing a // Ensure that enough time has passed since the proposal was submitted before allowing a
// withdrawal. Under the assumption that the fault proof mechanism is operating correctly, // withdrawal. Under the assumption that the fault proof mechanism is operating correctly,
// we can infer that any withdrawal that has passed the finalization period must be valid // we can infer that any withdrawal that has passed the finalization period must be valid
// and can therefore be operated on. // and can therefore be operated on.
require( require(_isOutputFinalized(proposal), "OptimismPortal: proposal is not yet finalized");
block.timestamp > proposal.timestamp + FINALIZATION_PERIOD_SECONDS,
"OptimismPortal: proposal is not yet finalized"
);
// Verify that the output root can be generated with the elements in the proof. // Verify that the output root can be generated with the elements in the proof.
require( require(
......
...@@ -54,9 +54,18 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { ...@@ -54,9 +54,18 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer {
assertEq(proposal.outputRoot, proposedOutput1); assertEq(proposal.outputRoot, proposedOutput1);
assertEq(proposal.timestamp, block.timestamp); assertEq(proposal.timestamp, block.timestamp);
L2OutputOracle.OutputProposal memory proposal2 = oracle.getL2Output(0); // Handles a block number that is between checkpoints:
assertEq(proposal2.outputRoot, bytes32(0)); proposal = oracle.getL2Output(nextBlockNumber - 1);
assertEq(proposal2.timestamp, 0); assertEq(proposal.outputRoot, proposedOutput1);
assertEq(proposal.timestamp, block.timestamp);
// The block number is too low:
vm.expectRevert("L2OutputOracle: block number cannot be less than the starting block number.");
proposal = oracle.getL2Output(0);
// The block number is larger than the latest proposed output:
vm.expectRevert("L2OutputOracle: No output found for that block number.");
proposal = oracle.getL2Output(nextBlockNumber + 1);
} }
// Test: nextBlockNumber() should return the correct value // Test: nextBlockNumber() should return the correct value
......
...@@ -220,7 +220,7 @@ contract OptimismPortal_Test is Portal_Initializer { ...@@ -220,7 +220,7 @@ contract OptimismPortal_Test is Portal_Initializer {
// TODO: test this deeply // TODO: test this deeply
// function test_verifyWithdrawal() external {} // function test_verifyWithdrawal() external {}
function test_cannotVerifyRecentWithdrawal() external { function test_cannotFinalizeRecentWithdrawal() external {
Hashing.OutputRootProof memory outputRootProof = Hashing Hashing.OutputRootProof memory outputRootProof = Hashing
.OutputRootProof({ .OutputRootProof({
version: bytes32(0), version: bytes32(0),
...@@ -228,12 +228,24 @@ contract OptimismPortal_Test is Portal_Initializer { ...@@ -228,12 +228,24 @@ contract OptimismPortal_Test is Portal_Initializer {
withdrawerStorageRoot: bytes32(0), withdrawerStorageRoot: bytes32(0),
latestBlockhash: bytes32(0) latestBlockhash: bytes32(0)
}); });
// Setup the Oracle to return an output with a recent timestamp
uint256 recentTimestamp = block.timestamp - 1000;
vm.mockCall(
address(op.L2_ORACLE()),
abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),
abi.encode(L2OutputOracle.OutputProposal(bytes32(uint256(1)), recentTimestamp))
);
vm.expectRevert("OptimismPortal: proposal is not yet finalized"); vm.expectRevert("OptimismPortal: proposal is not yet finalized");
op.finalizeWithdrawalTransaction(0, alice, alice, 0, 0, hex"", 0, outputRootProof, hex""); op.finalizeWithdrawalTransaction(0, alice, alice, 0, 0, hex"", 0, outputRootProof, hex"");
} }
function test_invalidWithdrawalProof() external { function test_invalidWithdrawalProof() external {
vm.mockCall(
address(op.L2_ORACLE()),
abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),
abi.encode(L2OutputOracle.OutputProposal(bytes32(uint256(1)), block.timestamp))
);
Hashing.OutputRootProof memory outputRootProof = Hashing Hashing.OutputRootProof memory outputRootProof = Hashing
.OutputRootProof({ .OutputRootProof({
version: bytes32(0), version: bytes32(0),
...@@ -243,17 +255,15 @@ contract OptimismPortal_Test is Portal_Initializer { ...@@ -243,17 +255,15 @@ contract OptimismPortal_Test is Portal_Initializer {
}); });
vm.warp( vm.warp(
oracle.getL2Output( oracle.getL2Output(oracle.latestBlockNumber()).timestamp +
oracle.latestBlockNumber() op.FINALIZATION_PERIOD_SECONDS() + 1
).timestamp
+ op.FINALIZATION_PERIOD_SECONDS()
); );
vm.expectRevert("OptimismPortal: invalid output root proof"); vm.expectRevert("OptimismPortal: invalid output root proof");
op.finalizeWithdrawalTransaction(0, alice, alice, 0, 0, hex"", 0, outputRootProof, hex""); op.finalizeWithdrawalTransaction(0, alice, alice, 0, 0, hex"", 0, outputRootProof, hex"");
} }
function test_simple_isOutputFinalized() external { function test_simple_isBlockFinalized() external {
vm.mockCall( vm.mockCall(
address(op.L2_ORACLE()), address(op.L2_ORACLE()),
abi.encodeWithSelector( abi.encodeWithSelector(
...@@ -262,20 +272,20 @@ contract OptimismPortal_Test is Portal_Initializer { ...@@ -262,20 +272,20 @@ contract OptimismPortal_Test is Portal_Initializer {
abi.encode( abi.encode(
L2OutputOracle.OutputProposal( L2OutputOracle.OutputProposal(
bytes32(uint256(1)), bytes32(uint256(1)),
0 startingBlockNumber
) )
) )
); );
// warp to the finalization period // warp to the finalization period
vm.warp(op.FINALIZATION_PERIOD_SECONDS()); vm.warp(startingBlockNumber + op.FINALIZATION_PERIOD_SECONDS());
assertEq(op.isOutputFinalized(0), false); assertEq(op.isBlockFinalized(startingBlockNumber), false);
// warp past the finalization period // warp past the finalization period
vm.warp(op.FINALIZATION_PERIOD_SECONDS() + 1); vm.warp(startingBlockNumber + op.FINALIZATION_PERIOD_SECONDS() + 1);
assertEq(op.isOutputFinalized(0), true); assertEq(op.isBlockFinalized(startingBlockNumber), true);
} }
function test_isOutputFinalized() external { function test_isBlockFinalized() external {
uint256 checkpoint = oracle.nextBlockNumber(); uint256 checkpoint = oracle.nextBlockNumber();
vm.roll(checkpoint); vm.roll(checkpoint);
vm.warp(oracle.computeL2Timestamp(checkpoint) + 1); vm.warp(oracle.computeL2Timestamp(checkpoint) + 1);
...@@ -286,21 +296,23 @@ contract OptimismPortal_Test is Portal_Initializer { ...@@ -286,21 +296,23 @@ contract OptimismPortal_Test is Portal_Initializer {
uint256 finalizationHorizon = block.timestamp + op.FINALIZATION_PERIOD_SECONDS(); uint256 finalizationHorizon = block.timestamp + op.FINALIZATION_PERIOD_SECONDS();
vm.warp(finalizationHorizon); vm.warp(finalizationHorizon);
// The checkpointed block should not be finalized until 1 second from now. // The checkpointed block should not be finalized until 1 second from now.
assertEq(op.isOutputFinalized(checkpoint), false); assertEq(op.isBlockFinalized(checkpoint), false);
// Nor should a block after it // Nor should a block after it
assertEq(op.isOutputFinalized(checkpoint + 1), false); vm.expectRevert("L2OutputOracle: No output found for that block number.");
assertEq(op.isBlockFinalized(checkpoint + 1), false);
// Nor a block before it, even though the finalization period has passed, there is // Nor a block before it, even though the finalization period has passed, there is
// not yet a checkpoint block on top of it for which that is true. // not yet a checkpoint block on top of it for which that is true.
assertEq(op.isOutputFinalized(checkpoint - 1), false); assertEq(op.isBlockFinalized(checkpoint - 1), false);
// warp past the finalization period // warp past the finalization period
vm.warp(finalizationHorizon + 1); vm.warp(finalizationHorizon + 1);
// It should now be finalized. // It should now be finalized.
assertEq(op.isOutputFinalized(checkpoint), true); assertEq(op.isBlockFinalized(checkpoint), true);
// So should the block before it. // So should the block before it.
assertEq(op.isOutputFinalized(checkpoint - 1), true); assertEq(op.isBlockFinalized(checkpoint - 1), true);
// But not the block after it. // But not the block after it.
assertEq(op.isOutputFinalized(checkpoint + 1), false); vm.expectRevert("L2OutputOracle: No output found for that block number.");
assertEq(op.isBlockFinalized(checkpoint + 1), false);
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment