Commit 6e890faf authored by Mark Tyneway's avatar Mark Tyneway

contracts-bedrock: test deploy script

This updates the tests to use the deploy script to set up the
L1 contracts. This ensures that the tests are testing a setup
as close as possible as to what ends up in production. The
L2 contracts are setup in a unified place but as not set up
behind proxies yet. This has been an issue but should be addressed
when we have the ability to import the output of the L2 genesis
generation script.

Any circleci machines that run `forge build` oom when the machine
is not an xlarge. This means that many jobs need to be bumped up
to that size for them to run until the end.

`CommonTest` is heavily modified and cleaned up. A lot of code was
deleted and a good amount of the code that was added is from moving
things to kwargs sytax from not. Some tests were converted from
being regular tests into fuzz tests.
parent 2743c1a0
......@@ -26,36 +26,36 @@ Bytes_toNibbles_Test:test_toNibbles_expectedResult128Bytes_works() (gas: 78882)
Bytes_toNibbles_Test:test_toNibbles_expectedResult5Bytes_works() (gas: 3992)
Bytes_toNibbles_Test:test_toNibbles_zeroLengthInput_works() (gas: 823)
Constants_Test:test_eip1967Constants_succeeds() (gas: 453)
CrossDomainMessenger_BaseGas_Test:test_baseGas_succeeds() (gas: 20435)
CrossDomainOwnable2_Test:test_onlyOwner_notMessenger_reverts() (gas: 8461)
CrossDomainOwnable2_Test:test_onlyOwner_notOwner2_reverts() (gas: 57494)
CrossDomainOwnable2_Test:test_onlyOwner_notOwner_reverts() (gas: 16610)
CrossDomainOwnable2_Test:test_onlyOwner_succeeds() (gas: 73522)
CrossDomainOwnable3_Test:test_constructor_succeeds() (gas: 10554)
CrossDomainOwnable3_Test:test_crossDomainOnlyOwner_notMessenger_reverts() (gas: 28289)
CrossDomainOwnable3_Test:test_crossDomainOnlyOwner_notOwner2_reverts() (gas: 73970)
CrossDomainOwnable3_Test:test_crossDomainOnlyOwner_notOwner_reverts() (gas: 32000)
CrossDomainOwnable3_Test:test_crossDomainTransferOwnership_succeeds() (gas: 91527)
CrossDomainOwnable3_Test:test_localOnlyOwner_notOwner_reverts() (gas: 13215)
CrossDomainOwnable3_Test:test_localOnlyOwner_succeeds() (gas: 35242)
CrossDomainOwnable3_Test:test_localTransferOwnership_succeeds() (gas: 52084)
CrossDomainOwnable3_Test:test_transferOwnershipNoLocal_succeeds() (gas: 48610)
CrossDomainOwnable3_Test:test_transferOwnership_noLocalZeroAddress_reverts() (gas: 12037)
CrossDomainOwnable3_Test:test_transferOwnership_notOwner_reverts() (gas: 13437)
CrossDomainOwnable3_Test:test_transferOwnership_zeroAddress_reverts() (gas: 12081)
CrossDomainOwnableThroughPortal_Test:test_depositTransaction_crossDomainOwner_succeeds() (gas: 81417)
CrossDomainMessenger_BaseGas_Test:test_baseGas_succeeds() (gas: 20525)
CrossDomainOwnable2_Test:test_onlyOwner_notMessenger_reverts() (gas: 8528)
CrossDomainOwnable2_Test:test_onlyOwner_notOwner2_reverts() (gas: 57518)
CrossDomainOwnable2_Test:test_onlyOwner_notOwner_reverts() (gas: 16655)
CrossDomainOwnable2_Test:test_onlyOwner_succeeds() (gas: 73597)
CrossDomainOwnable3_Test:test_constructor_succeeds() (gas: 10605)
CrossDomainOwnable3_Test:test_crossDomainOnlyOwner_notMessenger_reverts() (gas: 28378)
CrossDomainOwnable3_Test:test_crossDomainOnlyOwner_notOwner2_reverts() (gas: 74058)
CrossDomainOwnable3_Test:test_crossDomainOnlyOwner_notOwner_reverts() (gas: 32111)
CrossDomainOwnable3_Test:test_crossDomainTransferOwnership_succeeds() (gas: 91600)
CrossDomainOwnable3_Test:test_localOnlyOwner_notOwner_reverts() (gas: 13260)
CrossDomainOwnable3_Test:test_localOnlyOwner_succeeds() (gas: 35271)
CrossDomainOwnable3_Test:test_localTransferOwnership_succeeds() (gas: 52158)
CrossDomainOwnable3_Test:test_transferOwnershipNoLocal_succeeds() (gas: 48706)
CrossDomainOwnable3_Test:test_transferOwnership_noLocalZeroAddress_reverts() (gas: 12112)
CrossDomainOwnable3_Test:test_transferOwnership_notOwner_reverts() (gas: 13460)
CrossDomainOwnable3_Test:test_transferOwnership_zeroAddress_reverts() (gas: 12177)
CrossDomainOwnableThroughPortal_Test:test_depositTransaction_crossDomainOwner_succeeds() (gas: 81600)
CrossDomainOwnable_Test:test_onlyOwner_notOwner_reverts() (gas: 10597)
CrossDomainOwnable_Test:test_onlyOwner_succeeds() (gas: 34883)
DelayedVetoable_Getters_Test:test_getters() (gas: 24466)
DelayedVetoable_Getters_TestFail:test_getters_notZeroAddress_reverts() (gas: 36220)
DelayedVetoable_HandleCall_TestFail:test_handleCall_unauthorizedInitiation_reverts() (gas: 21867)
DelayedVetoable_Getters_Test:test_getters() (gas: 24671)
DelayedVetoable_Getters_TestFail:test_getters_notZeroAddress_reverts() (gas: 36263)
DelayedVetoable_HandleCall_TestFail:test_handleCall_unauthorizedInitiation_reverts() (gas: 15190)
DeployerWhitelist_Test:test_owner_succeeds() (gas: 7582)
DeployerWhitelist_Test:test_storageSlots_succeeds() (gas: 33395)
DisputeGameFactory_Owner_Test:test_owner_succeeds() (gas: 12581)
DisputeGameFactory_SetImplementation_Test:test_setImplementation_notOwner_reverts() (gas: 16042)
DisputeGameFactory_SetImplementation_Test:test_setImplementation_succeeds() (gas: 44301)
DisputeGameFactory_TransferOwnership_Test:test_transferOwnership_notOwner_reverts() (gas: 15950)
DisputeGameFactory_TransferOwnership_Test:test_transferOwnership_succeeds() (gas: 18642)
DisputeGameFactory_Owner_Test:test_owner_succeeds() (gas: 12611)
DisputeGameFactory_SetImplementation_Test:test_setImplementation_notOwner_reverts() (gas: 16067)
DisputeGameFactory_SetImplementation_Test:test_setImplementation_succeeds() (gas: 44346)
DisputeGameFactory_TransferOwnership_Test:test_transferOwnership_notOwner_reverts() (gas: 15974)
DisputeGameFactory_TransferOwnership_Test:test_transferOwnership_succeeds() (gas: 18738)
Drippie_Test:test_create_calledTwice_reverts() (gas: 168953)
Drippie_Test:test_create_succeeds() (gas: 183401)
Drippie_Test:test_drip_amount_succeeds() (gas: 285353)
......@@ -89,218 +89,218 @@ FaucetTest:test_nonAdmin_drip_fails() (gas: 262520)
FaucetTest:test_receive_succeeds() (gas: 17401)
FaucetTest:test_withdraw_nonAdmin_reverts() (gas: 13145)
FaucetTest:test_withdraw_succeeds() (gas: 78359)
FaultDisputeGame_ResolvesCorrectly_CorrectRoot1:test_resolvesCorrectly_succeeds() (gas: 660000)
FaultDisputeGame_ResolvesCorrectly_CorrectRoot2:test_resolvesCorrectly_succeeds() (gas: 666860)
FaultDisputeGame_ResolvesCorrectly_CorrectRoot3:test_resolvesCorrectly_succeeds() (gas: 663563)
FaultDisputeGame_ResolvesCorrectly_CorrectRoot4:test_resolvesCorrectly_succeeds() (gas: 666736)
FaultDisputeGame_ResolvesCorrectly_CorrectRoot5:test_resolvesCorrectly_succeeds() (gas: 666049)
FaultDisputeGame_ResolvesCorrectly_IncorrectRoot1:test_resolvesCorrectly_succeeds() (gas: 652764)
FaultDisputeGame_ResolvesCorrectly_IncorrectRoot2:test_resolvesCorrectly_succeeds() (gas: 658252)
FaultDisputeGame_ResolvesCorrectly_IncorrectRoot3:test_resolvesCorrectly_succeeds() (gas: 655614)
FaultDisputeGame_ResolvesCorrectly_IncorrectRoot4:test_resolvesCorrectly_succeeds() (gas: 656552)
FaultDisputeGame_ResolvesCorrectly_IncorrectRoot5:test_resolvesCorrectly_succeeds() (gas: 656003)
FaultDisputeGame_Test:test_addLocalData_static_succeeds() (gas: 642642)
FaultDisputeGame_Test:test_createdAt_succeeds() (gas: 10409)
FaultDisputeGame_Test:test_extraData_succeeds() (gas: 32328)
FaultDisputeGame_Test:test_gameData_succeeds() (gas: 32777)
FaultDisputeGame_ResolvesCorrectly_CorrectRoot1:test_resolvesCorrectly_succeeds() (gas: 660030)
FaultDisputeGame_ResolvesCorrectly_CorrectRoot2:test_resolvesCorrectly_succeeds() (gas: 666890)
FaultDisputeGame_ResolvesCorrectly_CorrectRoot3:test_resolvesCorrectly_succeeds() (gas: 663593)
FaultDisputeGame_ResolvesCorrectly_CorrectRoot4:test_resolvesCorrectly_succeeds() (gas: 666766)
FaultDisputeGame_ResolvesCorrectly_CorrectRoot5:test_resolvesCorrectly_succeeds() (gas: 666079)
FaultDisputeGame_ResolvesCorrectly_IncorrectRoot1:test_resolvesCorrectly_succeeds() (gas: 652788)
FaultDisputeGame_ResolvesCorrectly_IncorrectRoot2:test_resolvesCorrectly_succeeds() (gas: 658276)
FaultDisputeGame_ResolvesCorrectly_IncorrectRoot3:test_resolvesCorrectly_succeeds() (gas: 655638)
FaultDisputeGame_ResolvesCorrectly_IncorrectRoot4:test_resolvesCorrectly_succeeds() (gas: 656576)
FaultDisputeGame_ResolvesCorrectly_IncorrectRoot5:test_resolvesCorrectly_succeeds() (gas: 656027)
FaultDisputeGame_Test:test_addLocalData_static_succeeds() (gas: 642366)
FaultDisputeGame_Test:test_createdAt_succeeds() (gas: 10439)
FaultDisputeGame_Test:test_extraData_succeeds() (gas: 32385)
FaultDisputeGame_Test:test_gameData_succeeds() (gas: 32857)
FaultDisputeGame_Test:test_gameType_succeeds() (gas: 8265)
FaultDisputeGame_Test:test_initialize_correctData_succeeds() (gas: 57646)
FaultDisputeGame_Test:test_initialize_firstOutput_reverts() (gas: 213808)
FaultDisputeGame_Test:test_initialize_l1HeadTooOld_reverts() (gas: 228466)
FaultDisputeGame_Test:test_move_clockCorrectness_succeeds() (gas: 594025)
FaultDisputeGame_Test:test_move_clockTimeExceeded_reverts() (gas: 23175)
FaultDisputeGame_Test:test_move_defendRoot_reverts() (gas: 13300)
FaultDisputeGame_Test:test_move_duplicateClaim_reverts() (gas: 147367)
FaultDisputeGame_Test:test_move_duplicateClaimsDifferentSubgames_succeeds() (gas: 556831)
FaultDisputeGame_Test:test_initialize_correctData_succeeds() (gas: 57761)
FaultDisputeGame_Test:test_initialize_l1HeadTooOld_reverts() (gas: 228488)
FaultDisputeGame_Test:test_move_clockCorrectness_succeeds() (gas: 594267)
FaultDisputeGame_Test:test_move_clockTimeExceeded_reverts() (gas: 23197)
FaultDisputeGame_Test:test_move_defendRoot_reverts() (gas: 13322)
FaultDisputeGame_Test:test_move_duplicateClaim_reverts() (gas: 147390)
FaultDisputeGame_Test:test_move_duplicateClaimsDifferentSubgames_succeeds() (gas: 556832)
FaultDisputeGame_Test:test_move_gameDepthExceeded_reverts() (gas: 585853)
FaultDisputeGame_Test:test_move_gameNotInProgress_reverts() (gas: 10980)
FaultDisputeGame_Test:test_move_nonExistentParent_reverts() (gas: 24644)
FaultDisputeGame_Test:test_move_simpleAttack_succeeds() (gas: 151915)
FaultDisputeGame_Test:test_resolve_challengeContested_succeeds() (gas: 269432)
FaultDisputeGame_Test:test_move_gameNotInProgress_reverts() (gas: 11010)
FaultDisputeGame_Test:test_move_nonExistentParent_reverts() (gas: 24668)
FaultDisputeGame_Test:test_move_simpleAttack_succeeds() (gas: 152008)
FaultDisputeGame_Test:test_resolve_challengeContested_succeeds() (gas: 269473)
FaultDisputeGame_Test:test_resolve_claimAlreadyResolved_reverts() (gas: 272334)
FaultDisputeGame_Test:test_resolve_claimAtMaxDepthAlreadyResolved_reverts() (gas: 586606)
FaultDisputeGame_Test:test_resolve_notInProgress_reverts() (gas: 9754)
FaultDisputeGame_Test:test_resolve_outOfOrderResolution_reverts() (gas: 309015)
FaultDisputeGame_Test:test_resolve_rootContested_succeeds() (gas: 139090)
FaultDisputeGame_Test:test_resolve_rootUncontestedButUnresolved_reverts() (gas: 15884)
FaultDisputeGame_Test:test_resolve_notInProgress_reverts() (gas: 9776)
FaultDisputeGame_Test:test_resolve_outOfOrderResolution_reverts() (gas: 308993)
FaultDisputeGame_Test:test_resolve_rootContested_succeeds() (gas: 139119)
FaultDisputeGame_Test:test_resolve_rootUncontestedButUnresolved_reverts() (gas: 15980)
FaultDisputeGame_Test:test_resolve_rootUncontestedClockNotExpired_succeeds() (gas: 18428)
FaultDisputeGame_Test:test_resolve_rootUncontested_succeeds() (gas: 51410)
FaultDisputeGame_Test:test_resolve_stepReached_succeeds() (gas: 498406)
FaultDisputeGame_Test:test_resolve_teamDeathmatch_succeeds() (gas: 443357)
FaultDisputeGame_Test:test_resolve_rootUncontested_succeeds() (gas: 51484)
FaultDisputeGame_Test:test_resolve_stepReached_succeeds() (gas: 498483)
FaultDisputeGame_Test:test_resolve_teamDeathmatch_succeeds() (gas: 443381)
FaultDisputeGame_Test:test_rootClaim_succeeds() (gas: 8232)
FeeVault_Test:test_constructor_succeeds() (gas: 18185)
GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_0() (gas: 354421)
GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_1() (gas: 2952628)
GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_0() (gas: 542325)
GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_1() (gas: 4054518)
GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_0() (gas: 443561)
GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_1() (gas: 3489288)
GasBenchMark_L1StandardBridge_Finalize:test_finalizeETHWithdrawal_benchmark() (gas: 42714)
GasBenchMark_L2OutputOracle:test_proposeL2Output_benchmark() (gas: 90658)
GasBenchMark_OptimismPortal:test_depositTransaction_benchmark() (gas: 75076)
GasBenchMark_OptimismPortal:test_depositTransaction_benchmark_1() (gas: 75697)
GasBenchMark_OptimismPortal:test_proveWithdrawalTransaction_benchmark() (gas: 143181)
GasPriceOracle_Test:test_baseFee_succeeds() (gas: 8325)
GasPriceOracle_Test:test_decimals_succeeds() (gas: 6167)
GasPriceOracle_Test:test_gasPrice_succeeds() (gas: 8294)
GasPriceOracle_Test:test_l1BaseFee_succeeds() (gas: 10656)
GasPriceOracle_Test:test_overhead_succeeds() (gas: 10636)
GasPriceOracle_Test:test_scalar_succeeds() (gas: 10677)
GasPriceOracle_Test:test_setGasPrice_doesNotExist_reverts() (gas: 5910)
GasPriceOracle_Test:test_setL1BaseFee_doesNotExist_reverts() (gas: 5911)
GovernanceToken_Test:test_approve_succeeds() (gas: 133293)
GovernanceToken_Test:test_burnFrom_succeeds() (gas: 122733)
GovernanceToken_Test:test_burn_succeeds() (gas: 114588)
GovernanceToken_Test:test_constructor_succeeds() (gas: 21298)
GovernanceToken_Test:test_decreaseAllowance_succeeds() (gas: 137008)
GovernanceToken_Test:test_increaseAllowance_succeeds() (gas: 137118)
GovernanceToken_Test:test_mint_fromNotOwner_reverts() (gas: 17030)
GovernanceToken_Test:test_mint_fromOwner_succeeds() (gas: 108592)
GovernanceToken_Test:test_transferFrom_succeeds() (gas: 146273)
GovernanceToken_Test:test_transfer_succeeds() (gas: 138108)
Hashing_hashDepositSource_Test:test_hashDepositSource_succeeds() (gas: 633)
Initializer_Test:test_cannotReinitializeL1_succeeds() (gas: 98390)
FeeVault_Test:test_constructor_baseFeeVault_succeeds() (gas: 17428)
FeeVault_Test:test_constructor_l1FeeVault_succeeds() (gas: 17396)
GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_0() (gas: 354398)
GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_1() (gas: 2952696)
GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_0() (gas: 544879)
GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_1() (gas: 4057119)
GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_0() (gas: 446307)
GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_1() (gas: 3491910)
GasBenchMark_L1StandardBridge_Finalize:test_finalizeETHWithdrawal_benchmark() (gas: 45340)
GasBenchMark_L2OutputOracle:test_proposeL2Output_benchmark() (gas: 88797)
GasBenchMark_OptimismPortal:test_depositTransaction_benchmark() (gas: 68343)
GasBenchMark_OptimismPortal:test_depositTransaction_benchmark_1() (gas: 68922)
GasBenchMark_OptimismPortal:test_proveWithdrawalTransaction_benchmark() (gas: 143347)
GasPriceOracle_Test:test_baseFee_succeeds() (gas: 8392)
GasPriceOracle_Test:test_decimals_succeeds() (gas: 6234)
GasPriceOracle_Test:test_gasPrice_succeeds() (gas: 8340)
GasPriceOracle_Test:test_l1BaseFee_succeeds() (gas: 10657)
GasPriceOracle_Test:test_overhead_succeeds() (gas: 10637)
GasPriceOracle_Test:test_scalar_succeeds() (gas: 10722)
GasPriceOracle_Test:test_setGasPrice_doesNotExist_reverts() (gas: 5956)
GasPriceOracle_Test:test_setL1BaseFee_doesNotExist_reverts() (gas: 5976)
GovernanceToken_Test:test_approve_succeeds() (gas: 138023)
GovernanceToken_Test:test_burnFrom_succeeds() (gas: 127582)
GovernanceToken_Test:test_burn_succeeds() (gas: 119070)
GovernanceToken_Test:test_constructor_succeeds() (gas: 23693)
GovernanceToken_Test:test_decreaseAllowance_succeeds() (gas: 141912)
GovernanceToken_Test:test_increaseAllowance_succeeds() (gas: 142022)
GovernanceToken_Test:test_mint_fromNotOwner_reverts() (gas: 21355)
GovernanceToken_Test:test_mint_fromOwner_succeeds() (gas: 110895)
GovernanceToken_Test:test_transferFrom_succeeds() (gas: 151340)
GovernanceToken_Test:test_transfer_succeeds() (gas: 142867)
Hashing_hashDepositSource_Test:test_hashDepositSource_succeeds() (gas: 700)
Initializer_Test:test_cannotReinitializeL1_succeeds() (gas: 101013)
L1BlockNumberTest:test_fallback_succeeds() (gas: 18655)
L1BlockNumberTest:test_getL1BlockNumber_succeeds() (gas: 10625)
L1BlockNumberTest:test_receive_succeeds() (gas: 25384)
L1BlockTest:test_basefee_succeeds() (gas: 7554)
L1BlockTest:test_hash_succeeds() (gas: 7576)
L1BlockTest:test_number_succeeds() (gas: 7629)
L1BlockTest:test_sequenceNumber_succeeds() (gas: 7630)
L1BlockTest:test_timestamp_succeeds() (gas: 7640)
L1BlockTest:test_updateValues_succeeds() (gas: 60482)
L1CrossDomainMessenger_Test:test_messageVersion_succeeds() (gas: 24781)
L1CrossDomainMessenger_Test:test_relayMessage_legacyOldReplay_reverts() (gas: 49384)
L1CrossDomainMessenger_Test:test_relayMessage_legacyRetryAfterFailureThenSuccess_reverts() (gas: 239657)
L1CrossDomainMessenger_Test:test_relayMessage_legacyRetryAfterFailure_succeeds() (gas: 233416)
L1CrossDomainMessenger_Test:test_relayMessage_legacyRetryAfterSuccess_reverts() (gas: 126344)
L1CrossDomainMessenger_Test:test_relayMessage_legacy_succeeds() (gas: 79599)
L1CrossDomainMessenger_Test:test_relayMessage_retryAfterFailure_succeeds() (gas: 227456)
L1CrossDomainMessenger_Test:test_relayMessage_succeeds() (gas: 76590)
L1CrossDomainMessenger_Test:test_relayMessage_toSystemContract_reverts() (gas: 60779)
L1CrossDomainMessenger_Test:test_relayMessage_v2_reverts() (gas: 12343)
L1CrossDomainMessenger_Test:test_replayMessage_withValue_reverts() (gas: 33133)
L1CrossDomainMessenger_Test:test_sendMessage_succeeds() (gas: 392933)
L1CrossDomainMessenger_Test:test_sendMessage_twice_succeeds() (gas: 1669172)
L1CrossDomainMessenger_Test:test_xDomainMessageSender_reset_succeeds() (gas: 87853)
L1CrossDomainMessenger_Test:test_xDomainSender_notSet_reverts() (gas: 24253)
L1ERC721Bridge_Test:test_bridgeERC721To_localTokenZeroAddress_reverts() (gas: 62686)
L1ERC721Bridge_Test:test_bridgeERC721To_remoteTokenZeroAddress_reverts() (gas: 37285)
L1ERC721Bridge_Test:test_bridgeERC721To_succeeds() (gas: 455269)
L1ERC721Bridge_Test:test_bridgeERC721To_wrongOwner_reverts() (gas: 70997)
L1ERC721Bridge_Test:test_bridgeERC721_fromContract_reverts() (gas: 35681)
L1ERC721Bridge_Test:test_bridgeERC721_localTokenZeroAddress_reverts() (gas: 60561)
L1ERC721Bridge_Test:test_bridgeERC721_remoteTokenZeroAddress_reverts() (gas: 35204)
L1ERC721Bridge_Test:test_bridgeERC721_succeeds() (gas: 454966)
L1ERC721Bridge_Test:test_bridgeERC721_wrongOwner_reverts() (gas: 70823)
L1ERC721Bridge_Test:test_constructor_succeeds() (gas: 18861)
L1ERC721Bridge_Test:test_finalizeBridgeERC721_notEscrowed_reverts() (gas: 29475)
L1ERC721Bridge_Test:test_finalizeBridgeERC721_notFromRemoteMessenger_reverts() (gas: 27220)
L1ERC721Bridge_Test:test_finalizeBridgeERC721_notViaLocalMessenger_reverts() (gas: 23241)
L1ERC721Bridge_Test:test_finalizeBridgeERC721_selfToken_reverts() (gas: 24990)
L1ERC721Bridge_Test:test_finalizeBridgeERC721_succeeds() (gas: 425245)
L1StandardBridge_BridgeETHTo_Test:test_bridgeETHTo_succeeds() (gas: 514756)
L1StandardBridge_BridgeETH_Test:test_bridgeETH_succeeds() (gas: 501934)
L1StandardBridge_DepositERC20To_Test:test_depositERC20To_succeeds() (gas: 720272)
L1StandardBridge_DepositERC20_Test:test_depositERC20_succeeds() (gas: 717849)
L1StandardBridge_DepositERC20_TestFail:test_depositERC20_notEoa_reverts() (gas: 22276)
L1StandardBridge_DepositETHTo_Test:test_depositETHTo_succeeds() (gas: 514789)
L1StandardBridge_DepositETH_Test:test_depositETH_succeeds() (gas: 502006)
L1StandardBridge_DepositETH_TestFail:test_depositETH_notEoa_reverts() (gas: 40759)
L1StandardBridge_FinalizeBridgeETH_Test:test_finalizeBridgeETH_succeeds() (gas: 54102)
L1StandardBridge_FinalizeBridgeETH_TestFail:test_finalizeBridgeETH_incorrectValue_reverts() (gas: 36551)
L1StandardBridge_FinalizeBridgeETH_TestFail:test_finalizeBridgeETH_sendToMessenger_reverts() (gas: 36738)
L1StandardBridge_FinalizeBridgeETH_TestFail:test_finalizeBridgeETH_sendToSelf_reverts() (gas: 36623)
L1StandardBridge_FinalizeERC20Withdrawal_Test:test_finalizeERC20Withdrawal_succeeds() (gas: 498144)
L1StandardBridge_FinalizeERC20Withdrawal_TestFail:test_finalizeERC20Withdrawal_notMessenger_reverts() (gas: 33452)
L1StandardBridge_FinalizeERC20Withdrawal_TestFail:test_finalizeERC20Withdrawal_notOtherBridge_reverts() (gas: 34118)
L1StandardBridge_FinalizeETHWithdrawal_Test:test_finalizeETHWithdrawal_succeeds() (gas: 64673)
L1StandardBridge_Getter_Test:test_getters_succeeds() (gas: 28383)
L1StandardBridge_Initialize_Test:test_initialize_succeeds() (gas: 27239)
L1StandardBridge_Receive_Test:test_receive_succeeds() (gas: 615130)
L2CrossDomainMessenger_Test:test_messageVersion_succeeds() (gas: 8477)
L2CrossDomainMessenger_Test:test_relayMessage_retry_succeeds() (gas: 191078)
L2CrossDomainMessenger_Test:test_relayMessage_succeeds() (gas: 48913)
L2CrossDomainMessenger_Test:test_relayMessage_toSystemContract_reverts() (gas: 31136)
L2CrossDomainMessenger_Test:test_relayMessage_v2_reverts() (gas: 11689)
L2CrossDomainMessenger_Test:test_sendMessage_succeeds() (gas: 123957)
L2CrossDomainMessenger_Test:test_sendMessage_twice_succeeds() (gas: 135812)
L2CrossDomainMessenger_Test:test_xDomainMessageSender_reset_succeeds() (gas: 49230)
L2CrossDomainMessenger_Test:test_xDomainSender_senderNotSet_reverts() (gas: 10590)
L2ERC721Bridge_Test:test_bridgeERC721To_localTokenZeroAddress_reverts() (gas: 31453)
L2ERC721Bridge_Test:test_bridgeERC721To_remoteTokenZeroAddress_reverts() (gas: 26854)
L2ERC721Bridge_Test:test_bridgeERC721To_succeeds() (gas: 157156)
L2ERC721Bridge_Test:test_bridgeERC721To_wrongOwner_reverts() (gas: 34489)
L2ERC721Bridge_Test:test_bridgeERC721_fromContract_reverts() (gas: 27183)
L2ERC721Bridge_Test:test_bridgeERC721_localTokenZeroAddress_reverts() (gas: 29305)
L2ERC721Bridge_Test:test_bridgeERC721_remoteTokenZeroAddress_reverts() (gas: 24641)
L2ERC721Bridge_Test:test_bridgeERC721_succeeds() (gas: 154746)
L2ERC721Bridge_Test:test_bridgeERC721_wrongOwner_reverts() (gas: 34271)
L2ERC721Bridge_Test:test_constructor_succeeds() (gas: 21004)
L2ERC721Bridge_Test:test_finalizeBridgeERC721_alreadyExists_reverts() (gas: 38661)
L2ERC721Bridge_Test:test_finalizeBridgeERC721_interfaceNotCompliant_reverts() (gas: 246925)
L2ERC721Bridge_Test:test_finalizeBridgeERC721_notFromRemoteMessenger_reverts() (gas: 27208)
L2ERC721Bridge_Test:test_finalizeBridgeERC721_notViaLocalMessenger_reverts() (gas: 23274)
L2ERC721Bridge_Test:test_finalizeBridgeERC721_selfToken_reverts() (gas: 27124)
L2ERC721Bridge_Test:test_finalizeBridgeERC721_succeeds() (gas: 179976)
L2OutputOracleUpgradeable_Test:test_initValuesOnImpl_succeeds() (gas: 23902)
L2OutputOracleUpgradeable_Test:test_initValuesOnProxy_succeeds() (gas: 46800)
L2OutputOracleUpgradeable_Test:test_initializeImpl_alreadyInitialized_reverts() (gas: 15216)
L2OutputOracleUpgradeable_Test:test_initializeProxy_alreadyInitialized_reverts() (gas: 20216)
L2OutputOracleUpgradeable_Test:test_upgrading_succeeds() (gas: 187875)
L2OutputOracle_constructor_Test:test_constructor_l2BlockTimeZero_reverts() (gas: 39022)
L2OutputOracle_constructor_Test:test_constructor_submissionInterval_reverts() (gas: 39032)
L2OutputOracle_constructor_Test:test_constructor_succeeds() (gas: 51777)
L2OutputOracle_constructor_Test:test_initialize_badTimestamp_reverts() (gas: 12353)
L2OutputOracle_deleteOutputs_Test:test_deleteL2Outputs_afterLatest_reverts() (gas: 217031)
L2OutputOracle_deleteOutputs_Test:test_deleteL2Outputs_finalized_reverts() (gas: 113258)
L2OutputOracle_deleteOutputs_Test:test_deleteL2Outputs_ifNotChallenger_reverts() (gas: 21018)
L2OutputOracle_deleteOutputs_Test:test_deleteL2Outputs_nonExistent_reverts() (gas: 111651)
L2OutputOracle_deleteOutputs_Test:test_deleteOutputs_multipleOutputs_succeeds() (gas: 307411)
L2OutputOracle_deleteOutputs_Test:test_deleteOutputs_singleOutput_succeeds() (gas: 185564)
L2OutputOracle_getter_Test:test_computeL2Timestamp_succeeds() (gas: 38198)
L2OutputOracle_getter_Test:test_getL2OutputIndexAfter_multipleOutputsExist_succeeds() (gas: 269700)
L2OutputOracle_getter_Test:test_getL2OutputIndexAfter_noOutputsExis_reverts() (gas: 17892)
L2OutputOracle_getter_Test:test_getL2OutputIndexAfter_previousBlock_succeeds() (gas: 98188)
L2OutputOracle_getter_Test:test_getL2OutputIndexAfter_sameBlock_succeeds() (gas: 98096)
L2OutputOracle_getter_Test:test_getL2Output_succeeds() (gas: 104600)
L2OutputOracle_getter_Test:test_latestBlockNumber_succeeds() (gas: 99129)
L2OutputOracle_getter_Test:test_nextBlockNumber_succeeds() (gas: 17447)
L2OutputOracle_proposeL2Output_Test:test_proposeL2Output_emptyOutput_reverts() (gas: 28812)
L2OutputOracle_proposeL2Output_Test:test_proposeL2Output_futureTimetamp_reverts() (gas: 30792)
L2OutputOracle_proposeL2Output_Test:test_proposeL2Output_notProposer_reverts() (gas: 27928)
L2OutputOracle_proposeL2Output_Test:test_proposeL2Output_proposeAnotherOutput_succeeds() (gas: 103242)
L2OutputOracle_proposeL2Output_Test:test_proposeL2Output_unexpectedBlockNumber_reverts() (gas: 30526)
L2OutputOracle_proposeL2Output_Test:test_proposeL2Output_unmatchedBlockhash_reverts() (gas: 31526)
L2OutputOracle_proposeL2Output_Test:test_proposeL2Output_wrongFork_reverts() (gas: 31129)
L2OutputOracle_proposeL2Output_Test:test_proposeWithBlockhashAndHeight_succeeds() (gas: 97442)
L2StandardBridge_BridgeERC20To_Test:test_bridgeERC20To_succeeds() (gas: 392297)
L2StandardBridge_BridgeERC20To_Test:test_withdrawTo_withdrawingERC20_succeeds() (gas: 392530)
L2StandardBridge_BridgeERC20_Test:test_bridgeERC20_succeeds() (gas: 387821)
L2StandardBridge_BridgeERC20_Test:test_bridgeLegacyERC20_succeeds() (gas: 396094)
L2StandardBridge_BridgeERC20_Test:test_withdrawLegacyERC20_succeeds() (gas: 396456)
L2StandardBridge_BridgeERC20_Test:test_withdraw_notEOA_reverts() (gas: 251807)
L2StandardBridge_BridgeERC20_Test:test_withdraw_withdrawingERC20_succeeds() (gas: 388103)
L2StandardBridge_Bridge_Test:test_finalizeBridgeETH_incorrectValue_reverts() (gas: 26132)
L2StandardBridge_Bridge_Test:test_finalizeBridgeETH_sendToMessenger_reverts() (gas: 26400)
L2StandardBridge_Bridge_Test:test_finalizeBridgeETH_sendToSelf_reverts() (gas: 26159)
L2StandardBridge_Bridge_Test:test_finalizeDeposit_depositingERC20_succeeds() (gas: 96091)
L2StandardBridge_Bridge_Test:test_finalizeDeposit_depositingETH_succeeds() (gas: 94945)
L2StandardBridge_FinalizeBridgeETH_Test:test_finalizeBridgeETH_succeeds() (gas: 45528)
L2StandardBridge_Test:test_initialize_succeeds() (gas: 26316)
L2StandardBridge_Test:test_receive_succeeds() (gas: 177125)
L2StandardBridge_Test:test_withdraw_ether_succeeds() (gas: 143366)
L2StandardBridge_Test:test_withdraw_insufficientValue_reverts() (gas: 16552)
LegacyERC20ETH_Test:test_approve_doesNotExist_reverts() (gas: 10702)
LegacyERC20ETH_Test:test_burn_doesNotExist_reverts() (gas: 10637)
LegacyERC20ETH_Test:test_crossDomain_succeeds() (gas: 6341)
LegacyERC20ETH_Test:test_decreaseAllowance_doesNotExist_reverts() (gas: 10724)
LegacyERC20ETH_Test:test_increaseAllowance_doesNotExist_reverts() (gas: 10690)
LegacyERC20ETH_Test:test_metadata_succeeds() (gas: 15420)
LegacyERC20ETH_Test:test_mint_doesNotExist_reverts() (gas: 10627)
LegacyERC20ETH_Test:test_transferFrom_doesNotExist_reverts() (gas: 12957)
LegacyERC20ETH_Test:test_transfer_doesNotExist_reverts() (gas: 10755)
LegacyMessagePasser_Test:test_passMessageToL1_succeeds() (gas: 34524)
L1BlockTest:test_basefee_succeeds() (gas: 7576)
L1BlockTest:test_hash_succeeds() (gas: 7671)
L1BlockTest:test_number_succeeds() (gas: 7651)
L1BlockTest:test_sequenceNumber_succeeds() (gas: 7676)
L1BlockTest:test_timestamp_succeeds() (gas: 7685)
L1BlockTest:test_updateValues_succeeds() (gas: 60549)
L1CrossDomainMessenger_Test:test_messageVersion_succeeds() (gas: 24803)
L1CrossDomainMessenger_Test:test_relayMessage_legacyOldReplay_reverts() (gas: 49430)
L1CrossDomainMessenger_Test:test_relayMessage_legacyRetryAfterFailureThenSuccess_reverts() (gas: 239747)
L1CrossDomainMessenger_Test:test_relayMessage_legacyRetryAfterFailure_succeeds() (gas: 233439)
L1CrossDomainMessenger_Test:test_relayMessage_legacyRetryAfterSuccess_reverts() (gas: 126367)
L1CrossDomainMessenger_Test:test_relayMessage_legacy_succeeds() (gas: 79600)
L1CrossDomainMessenger_Test:test_relayMessage_retryAfterFailure_succeeds() (gas: 227457)
L1CrossDomainMessenger_Test:test_relayMessage_succeeds() (gas: 76613)
L1CrossDomainMessenger_Test:test_relayMessage_toSystemContract_reverts() (gas: 60802)
L1CrossDomainMessenger_Test:test_relayMessage_v2_reverts() (gas: 12410)
L1CrossDomainMessenger_Test:test_replayMessage_withValue_reverts() (gas: 33134)
L1CrossDomainMessenger_Test:test_sendMessage_succeeds() (gas: 392982)
L1CrossDomainMessenger_Test:test_sendMessage_twice_succeeds() (gas: 1669266)
L1CrossDomainMessenger_Test:test_xDomainMessageSender_reset_succeeds() (gas: 87934)
L1CrossDomainMessenger_Test:test_xDomainSender_notSet_reverts() (gas: 24282)
L1ERC721Bridge_Test:test_bridgeERC721To_localTokenZeroAddress_reverts() (gas: 62734)
L1ERC721Bridge_Test:test_bridgeERC721To_remoteTokenZeroAddress_reverts() (gas: 37330)
L1ERC721Bridge_Test:test_bridgeERC721To_succeeds() (gas: 455331)
L1ERC721Bridge_Test:test_bridgeERC721To_wrongOwner_reverts() (gas: 71019)
L1ERC721Bridge_Test:test_bridgeERC721_fromContract_reverts() (gas: 35761)
L1ERC721Bridge_Test:test_bridgeERC721_localTokenZeroAddress_reverts() (gas: 60608)
L1ERC721Bridge_Test:test_bridgeERC721_remoteTokenZeroAddress_reverts() (gas: 35185)
L1ERC721Bridge_Test:test_bridgeERC721_succeeds() (gas: 455030)
L1ERC721Bridge_Test:test_bridgeERC721_wrongOwner_reverts() (gas: 70867)
L1ERC721Bridge_Test:test_constructor_succeeds() (gas: 18927)
L1ERC721Bridge_Test:test_finalizeBridgeERC721_notEscrowed_reverts() (gas: 29495)
L1ERC721Bridge_Test:test_finalizeBridgeERC721_notFromRemoteMessenger_reverts() (gas: 27242)
L1ERC721Bridge_Test:test_finalizeBridgeERC721_notViaLocalMessenger_reverts() (gas: 23283)
L1ERC721Bridge_Test:test_finalizeBridgeERC721_selfToken_reverts() (gas: 25013)
L1ERC721Bridge_Test:test_finalizeBridgeERC721_succeeds() (gas: 425310)
L1StandardBridge_BridgeETHTo_Test:test_bridgeETHTo_succeeds() (gas: 517246)
L1StandardBridge_BridgeETH_Test:test_bridgeETH_succeeds() (gas: 504475)
L1StandardBridge_DepositERC20To_Test:test_depositERC20To_succeeds() (gas: 723482)
L1StandardBridge_DepositERC20_Test:test_depositERC20_succeeds() (gas: 721016)
L1StandardBridge_DepositERC20_TestFail:test_depositERC20_notEoa_reverts() (gas: 24968)
L1StandardBridge_DepositETHTo_Test:test_depositETHTo_succeeds() (gas: 517343)
L1StandardBridge_DepositETH_Test:test_depositETH_succeeds() (gas: 504614)
L1StandardBridge_DepositETH_TestFail:test_depositETH_notEoa_reverts() (gas: 43427)
L1StandardBridge_FinalizeBridgeETH_Test:test_finalizeBridgeETH_succeeds() (gas: 57852)
L1StandardBridge_FinalizeBridgeETH_TestFail:test_finalizeBridgeETH_incorrectValue_reverts() (gas: 40313)
L1StandardBridge_FinalizeBridgeETH_TestFail:test_finalizeBridgeETH_sendToMessenger_reverts() (gas: 40464)
L1StandardBridge_FinalizeBridgeETH_TestFail:test_finalizeBridgeETH_sendToSelf_reverts() (gas: 40350)
L1StandardBridge_FinalizeERC20Withdrawal_Test:test_finalizeERC20Withdrawal_succeeds() (gas: 503477)
L1StandardBridge_FinalizeERC20Withdrawal_TestFail:test_finalizeERC20Withdrawal_notMessenger_reverts() (gas: 37194)
L1StandardBridge_FinalizeERC20Withdrawal_TestFail:test_finalizeERC20Withdrawal_notOtherBridge_reverts() (gas: 37883)
L1StandardBridge_FinalizeETHWithdrawal_Test:test_finalizeETHWithdrawal_succeeds() (gas: 70086)
L1StandardBridge_Getter_Test:test_getters_succeeds() (gas: 32693)
L1StandardBridge_Initialize_Test:test_initialize_succeeds() (gas: 30416)
L1StandardBridge_Receive_Test:test_receive_succeeds() (gas: 617714)
L2CrossDomainMessenger_Test:test_messageVersion_succeeds() (gas: 8521)
L2CrossDomainMessenger_Test:test_relayMessage_retry_succeeds() (gas: 191123)
L2CrossDomainMessenger_Test:test_relayMessage_succeeds() (gas: 48936)
L2CrossDomainMessenger_Test:test_relayMessage_toSystemContract_reverts() (gas: 31159)
L2CrossDomainMessenger_Test:test_relayMessage_v2_reverts() (gas: 11712)
L2CrossDomainMessenger_Test:test_sendMessage_succeeds() (gas: 124025)
L2CrossDomainMessenger_Test:test_sendMessage_twice_succeeds() (gas: 135857)
L2CrossDomainMessenger_Test:test_xDomainMessageSender_reset_succeeds() (gas: 49311)
L2CrossDomainMessenger_Test:test_xDomainSender_senderNotSet_reverts() (gas: 10686)
L2ERC721Bridge_Test:test_bridgeERC721To_localTokenZeroAddress_reverts() (gas: 26476)
L2ERC721Bridge_Test:test_bridgeERC721To_remoteTokenZeroAddress_reverts() (gas: 21837)
L2ERC721Bridge_Test:test_bridgeERC721To_succeeds() (gas: 152170)
L2ERC721Bridge_Test:test_bridgeERC721To_wrongOwner_reverts() (gas: 29472)
L2ERC721Bridge_Test:test_bridgeERC721_fromContract_reverts() (gas: 22228)
L2ERC721Bridge_Test:test_bridgeERC721_localTokenZeroAddress_reverts() (gas: 24332)
L2ERC721Bridge_Test:test_bridgeERC721_remoteTokenZeroAddress_reverts() (gas: 19674)
L2ERC721Bridge_Test:test_bridgeERC721_succeeds() (gas: 149761)
L2ERC721Bridge_Test:test_bridgeERC721_wrongOwner_reverts() (gas: 29304)
L2ERC721Bridge_Test:test_constructor_succeeds() (gas: 14638)
L2ERC721Bridge_Test:test_finalizeBridgeERC721_alreadyExists_reverts() (gas: 33650)
L2ERC721Bridge_Test:test_finalizeBridgeERC721_interfaceNotCompliant_reverts() (gas: 241398)
L2ERC721Bridge_Test:test_finalizeBridgeERC721_notFromRemoteMessenger_reverts() (gas: 22196)
L2ERC721Bridge_Test:test_finalizeBridgeERC721_notViaLocalMessenger_reverts() (gas: 18260)
L2ERC721Bridge_Test:test_finalizeBridgeERC721_selfToken_reverts() (gas: 22091)
L2ERC721Bridge_Test:test_finalizeBridgeERC721_succeeds() (gas: 174492)
L2OutputOracleUpgradeable_Test:test_initValuesOnImpl_succeeds() (gas: 32612)
L2OutputOracleUpgradeable_Test:test_initValuesOnProxy_succeeds() (gas: 56622)
L2OutputOracleUpgradeable_Test:test_initializeImpl_alreadyInitialized_reverts() (gas: 24804)
L2OutputOracleUpgradeable_Test:test_initializeProxy_alreadyInitialized_reverts() (gas: 26357)
L2OutputOracleUpgradeable_Test:test_upgrading_succeeds() (gas: 191207)
L2OutputOracle_constructor_Test:test_constructor_l2BlockTimeZero_reverts() (gas: 44322)
L2OutputOracle_constructor_Test:test_constructor_submissionInterval_reverts() (gas: 44398)
L2OutputOracle_constructor_Test:test_constructor_succeeds() (gas: 61377)
L2OutputOracle_constructor_Test:test_initialize_badTimestamp_reverts() (gas: 12388)
L2OutputOracle_deleteOutputs_Test:test_deleteL2Outputs_afterLatest_reverts() (gas: 226802)
L2OutputOracle_deleteOutputs_Test:test_deleteL2Outputs_finalized_reverts() (gas: 118576)
L2OutputOracle_deleteOutputs_Test:test_deleteL2Outputs_ifNotChallenger_reverts() (gas: 21030)
L2OutputOracle_deleteOutputs_Test:test_deleteL2Outputs_nonExistent_reverts() (gas: 117047)
L2OutputOracle_deleteOutputs_Test:test_deleteOutputs_multipleOutputs_succeeds() (gas: 318177)
L2OutputOracle_deleteOutputs_Test:test_deleteOutputs_singleOutput_succeeds() (gas: 193280)
L2OutputOracle_getter_Test:test_computeL2Timestamp_succeeds() (gas: 44531)
L2OutputOracle_getter_Test:test_getL2OutputIndexAfter_multipleOutputsExist_succeeds() (gas: 277477)
L2OutputOracle_getter_Test:test_getL2OutputIndexAfter_noOutputsExis_reverts() (gas: 17960)
L2OutputOracle_getter_Test:test_getL2OutputIndexAfter_previousBlock_succeeds() (gas: 103519)
L2OutputOracle_getter_Test:test_getL2OutputIndexAfter_sameBlock_succeeds() (gas: 103427)
L2OutputOracle_getter_Test:test_getL2Output_succeeds() (gas: 109954)
L2OutputOracle_getter_Test:test_latestBlockNumber_succeeds() (gas: 104504)
L2OutputOracle_getter_Test:test_nextBlockNumber_succeeds() (gas: 17492)
L2OutputOracle_proposeL2Output_Test:test_proposeL2Output_emptyOutput_reverts() (gas: 34143)
L2OutputOracle_proposeL2Output_Test:test_proposeL2Output_futureTimetamp_reverts() (gas: 34240)
L2OutputOracle_proposeL2Output_Test:test_proposeL2Output_notProposer_reverts() (gas: 26076)
L2OutputOracle_proposeL2Output_Test:test_proposeL2Output_proposeAnotherOutput_succeeds() (gas: 109323)
L2OutputOracle_proposeL2Output_Test:test_proposeL2Output_unexpectedBlockNumber_reverts() (gas: 33945)
L2OutputOracle_proposeL2Output_Test:test_proposeL2Output_unmatchedBlockhash_reverts() (gas: 34946)
L2OutputOracle_proposeL2Output_Test:test_proposeL2Output_wrongFork_reverts() (gas: 34466)
L2OutputOracle_proposeL2Output_Test:test_proposeWithBlockhashAndHeight_succeeds() (gas: 100845)
L2StandardBridge_BridgeERC20To_Test:test_bridgeERC20To_succeeds() (gas: 392348)
L2StandardBridge_BridgeERC20To_Test:test_withdrawTo_withdrawingERC20_succeeds() (gas: 392599)
L2StandardBridge_BridgeERC20_Test:test_bridgeERC20_succeeds() (gas: 387993)
L2StandardBridge_BridgeERC20_Test:test_bridgeLegacyERC20_succeeds() (gas: 396266)
L2StandardBridge_BridgeERC20_Test:test_withdrawLegacyERC20_succeeds() (gas: 396611)
L2StandardBridge_BridgeERC20_Test:test_withdraw_notEOA_reverts() (gas: 251910)
L2StandardBridge_BridgeERC20_Test:test_withdraw_withdrawingERC20_succeeds() (gas: 388275)
L2StandardBridge_Bridge_Test:test_finalizeBridgeETH_incorrectValue_reverts() (gas: 26215)
L2StandardBridge_Bridge_Test:test_finalizeBridgeETH_sendToMessenger_reverts() (gas: 26425)
L2StandardBridge_Bridge_Test:test_finalizeBridgeETH_sendToSelf_reverts() (gas: 26230)
L2StandardBridge_Bridge_Test:test_finalizeDeposit_depositingERC20_succeeds() (gas: 96161)
L2StandardBridge_Bridge_Test:test_finalizeDeposit_depositingETH_succeeds() (gas: 95024)
L2StandardBridge_FinalizeBridgeETH_Test:test_finalizeBridgeETH_succeeds() (gas: 45613)
L2StandardBridge_Test:test_initialize_succeeds() (gas: 28938)
L2StandardBridge_Test:test_receive_succeeds() (gas: 177159)
L2StandardBridge_Test:test_withdraw_ether_succeeds() (gas: 143423)
L2StandardBridge_Test:test_withdraw_insufficientValue_reverts() (gas: 16587)
LegacyERC20ETH_Test:test_approve_doesNotExist_reverts() (gas: 10804)
LegacyERC20ETH_Test:test_burn_doesNotExist_reverts() (gas: 10676)
LegacyERC20ETH_Test:test_crossDomain_succeeds() (gas: 6422)
LegacyERC20ETH_Test:test_decreaseAllowance_doesNotExist_reverts() (gas: 10739)
LegacyERC20ETH_Test:test_increaseAllowance_doesNotExist_reverts() (gas: 10749)
LegacyERC20ETH_Test:test_metadata_succeeds() (gas: 15773)
LegacyERC20ETH_Test:test_mint_doesNotExist_reverts() (gas: 10709)
LegacyERC20ETH_Test:test_transferFrom_doesNotExist_reverts() (gas: 12970)
LegacyERC20ETH_Test:test_transfer_doesNotExist_reverts() (gas: 10793)
LegacyMessagePasser_Test:test_passMessageToL1_succeeds() (gas: 34629)
LibPosition_Test:test_pos_correctness_succeeds() (gas: 38689)
LivenessGuard_CheckAfterExecution_TestFails:test_checkAfterExecution_callerIsNotSafe_revert() (gas: 8531)
LivenessGuard_CheckTx_Test:test_checkTransaction_succeeds() (gas: 233535)
......@@ -329,81 +329,81 @@ LivenessModule_RemoveOwners_TestFail:test_removeOwners_ownerHasShownLivenessRece
LivenessModule_RemoveOwners_TestFail:test_removeOwners_ownerHasSignedRecently_reverts() (gas: 615047)
LivenessModule_RemoveOwners_TestFail:test_removeOwners_swapToFallbackOwner_reverts() (gas: 1278252)
LivenessModule_RemoveOwners_TestFail:test_removeOwners_wrongPreviousOwner_reverts() (gas: 73954)
MIPS_Test:test_add_succeeds() (gas: 122866)
MIPS_Test:test_addiSign_succeeds() (gas: 122857)
MIPS_Test:test_addi_succeeds() (gas: 123054)
MIPS_Test:test_addu_succeeds() (gas: 122908)
MIPS_Test:test_addui_succeeds() (gas: 123116)
MIPS_Test:test_and_succeeds() (gas: 122927)
MIPS_Test:test_andi_succeeds() (gas: 122860)
MIPS_Test:test_beq_succeeds() (gas: 203293)
MIPS_Test:test_bgez_succeeds() (gas: 122153)
MIPS_Test:test_bgtz_succeeds() (gas: 122074)
MIPS_Test:test_blez_succeeds() (gas: 122030)
MIPS_Test:test_bltz_succeeds() (gas: 122173)
MIPS_Test:test_bne_succeeds() (gas: 122239)
MIPS_Test:test_branch_inDelaySlot_fails() (gas: 86448)
MIPS_Test:test_brk_succeeds() (gas: 122543)
MIPS_Test:test_clo_succeeds() (gas: 122595)
MIPS_Test:test_clone_succeeds() (gas: 122496)
MIPS_Test:test_clz_succeeds() (gas: 123066)
MIPS_Test:test_div_succeeds() (gas: 123045)
MIPS_Test:test_divu_succeeds() (gas: 123030)
MIPS_Test:test_exit_succeeds() (gas: 122545)
MIPS_Test:test_fcntl_succeeds() (gas: 204775)
MIPS_Test:test_illegal_instruction_fails() (gas: 91911)
MIPS_Test:test_invalid_root_fails() (gas: 436085)
MIPS_Test:test_jal_nonzeroRegion_succeeds() (gas: 121183)
MIPS_Test:test_jal_succeeds() (gas: 121172)
MIPS_Test:test_jalr_succeeds() (gas: 122291)
MIPS_Test:test_jr_succeeds() (gas: 121985)
MIPS_Test:test_jump_inDelaySlot_fails() (gas: 85816)
MIPS_Test:test_jump_nonzeroRegion_succeeds() (gas: 120927)
MIPS_Test:test_jump_succeeds() (gas: 120857)
MIPS_Test:test_lb_succeeds() (gas: 128098)
MIPS_Test:test_lbu_succeeds() (gas: 127996)
MIPS_Test:test_lh_succeeds() (gas: 128119)
MIPS_Test:test_lhu_succeeds() (gas: 128036)
MIPS_Test:test_ll_succeeds() (gas: 128258)
MIPS_Test:test_lui_succeeds() (gas: 122139)
MIPS_Test:test_lw_succeeds() (gas: 127887)
MIPS_Test:test_lwl_succeeds() (gas: 242938)
MIPS_Test:test_lwr_succeeds() (gas: 243226)
MIPS_Test:test_mfhi_succeeds() (gas: 122500)
MIPS_Test:test_mflo_succeeds() (gas: 122629)
MIPS_Test:test_mmap_succeeds() (gas: 119528)
MIPS_Test:test_movn_succeeds() (gas: 203965)
MIPS_Test:test_movz_succeeds() (gas: 203833)
MIPS_Test:test_mthi_succeeds() (gas: 122544)
MIPS_Test:test_mtlo_succeeds() (gas: 122652)
MIPS_Test:test_mul_succeeds() (gas: 122144)
MIPS_Test:test_mult_succeeds() (gas: 122848)
MIPS_Test:test_multu_succeeds() (gas: 122885)
MIPS_Test:test_nor_succeeds() (gas: 122977)
MIPS_Test:test_or_succeeds() (gas: 122934)
MIPS_Test:test_ori_succeeds() (gas: 122937)
MIPS_Test:test_preimage_read_succeeds() (gas: 235349)
MIPS_Test:test_preimage_write_succeeds() (gas: 127485)
MIPS_Test:test_prestate_exited_succeeds() (gas: 113726)
MIPS_Test:test_sb_succeeds() (gas: 161369)
MIPS_Test:test_sc_succeeds() (gas: 161552)
MIPS_Test:test_sh_succeeds() (gas: 161406)
MIPS_Test:test_sll_succeeds() (gas: 122105)
MIPS_Test:test_sllv_succeeds() (gas: 122334)
MIPS_Test:test_slt_succeeds() (gas: 205160)
MIPS_Test:test_sltu_succeeds() (gas: 123151)
MIPS_Test:test_sra_succeeds() (gas: 122356)
MIPS_Test:test_srav_succeeds() (gas: 122624)
MIPS_Test:test_srl_succeeds() (gas: 122187)
MIPS_Test:test_srlv_succeeds() (gas: 122352)
MIPS_Test:test_step_abi_succeeds() (gas: 58467)
MIPS_Test:test_sub_succeeds() (gas: 122961)
MIPS_Test:test_subu_succeeds() (gas: 122958)
MIPS_Test:test_sw_succeeds() (gas: 161381)
MIPS_Test:test_swl_succeeds() (gas: 161442)
MIPS_Test:test_swr_succeeds() (gas: 161517)
MIPS_Test:test_xor_succeeds() (gas: 122962)
MIPS_Test:test_xori_succeeds() (gas: 123014)
MIPS_Test:test_add_succeeds() (gas: 123021)
MIPS_Test:test_addiSign_succeeds() (gas: 122946)
MIPS_Test:test_addi_succeeds() (gas: 123144)
MIPS_Test:test_addu_succeeds() (gas: 122975)
MIPS_Test:test_addui_succeeds() (gas: 123206)
MIPS_Test:test_and_succeeds() (gas: 122994)
MIPS_Test:test_andi_succeeds() (gas: 122971)
MIPS_Test:test_beq_succeeds() (gas: 203427)
MIPS_Test:test_bgez_succeeds() (gas: 122287)
MIPS_Test:test_bgtz_succeeds() (gas: 122164)
MIPS_Test:test_blez_succeeds() (gas: 122186)
MIPS_Test:test_bltz_succeeds() (gas: 122284)
MIPS_Test:test_bne_succeeds() (gas: 122329)
MIPS_Test:test_branch_inDelaySlot_fails() (gas: 86558)
MIPS_Test:test_brk_succeeds() (gas: 122588)
MIPS_Test:test_clo_succeeds() (gas: 122707)
MIPS_Test:test_clone_succeeds() (gas: 122563)
MIPS_Test:test_clz_succeeds() (gas: 123199)
MIPS_Test:test_div_succeeds() (gas: 123134)
MIPS_Test:test_divu_succeeds() (gas: 123164)
MIPS_Test:test_exit_succeeds() (gas: 122634)
MIPS_Test:test_fcntl_succeeds() (gas: 204864)
MIPS_Test:test_illegal_instruction_fails() (gas: 91978)
MIPS_Test:test_invalid_root_fails() (gas: 436238)
MIPS_Test:test_jal_nonzeroRegion_succeeds() (gas: 121250)
MIPS_Test:test_jal_succeeds() (gas: 121239)
MIPS_Test:test_jalr_succeeds() (gas: 122425)
MIPS_Test:test_jr_succeeds() (gas: 122140)
MIPS_Test:test_jump_inDelaySlot_fails() (gas: 85861)
MIPS_Test:test_jump_nonzeroRegion_succeeds() (gas: 120994)
MIPS_Test:test_jump_succeeds() (gas: 120991)
MIPS_Test:test_lb_succeeds() (gas: 128187)
MIPS_Test:test_lbu_succeeds() (gas: 128107)
MIPS_Test:test_lh_succeeds() (gas: 128251)
MIPS_Test:test_lhu_succeeds() (gas: 128125)
MIPS_Test:test_ll_succeeds() (gas: 128347)
MIPS_Test:test_lui_succeeds() (gas: 122228)
MIPS_Test:test_lw_succeeds() (gas: 127976)
MIPS_Test:test_lwl_succeeds() (gas: 243138)
MIPS_Test:test_lwr_succeeds() (gas: 243427)
MIPS_Test:test_mfhi_succeeds() (gas: 122634)
MIPS_Test:test_mflo_succeeds() (gas: 122718)
MIPS_Test:test_mmap_succeeds() (gas: 119636)
MIPS_Test:test_movn_succeeds() (gas: 204054)
MIPS_Test:test_movz_succeeds() (gas: 203900)
MIPS_Test:test_mthi_succeeds() (gas: 122634)
MIPS_Test:test_mtlo_succeeds() (gas: 122741)
MIPS_Test:test_mul_succeeds() (gas: 122278)
MIPS_Test:test_mult_succeeds() (gas: 122915)
MIPS_Test:test_multu_succeeds() (gas: 122995)
MIPS_Test:test_nor_succeeds() (gas: 123087)
MIPS_Test:test_or_succeeds() (gas: 123046)
MIPS_Test:test_ori_succeeds() (gas: 123026)
MIPS_Test:test_preimage_read_succeeds() (gas: 235502)
MIPS_Test:test_preimage_write_succeeds() (gas: 127574)
MIPS_Test:test_prestate_exited_succeeds() (gas: 113834)
MIPS_Test:test_sb_succeeds() (gas: 161547)
MIPS_Test:test_sc_succeeds() (gas: 161752)
MIPS_Test:test_sh_succeeds() (gas: 161628)
MIPS_Test:test_sll_succeeds() (gas: 122260)
MIPS_Test:test_sllv_succeeds() (gas: 122424)
MIPS_Test:test_slt_succeeds() (gas: 205272)
MIPS_Test:test_sltu_succeeds() (gas: 123285)
MIPS_Test:test_sra_succeeds() (gas: 122490)
MIPS_Test:test_srav_succeeds() (gas: 122758)
MIPS_Test:test_srl_succeeds() (gas: 122276)
MIPS_Test:test_srlv_succeeds() (gas: 122506)
MIPS_Test:test_step_abi_succeeds() (gas: 58532)
MIPS_Test:test_sub_succeeds() (gas: 123029)
MIPS_Test:test_subu_succeeds() (gas: 123092)
MIPS_Test:test_sw_succeeds() (gas: 161626)
MIPS_Test:test_swl_succeeds() (gas: 161643)
MIPS_Test:test_swr_succeeds() (gas: 161718)
MIPS_Test:test_xor_succeeds() (gas: 123029)
MIPS_Test:test_xori_succeeds() (gas: 123082)
MerkleTrie_get_Test:test_get_corruptedProof_reverts() (gas: 5733)
MerkleTrie_get_Test:test_get_extraProofElements_reverts() (gas: 58889)
MerkleTrie_get_Test:test_get_invalidDataRemainder_reverts() (gas: 35845)
......@@ -425,77 +425,77 @@ MerkleTrie_get_Test:test_get_validProof9_succeeds() (gas: 48802)
MerkleTrie_get_Test:test_get_wrongKeyProof_reverts() (gas: 50730)
MerkleTrie_get_Test:test_get_zeroBranchValueLength_reverts() (gas: 41684)
MerkleTrie_get_Test:test_get_zeroLengthKey_reverts() (gas: 3632)
MintManager_constructor_Test:test_constructor_succeeds() (gas: 10579)
MintManager_mint_Test:test_mint_afterPeriodElapsed_succeeds() (gas: 148117)
MintManager_mint_Test:test_mint_beforePeriodElapsed_reverts() (gas: 140433)
MintManager_mint_Test:test_mint_fromNotOwner_reverts() (gas: 10987)
MintManager_mint_Test:test_mint_fromOwner_succeeds() (gas: 137219)
MintManager_mint_Test:test_mint_moreThanCap_reverts() (gas: 142523)
MintManager_upgrade_Test:test_upgrade_fromNotOwner_reverts() (gas: 10974)
MintManager_upgrade_Test:test_upgrade_fromOwner_succeeds() (gas: 23434)
MintManager_upgrade_Test:test_upgrade_toZeroAddress_reverts() (gas: 11003)
MintManager_constructor_Test:test_constructor_succeeds() (gas: 10645)
MintManager_mint_Test:test_mint_afterPeriodElapsed_succeeds() (gas: 148140)
MintManager_mint_Test:test_mint_beforePeriodElapsed_reverts() (gas: 140523)
MintManager_mint_Test:test_mint_fromNotOwner_reverts() (gas: 11010)
MintManager_mint_Test:test_mint_fromOwner_succeeds() (gas: 137330)
MintManager_mint_Test:test_mint_moreThanCap_reverts() (gas: 142590)
MintManager_upgrade_Test:test_upgrade_fromNotOwner_reverts() (gas: 11041)
MintManager_upgrade_Test:test_upgrade_fromOwner_succeeds() (gas: 23509)
MintManager_upgrade_Test:test_upgrade_toZeroAddress_reverts() (gas: 11070)
Multichain:test_script_succeeds() (gas: 3078)
OptimismMintableERC20_Test:test_bridge_succeeds() (gas: 7621)
OptimismMintableERC20_Test:test_burn_notBridge_reverts() (gas: 11164)
OptimismMintableERC20_Test:test_burn_succeeds() (gas: 50996)
OptimismMintableERC20_Test:test_erc165_supportsInterface_succeeds() (gas: 7787)
OptimismMintableERC20_Test:test_l1Token_succeeds() (gas: 7621)
OptimismMintableERC20_Test:test_l2Bridge_succeeds() (gas: 7621)
OptimismMintableERC20_Test:test_legacy_succeeds() (gas: 14322)
OptimismMintableERC20_Test:test_mint_notBridge_reverts() (gas: 11165)
OptimismMintableERC20_Test:test_mint_succeeds() (gas: 63544)
OptimismMintableERC20_Test:test_remoteToken_succeeds() (gas: 7667)
OptimismMintableERC721Factory_Test:test_constructor_succeeds() (gas: 8381)
OptimismMintableERC721Factory_Test:test_createOptimismMintableERC721_sameTwice_reverts() (gas: 8937393460516800045)
OptimismMintableERC721Factory_Test:test_createOptimismMintableERC721_succeeds() (gas: 2316169)
OptimismMintableERC721Factory_Test:test_createOptimismMintableERC721_zeroRemoteToken_reverts() (gas: 9493)
OptimismMintableERC721_Test:test_burn_notBridge_reverts() (gas: 136966)
OptimismMintableERC721_Test:test_burn_succeeds() (gas: 118832)
OptimismMintableERC721_Test:test_constructor_succeeds() (gas: 24162)
OptimismMintableERC721_Test:test_safeMint_notBridge_reverts() (gas: 11121)
OptimismMintableERC721_Test:test_safeMint_succeeds() (gas: 140547)
OptimismMintableERC721_Test:test_supportsInterfaces_succeeds() (gas: 9005)
OptimismMintableERC721_Test:test_tokenURI_succeeds() (gas: 163441)
OptimismMintableTokenFactory_Test:test_bridge_succeeds() (gas: 9760)
OptimismMintableTokenFactory_Test:test_createStandardL2TokenWithDecimals_succeeds() (gas: 1142536)
OptimismMintableTokenFactory_Test:test_createStandardL2Token_remoteIsZero_reverts() (gas: 9570)
OptimismMintableTokenFactory_Test:test_createStandardL2Token_sameTwice_reverts() (gas: 8937393460516764385)
OptimismMintableTokenFactory_Test:test_createStandardL2Token_succeeds() (gas: 1142527)
OptimismPortalUpgradeable_Test:test_initialize_cannotInitImpl_reverts() (gas: 11178)
OptimismPortalUpgradeable_Test:test_initialize_cannotInitProxy_reverts() (gas: 16111)
OptimismPortalUpgradeable_Test:test_params_initValuesOnProxy_succeeds() (gas: 26781)
OptimismPortalUpgradeable_Test:test_upgradeToAndCall_upgrading_succeeds() (gas: 191521)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifOutputRootChanges_reverts() (gas: 178667)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifOutputTimestampIsNotFinalized_reverts() (gas: 182306)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifWithdrawalNotProven_reverts() (gas: 41780)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifWithdrawalProofNotOldEnough_reverts() (gas: 173953)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onInsufficientGas_reverts() (gas: 181161)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onRecentWithdrawal_reverts() (gas: 154740)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onReentrancy_reverts() (gas: 219208)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onReplay_reverts() (gas: 220983)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_paused_reverts() (gas: 38706)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_provenWithdrawalHash_succeeds() (gas: 209679)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_targetFails_fails() (gas: 8797746687696162676)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_timestampLessThanL2OracleStart_reverts() (gas: 171302)
OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_onInvalidOutputRootProof_reverts() (gas: 85805)
OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_onInvalidWithdrawalProof_reverts() (gas: 111317)
OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_onSelfCall_reverts() (gas: 52973)
OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_paused_reverts() (gas: 58846)
OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_replayProveChangedOutputRootAndOutputIndex_succeeds() (gas: 297494)
OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_replayProveChangedOutputRoot_succeeds() (gas: 227596)
OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_replayProve_reverts() (gas: 166699)
OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_validWithdrawalProof_succeeds() (gas: 154430)
OptimismPortal_Test:test_constructor_succeeds() (gas: 28164)
OptimismPortal_Test:test_depositTransaction_contractCreation_reverts() (gas: 14281)
OptimismPortal_Test:test_depositTransaction_largeData_reverts() (gas: 512200)
OptimismPortal_Test:test_depositTransaction_smallGasLimit_reverts() (gas: 14528)
OptimismPortal_Test:test_isOutputFinalized_succeeds() (gas: 127594)
OptimismPortal_Test:test_minimumGasLimit_succeeds() (gas: 17597)
OptimismMintableERC20_Test:test_bridge_succeeds() (gas: 7717)
OptimismMintableERC20_Test:test_burn_notBridge_reverts() (gas: 11180)
OptimismMintableERC20_Test:test_burn_succeeds() (gas: 51074)
OptimismMintableERC20_Test:test_erc165_supportsInterface_succeeds() (gas: 7832)
OptimismMintableERC20_Test:test_l1Token_succeeds() (gas: 7717)
OptimismMintableERC20_Test:test_l2Bridge_succeeds() (gas: 7672)
OptimismMintableERC20_Test:test_legacy_succeeds() (gas: 14518)
OptimismMintableERC20_Test:test_mint_notBridge_reverts() (gas: 11224)
OptimismMintableERC20_Test:test_mint_succeeds() (gas: 63604)
OptimismMintableERC20_Test:test_remoteToken_succeeds() (gas: 7740)
OptimismMintableERC721Factory_Test:test_constructor_succeeds() (gas: 8402)
OptimismMintableERC721Factory_Test:test_createOptimismMintableERC721_sameTwice_reverts() (gas: 8937393460516800078)
OptimismMintableERC721Factory_Test:test_createOptimismMintableERC721_succeeds() (gas: 2316545)
OptimismMintableERC721Factory_Test:test_createOptimismMintableERC721_zeroRemoteToken_reverts() (gas: 9542)
OptimismMintableERC721_Test:test_burn_notBridge_reverts() (gas: 136997)
OptimismMintableERC721_Test:test_burn_succeeds() (gas: 118933)
OptimismMintableERC721_Test:test_constructor_succeeds() (gas: 24516)
OptimismMintableERC721_Test:test_safeMint_notBridge_reverts() (gas: 11224)
OptimismMintableERC721_Test:test_safeMint_succeeds() (gas: 140614)
OptimismMintableERC721_Test:test_supportsInterfaces_succeeds() (gas: 9050)
OptimismMintableERC721_Test:test_tokenURI_succeeds() (gas: 163620)
OptimismMintableTokenFactory_Test:test_bridge_succeeds() (gas: 9812)
OptimismMintableTokenFactory_Test:test_createStandardL2TokenWithDecimals_succeeds() (gas: 1142649)
OptimismMintableTokenFactory_Test:test_createStandardL2Token_remoteIsZero_reverts() (gas: 9621)
OptimismMintableTokenFactory_Test:test_createStandardL2Token_sameTwice_reverts() (gas: 8937393460516764416)
OptimismMintableTokenFactory_Test:test_createStandardL2Token_succeeds() (gas: 1142596)
OptimismPortalUpgradeable_Test:test_initialize_cannotInitImpl_reverts() (gas: 14593)
OptimismPortalUpgradeable_Test:test_initialize_cannotInitProxy_reverts() (gas: 16211)
OptimismPortalUpgradeable_Test:test_params_initValuesOnProxy_succeeds() (gas: 26775)
OptimismPortalUpgradeable_Test:test_upgradeToAndCall_upgrading_succeeds() (gas: 186062)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifOutputRootChanges_reverts() (gas: 178756)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifOutputTimestampIsNotFinalized_reverts() (gas: 182285)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifWithdrawalNotProven_reverts() (gas: 41781)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifWithdrawalProofNotOldEnough_reverts() (gas: 173977)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onInsufficientGas_reverts() (gas: 181245)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onRecentWithdrawal_reverts() (gas: 154807)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onReentrancy_reverts() (gas: 219305)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onReplay_reverts() (gas: 220984)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_paused_reverts() (gas: 38751)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_provenWithdrawalHash_succeeds() (gas: 209680)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_targetFails_fails() (gas: 8797746687696162678)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_timestampLessThanL2OracleStart_reverts() (gas: 171324)
OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_onInvalidOutputRootProof_reverts() (gas: 85828)
OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_onInvalidWithdrawalProof_reverts() (gas: 111318)
OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_onSelfCall_reverts() (gas: 52951)
OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_paused_reverts() (gas: 58892)
OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_replayProveChangedOutputRootAndOutputIndex_succeeds() (gas: 297539)
OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_replayProveChangedOutputRoot_succeeds() (gas: 227597)
OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_replayProve_reverts() (gas: 166744)
OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_validWithdrawalProof_succeeds() (gas: 154431)
OptimismPortal_Test:test_constructor_succeeds() (gas: 33454)
OptimismPortal_Test:test_depositTransaction_contractCreation_reverts() (gas: 14283)
OptimismPortal_Test:test_depositTransaction_largeData_reverts() (gas: 512202)
OptimismPortal_Test:test_depositTransaction_smallGasLimit_reverts() (gas: 14550)
OptimismPortal_Test:test_isOutputFinalized_succeeds() (gas: 127617)
OptimismPortal_Test:test_minimumGasLimit_succeeds() (gas: 17643)
OptimismPortal_Test:test_pause_onlyGuardian_reverts() (gas: 24487)
OptimismPortal_Test:test_pause_succeeds() (gas: 27344)
OptimismPortal_Test:test_receive_succeeds() (gas: 127564)
OptimismPortal_Test:test_unpause_onlyGuardian_reverts() (gas: 31514)
OptimismPortal_Test:test_unpause_succeeds() (gas: 27451)
OptimismPortal_Test:test_pause_succeeds() (gas: 27329)
OptimismPortal_Test:test_simple_isOutputFinalized_succeeds() (gas: 40906)
OptimismPortal_Test:test_unpause_onlyGuardian_reverts() (gas: 31558)
OptimismPortal_Test:test_unpause_succeeds() (gas: 27372)
OptimistAllowlistTest:test_constructor_succeeds() (gas: 16407)
OptimistAllowlistTest:test_isAllowedToMint_fromAllowlistAttestorWithFalsyValue_fails() (gas: 49650)
OptimistAllowlistTest:test_isAllowedToMint_fromAllowlistAttestor_succeeds() (gas: 49254)
......@@ -549,10 +549,10 @@ PreimageOracle_Test:test_loadKeccak256PreimagePart_succeeds() (gas: 76076)
PreimageOracle_Test:test_loadLocalData_multipleContexts_succeeds() (gas: 147718)
PreimageOracle_Test:test_loadLocalData_onePart_succeeds() (gas: 75905)
PreimageOracle_Test:test_loadLocalData_outOfBoundsOffset_reverts() (gas: 8882)
ProtocolVersions_Initialize_Test:test_initialize_events_succeeds() (gas: 52181)
ProtocolVersions_Initialize_Test:test_initialize_values_succeeds() (gas: 32301)
ProtocolVersions_Setters_TestFail:test_setRecommended_notOwner_reverts() (gas: 15508)
ProtocolVersions_Setters_TestFail:test_setRequired_notOwner_reverts() (gas: 15520)
ProtocolVersions_Initialize_Test:test_initialize_events_succeeds() (gas: 41635)
ProtocolVersions_Initialize_Test:test_initialize_values_succeeds() (gas: 45046)
ProtocolVersions_Setters_TestFail:test_setRecommended_notOwner_reverts() (gas: 15553)
ProtocolVersions_Setters_TestFail:test_setRequired_notOwner_reverts() (gas: 15565)
ProxyAdmin_Test:test_chugsplashChangeProxyAdmin_succeeds() (gas: 36440)
ProxyAdmin_Test:test_chugsplashGetProxyAdmin_succeeds() (gas: 15675)
ProxyAdmin_Test:test_chugsplashGetProxyImplementation_succeeds() (gas: 51084)
......@@ -661,33 +661,33 @@ ResourceMetering_Test:test_meter_useMax_succeeds() (gas: 20020816)
ResourceMetering_Test:test_meter_useMoreThanMax_reverts() (gas: 19549)
SafeCall_Test:test_callWithMinGas_noLeakageHigh_succeeds() (gas: 1021670598)
SafeCall_Test:test_callWithMinGas_noLeakageLow_succeeds() (gas: 1095190688)
SequencerFeeVault_L2Withdrawal_Test:test_withdraw_toL2_succeeds() (gas: 78333)
SequencerFeeVault_L2Withdrawal_Test:test_withdraw_toL2recipientReverts_fails() (gas: 46791)
SequencerFeeVault_Test:test_constructor_succeeds() (gas: 5526)
SequencerFeeVault_Test:test_minWithdrawalAmount_succeeds() (gas: 5464)
SequencerFeeVault_Test:test_receive_succeeds() (gas: 17373)
SequencerFeeVault_Test:test_withdraw_notEnough_reverts() (gas: 9332)
SequencerFeeVault_Test:test_withdraw_toL1_succeeds() (gas: 171675)
SetPrevBaseFee_Test:test_setPrevBaseFee_succeeds() (gas: 11549)
StandardBridge_Stateless_Test:test_isCorrectTokenPair_succeeds() (gas: 49936)
StandardBridge_Stateless_Test:test_isOptimismMintableERC20_succeeds() (gas: 33072)
Storage_Roundtrip_Test:test_setGetAddress_succeeds(bytes32,address) (runs: 64, μ: 31821, ~: 31821)
SequencerFeeVault_L2Withdrawal_Test:test_withdraw_toL2_succeeds() (gas: 80640)
SequencerFeeVault_L2Withdrawal_Test:test_withdraw_toL2recipientReverts_fails() (gas: 48926)
SequencerFeeVault_Test:test_constructor_succeeds() (gas: 7705)
SequencerFeeVault_Test:test_minWithdrawalAmount_succeeds() (gas: 12816)
SequencerFeeVault_Test:test_receive_succeeds() (gas: 17395)
SequencerFeeVault_Test:test_withdraw_notEnough_reverts() (gas: 9399)
SequencerFeeVault_Test:test_withdraw_toL1_succeeds() (gas: 618343)
SetPrevBaseFee_Test:test_setPrevBaseFee_succeeds() (gas: 11595)
StandardBridge_Stateless_Test:test_isCorrectTokenPair_succeeds() (gas: 50168)
StandardBridge_Stateless_Test:test_isOptimismMintableERC20_succeeds() (gas: 33117)
Storage_Roundtrip_Test:test_setGetAddress_succeeds(bytes32,address) (runs: 64, μ: 31510, ~: 31821)
Storage_Roundtrip_Test:test_setGetBytes32_succeeds(bytes32,bytes32) (runs: 64, μ: 31598, ~: 31598)
Storage_Roundtrip_Test:test_setGetUint_succeeds(bytes32,uint256) (runs: 64, μ: 30731, ~: 31664)
SystemConfig_Initialize_Test:test_initialize_events_succeeds() (gas: 71972)
SystemConfig_Initialize_Test:test_initialize_startBlockNoop_reverts() (gas: 81247)
SystemConfig_Initialize_Test:test_initialize_startBlockOverride_succeeds() (gas: 65143)
SystemConfig_Initialize_Test:test_initialize_values_succeeds() (gas: 64968)
SystemConfig_Initialize_TestFail:test_initialize_lowGasLimit_reverts() (gas: 57177)
SystemConfig_Setters_TestFail:test_setBatcherHash_notOwner_reverts() (gas: 15607)
SystemConfig_Setters_TestFail:test_setGasConfig_notOwner_reverts() (gas: 15577)
SystemConfig_Setters_TestFail:test_setGasLimit_notOwner_reverts() (gas: 15676)
SystemConfig_Setters_TestFail:test_setResourceConfig_badMinMax_reverts() (gas: 18541)
SystemConfig_Setters_TestFail:test_setResourceConfig_badPrecision_reverts() (gas: 21142)
SystemConfig_Setters_TestFail:test_setResourceConfig_lowGasLimit_reverts() (gas: 22146)
SystemConfig_Setters_TestFail:test_setResourceConfig_notOwner_reverts() (gas: 16799)
SystemConfig_Setters_TestFail:test_setResourceConfig_zeroDenominator_reverts() (gas: 18578)
SystemConfig_Setters_TestFail:test_setUnsafeBlockSigner_notOwner_reverts() (gas: 15590)
SystemConfig_Initialize_Test:test_initialize_events_succeeds() (gas: 88186)
SystemConfig_Initialize_Test:test_initialize_startBlockNoop_reverts() (gas: 77159)
SystemConfig_Initialize_Test:test_initialize_startBlockOverride_succeeds() (gas: 81116)
SystemConfig_Initialize_Test:test_initialize_values_succeeds() (gas: 88523)
SystemConfig_Initialize_TestFail:test_initialize_lowGasLimit_reverts() (gas: 59900)
SystemConfig_Setters_TestFail:test_setBatcherHash_notOwner_reverts() (gas: 15652)
SystemConfig_Setters_TestFail:test_setGasConfig_notOwner_reverts() (gas: 15644)
SystemConfig_Setters_TestFail:test_setGasLimit_notOwner_reverts() (gas: 15743)
SystemConfig_Setters_TestFail:test_setResourceConfig_badMinMax_reverts() (gas: 18614)
SystemConfig_Setters_TestFail:test_setResourceConfig_badPrecision_reverts() (gas: 21194)
SystemConfig_Setters_TestFail:test_setResourceConfig_lowGasLimit_reverts() (gas: 22242)
SystemConfig_Setters_TestFail:test_setResourceConfig_notOwner_reverts() (gas: 16844)
SystemConfig_Setters_TestFail:test_setResourceConfig_zeroDenominator_reverts() (gas: 18629)
SystemConfig_Setters_TestFail:test_setUnsafeBlockSigner_notOwner_reverts() (gas: 15657)
TransactorTest:test_call_succeeds() (gas: 26709)
TransactorTest:test_call_unauthorized_reverts() (gas: 18117)
TransactorTest:test_constructor_succeeds() (gas: 9739)
......
# `OptimismPortal` Invariants
## Deposits of any value should always succeed unless `_to` = `address(0)` or `_isCreation` = `true`.
**Test:** [`OptimismPortal.t.sol#L148`](../test/invariants/OptimismPortal.t.sol#L148)
**Test:** [`OptimismPortal.t.sol#L151`](../test/invariants/OptimismPortal.t.sol#L151)
All deposits, barring creation transactions and transactions sent to `address(0)`, should always succeed.
## `finalizeWithdrawalTransaction` should revert if the finalization period has not elapsed.
**Test:** [`OptimismPortal.t.sol#L171`](../test/invariants/OptimismPortal.t.sol#L171)
**Test:** [`OptimismPortal.t.sol#L174`](../test/invariants/OptimismPortal.t.sol#L174)
A withdrawal that has been proven should not be able to be finalized until after the finalization period has elapsed.
## `finalizeWithdrawalTransaction` should revert if the withdrawal has already been finalized.
**Test:** [`OptimismPortal.t.sol#L201`](../test/invariants/OptimismPortal.t.sol#L201)
**Test:** [`OptimismPortal.t.sol#L204`](../test/invariants/OptimismPortal.t.sol#L204)
Ensures that there is no chain of calls that can be made that allows a withdrawal to be finalized twice.
## A withdrawal should **always** be able to be finalized `FINALIZATION_PERIOD_SECONDS` after it was successfully proven.
**Test:** [`OptimismPortal.t.sol#L230`](../test/invariants/OptimismPortal.t.sol#L230)
**Test:** [`OptimismPortal.t.sol#L233`](../test/invariants/OptimismPortal.t.sol#L233)
This invariant asserts that there is no chain of calls that can be made that will prevent a withdrawal from being finalized exactly `FINALIZATION_PERIOD_SECONDS` after it was successfully proven.
\ No newline at end of file
......@@ -15,8 +15,8 @@ function setPrevBaseFee(Vm _vm, address _op, uint128 _prevBaseFee) {
contract SetPrevBaseFee_Test is Portal_Initializer {
function test_setPrevBaseFee_succeeds() external {
setPrevBaseFee(vm, address(op), 100 gwei);
(uint128 prevBaseFee,, uint64 prevBlockNum) = op.params();
setPrevBaseFee(vm, address(optimismPortal), 100 gwei);
(uint128 prevBaseFee,, uint64 prevBlockNum) = optimismPortal.params();
assertEq(uint256(prevBaseFee), 100 gwei);
assertEq(uint256(prevBlockNum), block.number);
}
......@@ -61,61 +61,64 @@ contract GasBenchMark_OptimismPortal is Portal_Initializer {
messagePasserStorageRoot: _storageRoot,
latestBlockhash: bytes32(uint256(0))
});
_proposedBlockNumber = oracle.nextBlockNumber();
_proposedOutputIndex = oracle.nextOutputIndex();
_proposedBlockNumber = l2OutputOracle.nextBlockNumber();
_proposedOutputIndex = l2OutputOracle.nextOutputIndex();
}
// Get the system into a nice ready-to-use state.
function setUp() public virtual override {
// Configure the oracle to return the output root we've prepared.
vm.warp(oracle.computeL2Timestamp(_proposedBlockNumber) + 1);
vm.prank(oracle.PROPOSER());
oracle.proposeL2Output(_outputRoot, _proposedBlockNumber, 0, 0);
vm.warp(l2OutputOracle.computeL2Timestamp(_proposedBlockNumber) + 1);
vm.prank(l2OutputOracle.PROPOSER());
l2OutputOracle.proposeL2Output(_outputRoot, _proposedBlockNumber, 0, 0);
// Warp beyond the finalization period for the block we've proposed.
vm.warp(oracle.getL2Output(_proposedOutputIndex).timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);
vm.warp(
l2OutputOracle.getL2Output(_proposedOutputIndex).timestamp + l2OutputOracle.FINALIZATION_PERIOD_SECONDS()
+ 1
);
// Fund the portal so that we can withdraw ETH.
vm.deal(address(op), 0xFFFFFFFF);
vm.deal(address(optimismPortal), 0xFFFFFFFF);
}
function test_depositTransaction_benchmark() external {
op.depositTransaction{ value: NON_ZERO_VALUE }(
NON_ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, false, NON_ZERO_DATA
optimismPortal.depositTransaction{ value: 100 }(
address(1), 0, 50000, false, hex"0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff0000"
);
}
function test_depositTransaction_benchmark_1() external {
setPrevBaseFee(vm, address(op), 1 gwei);
op.depositTransaction{ value: NON_ZERO_VALUE }(
NON_ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, false, NON_ZERO_DATA
setPrevBaseFee(vm, address(optimismPortal), 1 gwei);
optimismPortal.depositTransaction{ value: 100 }(
address(1), 0, 50000, false, hex"0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff0000"
);
}
function test_proveWithdrawalTransaction_benchmark() external {
op.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof);
optimismPortal.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof);
}
}
contract GasBenchMark_L1CrossDomainMessenger is Messenger_Initializer {
function test_sendMessage_benchmark_0() external {
vm.pauseGasMetering();
setPrevBaseFee(vm, address(op), 1 gwei);
setPrevBaseFee(vm, address(optimismPortal), 1 gwei);
// The amount of data typically sent during a bridge deposit.
bytes memory data =
hex"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";
vm.resumeGasMetering();
L1Messenger.sendMessage(bob, data, uint32(100));
l1CrossDomainMessenger.sendMessage(bob, data, uint32(100));
}
function test_sendMessage_benchmark_1() external {
vm.pauseGasMetering();
setPrevBaseFee(vm, address(op), 10 gwei);
setPrevBaseFee(vm, address(optimismPortal), 10 gwei);
// The amount of data typically sent during a bridge deposit.
bytes memory data =
hex"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";
vm.resumeGasMetering();
L1Messenger.sendMessage(bob, data, uint32(100));
l1CrossDomainMessenger.sendMessage(bob, data, uint32(100));
}
}
......@@ -124,28 +127,28 @@ contract GasBenchMark_L1StandardBridge_Deposit is Bridge_Initializer {
super.setUp();
deal(address(L1Token), alice, 100000, true);
vm.startPrank(alice, alice);
L1Token.approve(address(L1Bridge), type(uint256).max);
L1Token.approve(address(l1StandardBridge), type(uint256).max);
}
function test_depositETH_benchmark_0() external {
vm.pauseGasMetering();
setPrevBaseFee(vm, address(op), 1 gwei);
setPrevBaseFee(vm, address(optimismPortal), 1 gwei);
vm.resumeGasMetering();
L1Bridge.depositETH{ value: 500 }(50000, hex"");
l1StandardBridge.depositETH{ value: 500 }(50000, hex"");
}
function test_depositETH_benchmark_1() external {
vm.pauseGasMetering();
setPrevBaseFee(vm, address(op), 10 gwei);
setPrevBaseFee(vm, address(optimismPortal), 10 gwei);
vm.resumeGasMetering();
L1Bridge.depositETH{ value: 500 }(50000, hex"");
l1StandardBridge.depositETH{ value: 500 }(50000, hex"");
}
function test_depositERC20_benchmark_0() external {
vm.pauseGasMetering();
setPrevBaseFee(vm, address(op), 1 gwei);
setPrevBaseFee(vm, address(optimismPortal), 1 gwei);
vm.resumeGasMetering();
L1Bridge.bridgeERC20({
l1StandardBridge.bridgeERC20({
_localToken: address(L1Token),
_remoteToken: address(L2Token),
_amount: 100,
......@@ -156,9 +159,9 @@ contract GasBenchMark_L1StandardBridge_Deposit is Bridge_Initializer {
function test_depositERC20_benchmark_1() external {
vm.pauseGasMetering();
setPrevBaseFee(vm, address(op), 10 gwei);
setPrevBaseFee(vm, address(optimismPortal), 10 gwei);
vm.resumeGasMetering();
L1Bridge.bridgeERC20({
l1StandardBridge.bridgeERC20({
_localToken: address(L1Token),
_remoteToken: address(L2Token),
_amount: 100,
......@@ -171,21 +174,21 @@ contract GasBenchMark_L1StandardBridge_Deposit is Bridge_Initializer {
contract GasBenchMark_L1StandardBridge_Finalize is Bridge_Initializer {
function setUp() public virtual override {
super.setUp();
deal(address(L1Token), address(L1Bridge), 100, true);
deal(address(L1Token), address(l1StandardBridge), 100, true);
vm.mockCall(
address(L1Bridge.messenger()),
address(l1StandardBridge.messenger()),
abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),
abi.encode(address(L1Bridge.OTHER_BRIDGE()))
abi.encode(address(l1StandardBridge.OTHER_BRIDGE()))
);
vm.startPrank(address(L1Bridge.messenger()));
vm.deal(address(L1Bridge.messenger()), 100);
vm.startPrank(address(l1StandardBridge.messenger()));
vm.deal(address(l1StandardBridge.messenger()), 100);
}
function test_finalizeETHWithdrawal_benchmark() external {
// TODO: Make this more accurate. It is underestimating the cost because it pranks
// the call coming from the messenger, which bypasses the portal
// and oracle.
L1Bridge.finalizeETHWithdrawal{ value: 100 }(alice, alice, 100, hex"");
l1StandardBridge.finalizeETHWithdrawal{ value: 100 }(alice, alice, 100, hex"");
}
}
......@@ -194,12 +197,13 @@ contract GasBenchMark_L2OutputOracle is L2OutputOracle_Initializer {
function setUp() public override {
super.setUp();
nextBlockNumber = oracle.nextBlockNumber();
nextBlockNumber = l2OutputOracle.nextBlockNumber();
warpToProposeTime(nextBlockNumber);
address proposer = cfg.l2OutputOracleProposer();
vm.startPrank(proposer);
}
function test_proposeL2Output_benchmark() external {
oracle.proposeL2Output(nonZeroHash, nextBlockNumber, 0, 0);
l2OutputOracle.proposeL2Output(nonZeroHash, nextBlockNumber, 0, 0);
}
}
......@@ -3,7 +3,6 @@ pragma solidity 0.8.15;
// Testing utilities
import { Test, StdUtils } from "forge-std/Test.sol";
import { Vm } from "forge-std/Vm.sol";
import { L2OutputOracle } from "src/L1/L2OutputOracle.sol";
import { L2ToL1MessagePasser } from "src/L2/L2ToL1MessagePasser.sol";
import { L1StandardBridge } from "src/L1/L1StandardBridge.sol";
......@@ -18,6 +17,12 @@ import { OptimismPortal } from "src/L1/OptimismPortal.sol";
import { L1CrossDomainMessenger } from "src/L1/L1CrossDomainMessenger.sol";
import { L2CrossDomainMessenger } from "src/L2/L2CrossDomainMessenger.sol";
import { SequencerFeeVault } from "src/L2/SequencerFeeVault.sol";
import { L1FeeVault } from "src/L2/L1FeeVault.sol";
import { BaseFeeVault } from "src/L2/BaseFeeVault.sol";
import { FeeVault } from "src/universal/FeeVault.sol";
import { GasPriceOracle } from "src/L2/GasPriceOracle.sol";
import { L1Block } from "src/L2/L1Block.sol";
import { ProtocolVersions } from "src/L1/ProtocolVersions.sol";
import { FeeVault } from "src/universal/FeeVault.sol";
import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol";
import { LegacyERC20ETH } from "src/legacy/LegacyERC20ETH.sol";
......@@ -25,53 +30,191 @@ import { Predeploys } from "src/libraries/Predeploys.sol";
import { Types } from "src/libraries/Types.sol";
import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import { Proxy } from "src/universal/Proxy.sol";
import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import { ResolvedDelegateProxy } from "src/legacy/ResolvedDelegateProxy.sol";
import { AddressManager } from "src/legacy/AddressManager.sol";
import { L1ChugSplashProxy } from "src/legacy/L1ChugSplashProxy.sol";
import { IL1ChugSplashDeployer } from "src/legacy/L1ChugSplashProxy.sol";
import { CrossDomainMessenger } from "src/universal/CrossDomainMessenger.sol";
import { GovernanceToken } from "src/governance/GovernanceToken.sol";
import { Strings } from "@openzeppelin/contracts/utils/Strings.sol";
import { LegacyMintableERC20 } from "src/legacy/LegacyMintableERC20.sol";
import { LegacyMessagePasser } from "src/legacy/LegacyMessagePasser.sol";
import { SystemConfig } from "src/L1/SystemConfig.sol";
import { ResourceMetering } from "src/L1/ResourceMetering.sol";
import { Constants } from "src/libraries/Constants.sol";
import { Deploy } from "scripts/Deploy.s.sol";
import { FFIInterface } from "test/setup/FFIInterface.sol";
contract CommonTest is Test {
contract CommonTest is Deploy, Test {
address alice = address(128);
address bob = address(256);
address multisig = address(512);
address immutable ZERO_ADDRESS = address(0);
address immutable NON_ZERO_ADDRESS = address(1);
uint256 immutable NON_ZERO_VALUE = 100;
uint256 immutable ZERO_VALUE = 0;
uint64 immutable NON_ZERO_GASLIMIT = 50000;
bytes32 nonZeroHash = keccak256(abi.encode("NON_ZERO"));
bytes NON_ZERO_DATA = hex"0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff0000";
bytes32 constant nonZeroHash = keccak256(abi.encode("NON_ZERO"));
event TransactionDeposited(address indexed from, address indexed to, uint256 indexed version, bytes opaqueData);
/// @dev OpenZeppelin Ownable.sol transferOwnership event
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
OptimismPortal optimismPortal;
L2OutputOracle l2OutputOracle;
SystemConfig systemConfig;
L1StandardBridge l1StandardBridge;
L1CrossDomainMessenger l1CrossDomainMessenger;
AddressManager addressManager;
L1ERC721Bridge l1ERC721Bridge;
OptimismMintableERC20Factory l1OptimismMintableERC20Factory;
ProtocolVersions protocolVersions;
L2CrossDomainMessenger l2CrossDomainMessenger;
L2StandardBridge l2StandardBridge;
L2ToL1MessagePasser l2ToL1MessagePasser;
OptimismMintableERC20Factory l2OptimismMintableERC20Factory;
L2ERC721Bridge l2ERC721Bridge;
BaseFeeVault baseFeeVault;
SequencerFeeVault sequencerFeeVault;
L1FeeVault l1FeeVault;
GasPriceOracle gasPriceOracle;
L1Block l1Block;
LegacyMessagePasser legacyMessagePasser;
GovernanceToken governanceToken;
FFIInterface ffi;
function setUp() public virtual {
function setUp() public virtual override {
// Give alice and bob some ETH
vm.deal(alice, 1 << 16);
vm.deal(bob, 1 << 16);
vm.deal(multisig, 1 << 16);
vm.label(alice, "alice");
vm.label(bob, "bob");
vm.label(multisig, "multisig");
// Make sure we have a non-zero base fee
vm.fee(1000000000);
// Set the deterministic deployer in state
vm.etch(
0x4e59b44847b379578588920cA78FbF26c0B4956C,
hex"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3"
);
ffi = new FFIInterface();
Deploy.setUp();
Deploy.run();
// Set up L1
optimismPortal = OptimismPortal(mustGetAddress("OptimismPortalProxy"));
l2OutputOracle = L2OutputOracle(mustGetAddress("L2OutputOracleProxy"));
systemConfig = SystemConfig(mustGetAddress("SystemConfigProxy"));
l1StandardBridge = L1StandardBridge(mustGetAddress("L1StandardBridgeProxy"));
l1CrossDomainMessenger = L1CrossDomainMessenger(mustGetAddress("L1CrossDomainMessengerProxy"));
addressManager = AddressManager(mustGetAddress("AddressManager"));
l1ERC721Bridge = L1ERC721Bridge(mustGetAddress("L1ERC721BridgeProxy"));
l1OptimismMintableERC20Factory =
OptimismMintableERC20Factory(mustGetAddress("OptimismMintableERC20FactoryProxy"));
protocolVersions = ProtocolVersions(mustGetAddress("ProtocolVersionsProxy"));
vm.label(address(l2OutputOracle), "L2OutputOracle");
vm.label(address(optimismPortal), "OptimismPortal");
vm.label(address(systemConfig), "SystemConfig");
vm.label(address(l1StandardBridge), "L1StandardBridge");
vm.label(address(l1CrossDomainMessenger), "L1CrossDomainMessenger");
vm.label(address(addressManager), "AddressManager");
vm.label(address(l1ERC721Bridge), "L1ERC721Bridge");
vm.label(address(l1OptimismMintableERC20Factory), "OptimismMintableERC20Factory");
vm.label(address(protocolVersions), "ProtocolVersions");
// Set up L2. There are currently no proxies set in the L2 initialization.
vm.etch(
Predeploys.L2_CROSS_DOMAIN_MESSENGER,
address(new L2CrossDomainMessenger(address(l1CrossDomainMessenger))).code
);
l2CrossDomainMessenger = L2CrossDomainMessenger(payable(Predeploys.L2_CROSS_DOMAIN_MESSENGER));
l2CrossDomainMessenger.initialize();
vm.etch(Predeploys.L2_TO_L1_MESSAGE_PASSER, address(new L2ToL1MessagePasser()).code);
l2ToL1MessagePasser = L2ToL1MessagePasser(payable(Predeploys.L2_TO_L1_MESSAGE_PASSER));
vm.etch(
Predeploys.L2_STANDARD_BRIDGE, address(new L2StandardBridge(StandardBridge(payable(l1StandardBridge)))).code
);
l2StandardBridge = L2StandardBridge(payable(Predeploys.L2_STANDARD_BRIDGE));
l2StandardBridge.initialize();
vm.etch(Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY, address(new OptimismMintableERC20Factory()).code);
l2OptimismMintableERC20Factory = OptimismMintableERC20Factory(Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY);
l2OptimismMintableERC20Factory.initialize(Predeploys.L2_STANDARD_BRIDGE);
vm.etch(Predeploys.LEGACY_ERC20_ETH, address(new LegacyERC20ETH()).code);
vm.etch(Predeploys.L2_ERC721_BRIDGE, address(new L2ERC721Bridge(address(l1ERC721Bridge))).code);
l2ERC721Bridge = L2ERC721Bridge(Predeploys.L2_ERC721_BRIDGE);
l2ERC721Bridge.initialize();
vm.etch(
Predeploys.SEQUENCER_FEE_WALLET,
address(
new SequencerFeeVault(cfg.sequencerFeeVaultRecipient(), cfg.sequencerFeeVaultMinimumWithdrawalAmount(), FeeVault.WithdrawalNetwork.L2)
).code
);
vm.etch(
Predeploys.BASE_FEE_VAULT,
address(
new BaseFeeVault(cfg.baseFeeVaultRecipient(), cfg.baseFeeVaultMinimumWithdrawalAmount(), FeeVault.WithdrawalNetwork.L1)
).code
);
vm.etch(
Predeploys.L1_FEE_VAULT,
address(
new L1FeeVault(cfg.l1FeeVaultRecipient(), cfg.l1FeeVaultMinimumWithdrawalAmount(), FeeVault.WithdrawalNetwork.L2)
).code
);
sequencerFeeVault = SequencerFeeVault(payable(Predeploys.SEQUENCER_FEE_WALLET));
baseFeeVault = BaseFeeVault(payable(Predeploys.BASE_FEE_VAULT));
l1FeeVault = L1FeeVault(payable(Predeploys.L1_FEE_VAULT));
vm.etch(Predeploys.L1_BLOCK_ATTRIBUTES, address(new L1Block()).code);
l1Block = L1Block(Predeploys.L1_BLOCK_ATTRIBUTES);
vm.etch(Predeploys.GAS_PRICE_ORACLE, address(new GasPriceOracle()).code);
gasPriceOracle = GasPriceOracle(Predeploys.GAS_PRICE_ORACLE);
vm.etch(Predeploys.LEGACY_MESSAGE_PASSER, address(new LegacyMessagePasser()).code);
legacyMessagePasser = LegacyMessagePasser(Predeploys.LEGACY_MESSAGE_PASSER);
vm.etch(Predeploys.GOVERNANCE_TOKEN, address(new GovernanceToken()).code);
governanceToken = GovernanceToken(Predeploys.GOVERNANCE_TOKEN);
vm.store(
Predeploys.GOVERNANCE_TOKEN,
bytes32(uint256(3)),
bytes32(0x4f7074696d69736d000000000000000000000000000000000000000000000010)
);
vm.store(
Predeploys.GOVERNANCE_TOKEN,
bytes32(uint256(4)),
bytes32(0x4f50000000000000000000000000000000000000000000000000000000000004)
);
// Set the governance token's owner to be the final system owner
address finalSystemOwner = cfg.finalSystemOwner();
vm.prank(governanceToken.owner());
governanceToken.transferOwnership(finalSystemOwner);
vm.label(Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY, "OptimismMintableERC20Factory");
vm.label(Predeploys.LEGACY_ERC20_ETH, "LegacyERC20ETH");
vm.label(Predeploys.L2_STANDARD_BRIDGE, "L2StandardBridge");
vm.label(Predeploys.L2_CROSS_DOMAIN_MESSENGER, "L2CrossDomainMessenger");
vm.label(Predeploys.L2_TO_L1_MESSAGE_PASSER, "L2ToL1MessagePasser");
vm.label(Predeploys.SEQUENCER_FEE_WALLET, "SequencerFeeVault");
vm.label(Predeploys.L2_ERC721_BRIDGE, "L2ERC721Bridge");
vm.label(Predeploys.BASE_FEE_VAULT, "BaseFeeVault");
vm.label(Predeploys.L1_FEE_VAULT, "L1FeeVault");
vm.label(Predeploys.L1_BLOCK_ATTRIBUTES, "L1Block");
vm.label(Predeploys.GAS_PRICE_ORACLE, "GasPriceOracle");
vm.label(Predeploys.LEGACY_MESSAGE_PASSER, "LegacyMessagePasser");
vm.label(Predeploys.GOVERNANCE_TOKEN, "GovernanceToken");
vm.label(AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger)), "L1CrossDomainMessenger_aliased");
}
function emitTransactionDeposited(
......@@ -90,44 +233,26 @@ contract CommonTest is Test {
}
contract L2OutputOracle_Initializer is CommonTest {
// Test target
L2OutputOracle oracle;
L2OutputOracle oracleImpl;
L2ToL1MessagePasser messagePasser = L2ToL1MessagePasser(payable(Predeploys.L2_TO_L1_MESSAGE_PASSER));
// Constructor arguments
address internal proposer = 0x000000000000000000000000000000000000AbBa;
address internal owner = 0x000000000000000000000000000000000000ACDC;
uint256 internal submissionInterval = 1800;
uint256 internal l2BlockTime = 2;
uint256 internal startingBlockNumber = 200;
uint256 internal startingTimestamp = 1000;
uint256 internal finalizationPeriodSeconds = 7 days;
address guardian;
// Test data
uint256 initL1Time;
event OutputProposed(
bytes32 indexed outputRoot, uint256 indexed l2OutputIndex, uint256 indexed l2BlockNumber, uint256 l1Timestamp
);
event OutputsDeleted(uint256 indexed prevNextOutputIndex, uint256 indexed newNextOutputIndex);
// Advance the evm's time to meet the L2OutputOracle's requirements for proposeL2Output
// @dev Advance the evm's time to meet the L2OutputOracle's requirements for proposeL2Output
function warpToProposeTime(uint256 _nextBlockNumber) public {
vm.warp(oracle.computeL2Timestamp(_nextBlockNumber) + 1);
vm.warp(l2OutputOracle.computeL2Timestamp(_nextBlockNumber) + 1);
}
/// @dev Helper function to propose an output.
function proposeAnotherOutput() public {
bytes32 proposedOutput2 = keccak256(abi.encode());
uint256 nextBlockNumber = oracle.nextBlockNumber();
uint256 nextOutputIndex = oracle.nextOutputIndex();
uint256 nextBlockNumber = l2OutputOracle.nextBlockNumber();
uint256 nextOutputIndex = l2OutputOracle.nextOutputIndex();
warpToProposeTime(nextBlockNumber);
uint256 proposedNumber = oracle.latestBlockNumber();
uint256 proposedNumber = l2OutputOracle.latestBlockNumber();
uint256 submissionInterval = cfg.l2OutputOracleSubmissionInterval();
// Ensure the submissionInterval is enforced
assertEq(nextBlockNumber, proposedNumber + submissionInterval);
......@@ -136,107 +261,29 @@ contract L2OutputOracle_Initializer is CommonTest {
vm.expectEmit(true, true, true, true);
emit OutputProposed(proposedOutput2, nextOutputIndex, nextBlockNumber, block.timestamp);
address proposer = cfg.l2OutputOracleProposer();
vm.prank(proposer);
oracle.proposeL2Output(proposedOutput2, nextBlockNumber, 0, 0);
l2OutputOracle.proposeL2Output(proposedOutput2, nextBlockNumber, 0, 0);
}
function setUp() public virtual override {
super.setUp();
guardian = makeAddr("guardian");
// By default the first block has timestamp and number zero, which will cause underflows in the
// tests, so we'll move forward to these block values.
initL1Time = startingTimestamp + 1;
vm.warp(initL1Time);
vm.roll(startingBlockNumber);
// Deploy the L2OutputOracle and transfer owernship to the proposer
oracleImpl = new L2OutputOracle({
_submissionInterval: submissionInterval,
_l2BlockTime: l2BlockTime,
_finalizationPeriodSeconds: finalizationPeriodSeconds
});
Proxy proxy = new Proxy(multisig);
vm.prank(multisig);
proxy.upgradeToAndCall(
address(oracleImpl),
abi.encodeCall(L2OutputOracle.initialize, (startingBlockNumber, startingTimestamp, proposer, owner))
);
oracle = L2OutputOracle(address(proxy));
vm.label(address(oracle), "L2OutputOracle");
// Set the L2ToL1MessagePasser at the correct address
vm.etch(Predeploys.L2_TO_L1_MESSAGE_PASSER, address(new L2ToL1MessagePasser()).code);
vm.label(Predeploys.L2_TO_L1_MESSAGE_PASSER, "L2ToL1MessagePasser");
vm.warp(cfg.l2OutputOracleStartingTimestamp() + 1);
vm.roll(cfg.l2OutputOracleStartingBlockNumber() + 1);
}
}
contract Portal_Initializer is L2OutputOracle_Initializer {
// Test target
OptimismPortal internal opImpl;
OptimismPortal internal op;
SystemConfig systemConfig;
event WithdrawalFinalized(bytes32 indexed withdrawalHash, bool success);
event WithdrawalProven(bytes32 indexed withdrawalHash, address indexed from, address indexed to);
function setUp() public virtual override {
super.setUp();
Proxy systemConfigProxy = new Proxy(multisig);
SystemConfig systemConfigImpl = new SystemConfig();
vm.prank(multisig);
systemConfigProxy.upgradeToAndCall(
address(systemConfigImpl),
abi.encodeCall(
SystemConfig.initialize,
(
address(1), //_owner,
0, //_overhead,
10000, //_scalar,
bytes32(0), //_batcherHash,
30_000_000, //_gasLimit,
address(0), //_unsafeBlockSigner,
Constants.DEFAULT_RESOURCE_CONFIG(), //_config,
0, //_startBlock
address(0xff), // _batchInbox
SystemConfig.Addresses({ // _addresses
l1CrossDomainMessenger: address(0),
l1ERC721Bridge: address(0),
l1StandardBridge: address(0),
l2OutputOracle: address(oracle),
optimismPortal: address(op),
optimismMintableERC20Factory: address(0)
})
)
)
);
systemConfig = SystemConfig(address(systemConfigProxy));
opImpl = new OptimismPortal();
Proxy proxy = new Proxy(multisig);
vm.prank(multisig);
proxy.upgradeToAndCall(
address(opImpl), abi.encodeCall(OptimismPortal.initialize, (oracle, guardian, systemConfig, false))
);
op = OptimismPortal(payable(address(proxy)));
vm.label(address(op), "OptimismPortal");
}
}
contract Messenger_Initializer is Portal_Initializer {
AddressManager internal addressManager;
L1CrossDomainMessenger internal L1Messenger;
L2CrossDomainMessenger internal L2Messenger = L2CrossDomainMessenger(Predeploys.L2_CROSS_DOMAIN_MESSENGER);
event SentMessage(address indexed target, address sender, bytes message, uint256 messageNonce, uint256 gasLimit);
event SentMessageExtension1(address indexed sender, uint256 value);
event MessagePassed(
uint256 indexed nonce,
address indexed sender,
......@@ -246,10 +293,8 @@ contract Messenger_Initializer is Portal_Initializer {
bytes data,
bytes32 withdrawalHash
);
event RelayedMessage(bytes32 indexed msgHash);
event FailedRelayedMessage(bytes32 indexed msgHash);
event TransactionDeposited(
address indexed from,
address indexed to,
......@@ -259,49 +304,10 @@ contract Messenger_Initializer is Portal_Initializer {
bool isCreation,
bytes data
);
event WhatHappened(bool success, bytes returndata);
function setUp() public virtual override {
super.setUp();
// Deploy the address manager
vm.prank(multisig);
addressManager = new AddressManager();
// Setup implementation
L1CrossDomainMessenger L1MessengerImpl = new L1CrossDomainMessenger();
// Setup the address manager and proxy
vm.prank(multisig);
addressManager.setAddress("OVM_L1CrossDomainMessenger", address(L1MessengerImpl));
ResolvedDelegateProxy proxy = new ResolvedDelegateProxy(
addressManager,
"OVM_L1CrossDomainMessenger"
);
L1Messenger = L1CrossDomainMessenger(address(proxy));
L1Messenger.initialize(op);
vm.etch(Predeploys.L2_CROSS_DOMAIN_MESSENGER, address(new L2CrossDomainMessenger(address(L1Messenger))).code);
L2Messenger.initialize();
// Label addresses
vm.label(address(addressManager), "AddressManager");
vm.label(address(L1MessengerImpl), "L1CrossDomainMessenger_Impl");
vm.label(address(L1Messenger), "L1CrossDomainMessenger_Proxy");
vm.label(Predeploys.LEGACY_ERC20_ETH, "LegacyERC20ETH");
vm.label(Predeploys.L2_CROSS_DOMAIN_MESSENGER, "L2CrossDomainMessenger");
vm.label(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)), "L1CrossDomainMessenger_aliased");
}
}
contract Bridge_Initializer is Messenger_Initializer {
L1StandardBridge L1Bridge;
L2StandardBridge L2Bridge;
OptimismMintableERC20Factory L2TokenFactory;
OptimismMintableERC20Factory L1TokenFactory;
ERC20 L1Token;
ERC20 BadL1Token;
OptimismMintableERC20 L2Token;
......@@ -359,44 +365,10 @@ contract Bridge_Initializer is Messenger_Initializer {
function setUp() public virtual override {
super.setUp();
vm.label(Predeploys.L2_STANDARD_BRIDGE, "L2StandardBridge");
vm.label(Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY, "OptimismMintableERC20Factory");
// Deploy the L1 bridge and initialize it with the address of the
// L1CrossDomainMessenger
L1ChugSplashProxy proxy = new L1ChugSplashProxy(multisig);
vm.mockCall(multisig, abi.encodeWithSelector(IL1ChugSplashDeployer.isUpgrading.selector), abi.encode(true));
vm.startPrank(multisig);
proxy.setCode(address(new L1StandardBridge()).code);
vm.clearMockedCalls();
address L1Bridge_Impl = proxy.getImplementation();
vm.stopPrank();
L1Bridge = L1StandardBridge(payable(address(proxy)));
L1Bridge.initialize({ _messenger: L1Messenger });
vm.label(address(proxy), "L1StandardBridge_Proxy");
vm.label(address(L1Bridge_Impl), "L1StandardBridge_Impl");
// Deploy the L2StandardBridge, move it to the correct predeploy
// address and then initialize it. It is safe to call initialize directly
// on the proxy because the bytecode was set in state with `etch`.
vm.etch(Predeploys.L2_STANDARD_BRIDGE, address(new L2StandardBridge(StandardBridge(payable(proxy)))).code);
L2Bridge = L2StandardBridge(payable(Predeploys.L2_STANDARD_BRIDGE));
L2Bridge.initialize();
// Set up the L2 mintable token factory
OptimismMintableERC20Factory factory = new OptimismMintableERC20Factory();
vm.etch(Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY, address(factory).code);
L2TokenFactory = OptimismMintableERC20Factory(Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY);
L2TokenFactory.initialize(Predeploys.L2_STANDARD_BRIDGE);
vm.etch(Predeploys.LEGACY_ERC20_ETH, address(new LegacyERC20ETH()).code);
L1Token = new ERC20("Native L1 Token", "L1T");
LegacyL2Token = new LegacyMintableERC20({
_l2Bridge: address(L2Bridge),
_l2Bridge: address(l2StandardBridge),
_l1Token: address(L1Token),
_name: string.concat("LegacyL2-", L1Token.name()),
_symbol: string.concat("LegacyL2-", L1Token.symbol())
......@@ -405,7 +377,7 @@ contract Bridge_Initializer is Messenger_Initializer {
// Deploy the L2 ERC20 now
L2Token = OptimismMintableERC20(
L2TokenFactory.createStandardL2Token(
l2OptimismMintableERC20Factory.createStandardL2Token(
address(L1Token),
string(abi.encodePacked("L2-", L1Token.name())),
string(abi.encodePacked("L2-", L1Token.symbol()))
......@@ -413,7 +385,7 @@ contract Bridge_Initializer is Messenger_Initializer {
);
BadL2Token = OptimismMintableERC20(
L2TokenFactory.createStandardL2Token(
l2OptimismMintableERC20Factory.createStandardL2Token(
address(1),
string(abi.encodePacked("L2-", L1Token.name())),
string(abi.encodePacked("L2-", L1Token.symbol()))
......@@ -421,18 +393,9 @@ contract Bridge_Initializer is Messenger_Initializer {
);
NativeL2Token = new ERC20("Native L2 Token", "L2T");
Proxy factoryProxy = new Proxy(multisig);
OptimismMintableERC20Factory L1TokenFactoryImpl = new OptimismMintableERC20Factory();
vm.prank(multisig);
factoryProxy.upgradeToAndCall(
address(L1TokenFactoryImpl), abi.encodeCall(OptimismMintableERC20Factory.initialize, address(L1Bridge))
);
L1TokenFactory = OptimismMintableERC20Factory(address(factoryProxy));
RemoteL1Token = OptimismMintableERC20(
L1TokenFactory.createStandardL2Token(
l1OptimismMintableERC20Factory.createStandardL2Token(
address(NativeL2Token),
string(abi.encodePacked("L1-", NativeL2Token.name())),
string(abi.encodePacked("L1-", NativeL2Token.symbol()))
......@@ -440,7 +403,7 @@ contract Bridge_Initializer is Messenger_Initializer {
);
BadL1Token = OptimismMintableERC20(
L1TokenFactory.createStandardL2Token(
l1OptimismMintableERC20Factory.createStandardL2Token(
address(1),
string(abi.encodePacked("L1-", NativeL2Token.name())),
string(abi.encodePacked("L1-", NativeL2Token.symbol()))
......@@ -449,52 +412,7 @@ contract Bridge_Initializer is Messenger_Initializer {
}
}
contract ERC721Bridge_Initializer is Bridge_Initializer {
L1ERC721Bridge L1NFTBridge;
L2ERC721Bridge L2NFTBridge;
function setUp() public virtual override {
super.setUp();
// Deploy the L1ERC721Bridge.
L1ERC721Bridge l1BridgeImpl = new L1ERC721Bridge();
Proxy l1BridgeProxy = new Proxy(multisig);
vm.prank(multisig);
l1BridgeProxy.upgradeToAndCall(
address(l1BridgeImpl), abi.encodeCall(L1ERC721Bridge.initialize, (CrossDomainMessenger(L1Messenger)))
);
L1NFTBridge = L1ERC721Bridge(address(l1BridgeProxy));
// Deploy the implementation for the L2ERC721Bridge and etch it into the predeploy address.
L2ERC721Bridge l2BridgeImpl = new L2ERC721Bridge(address(L1NFTBridge));
Proxy l2BridgeProxy = new Proxy(multisig);
vm.etch(Predeploys.L2_ERC721_BRIDGE, address(l2BridgeProxy).code);
// set the storage slot for admin
bytes32 OWNER_KEY = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
vm.store(Predeploys.L2_ERC721_BRIDGE, OWNER_KEY, bytes32(uint256(uint160(multisig))));
vm.prank(multisig);
Proxy(payable(Predeploys.L2_ERC721_BRIDGE)).upgradeToAndCall(
address(l2BridgeImpl), abi.encodeCall(L2ERC721Bridge.initialize, ())
);
// Set up a reference to the L2ERC721Bridge.
L2NFTBridge = L2ERC721Bridge(Predeploys.L2_ERC721_BRIDGE);
// Label the L1 and L2 bridges.
vm.label(address(L1NFTBridge), "L1ERC721Bridge");
vm.label(address(L2NFTBridge), "L2ERC721Bridge");
}
}
contract FeeVault_Initializer is Bridge_Initializer {
SequencerFeeVault vault = SequencerFeeVault(payable(Predeploys.SEQUENCER_FEE_WALLET));
address constant recipient = address(1024);
event Withdrawal(uint256 value, address to, address from);
event Withdrawal(uint256 value, address to, address from, FeeVault.WithdrawalNetwork withdrawalNetwork);
}
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
// Testing utilities
import { Test } from "forge-std/Test.sol";
import { Messenger_Initializer, Test } from "test/CommonTest.t.sol";
import { L1CrossDomainMessenger } from "src/L1/L1CrossDomainMessenger.sol";
import { Reverter, CallerCaller } from "test/mocks/Callers.sol";
import { Messenger_Initializer } from "test/CommonTest.t.sol";
import { CallerCaller, Reverter } from "test/mocks/Callers.sol";
// Libraries
import { Predeploys } from "src/libraries/Predeploys.sol";
import { Hashing } from "src/libraries/Hashing.sol";
import { Encoding } from "src/libraries/Encoding.sol";
import { L1CrossDomainMessenger } from "src/L1/L1CrossDomainMessenger.sol";
// CrossDomainMessenger_Test is for testing functionality which is common to both the L1 and L2
// CrossDomainMessenger contracts. For simplicity, we use the L1 Messenger as the test contract.
contract CrossDomainMessenger_BaseGas_Test is Messenger_Initializer {
/// @dev Ensure that baseGas passes for the max value of _minGasLimit,
/// this is about 4 Billion.
function test_baseGas_succeeds() external view {
L1Messenger.baseGas(hex"ff", type(uint32).max);
l1CrossDomainMessenger.baseGas(hex"ff", type(uint32).max);
}
/// @dev Fuzz for other values which might cause a revert in baseGas.
function testFuzz_baseGas_succeeds(uint32 _minGasLimit) external view {
L1Messenger.baseGas(hex"ff", _minGasLimit);
l1CrossDomainMessenger.baseGas(hex"ff", _minGasLimit);
}
/// @notice The baseGas function should always return a value greater than
......@@ -33,8 +34,8 @@ contract CrossDomainMessenger_BaseGas_Test is Messenger_Initializer {
/// gas to the OptimismPortal.
function testFuzz_baseGas_portalMinGasLimit_succeeds(bytes memory _data, uint32 _minGasLimit) external {
vm.assume(_data.length <= type(uint64).max);
uint64 baseGas = L1Messenger.baseGas(_data, _minGasLimit);
uint64 minGasLimit = op.minimumGasLimit(uint64(_data.length));
uint64 baseGas = l1CrossDomainMessenger.baseGas(_data, _minGasLimit);
uint64 minGasLimit = optimismPortal.minimumGasLimit(uint64(_data.length));
assertTrue(baseGas >= minGasLimit);
}
}
......@@ -45,18 +46,18 @@ contract CrossDomainMessenger_BaseGas_Test is Messenger_Initializer {
contract ExternalRelay is Test {
address internal op;
address internal fuzzedSender;
L1CrossDomainMessenger internal L1Messenger;
L1CrossDomainMessenger internal l1CrossDomainMessenger;
event FailedRelayedMessage(bytes32 indexed msgHash);
constructor(L1CrossDomainMessenger _l1Messenger, address _op) {
L1Messenger = _l1Messenger;
l1CrossDomainMessenger = _l1Messenger;
op = _op;
}
/// @notice Internal helper function to relay a message and perform assertions.
function _internalRelay(address _innerSender) internal {
address initialSender = L1Messenger.xDomainMessageSender();
address initialSender = l1CrossDomainMessenger.xDomainMessageSender();
bytes memory callMessage = getCallData();
......@@ -73,7 +74,7 @@ contract ExternalRelay is Test {
emit FailedRelayedMessage(hash);
vm.prank(address(op));
L1Messenger.relayMessage({
l1CrossDomainMessenger.relayMessage({
_nonce: Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),
_sender: _innerSender,
_target: address(this),
......@@ -82,9 +83,9 @@ contract ExternalRelay is Test {
_message: callMessage
});
assertTrue(L1Messenger.failedMessages(hash));
assertFalse(L1Messenger.successfulMessages(hash));
assertEq(initialSender, L1Messenger.xDomainMessageSender());
assertTrue(l1CrossDomainMessenger.failedMessages(hash));
assertFalse(l1CrossDomainMessenger.successfulMessages(hash));
assertEq(initialSender, l1CrossDomainMessenger.xDomainMessageSender());
}
/// @notice externalCallWithMinGas is called by the CrossDomainMessenger.
......@@ -119,7 +120,7 @@ contract CrossDomainMessenger_RelayMessage_Test is Messenger_Initializer {
function setUp() public override {
super.setUp();
er = new ExternalRelay(L1Messenger, address(op));
er = new ExternalRelay(l1CrossDomainMessenger, address(optimismPortal));
}
/// @dev This test mocks an OptimismPortal call to the L1CrossDomainMessenger via
......@@ -151,9 +152,9 @@ contract CrossDomainMessenger_RelayMessage_Test is Messenger_Initializer {
});
// set the value of op.l2Sender() to be the L2 Cross Domain Messenger.
vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));
vm.prank(address(op));
L1Messenger.relayMessage({
vm.store(address(optimismPortal), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));
vm.prank(address(optimismPortal));
l1CrossDomainMessenger.relayMessage({
_nonce: Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),
_sender: sender,
_target: target,
......@@ -162,11 +163,11 @@ contract CrossDomainMessenger_RelayMessage_Test is Messenger_Initializer {
_message: callMessage
});
assertTrue(L1Messenger.successfulMessages(hash));
assertEq(L1Messenger.failedMessages(hash), false);
assertTrue(l1CrossDomainMessenger.successfulMessages(hash));
assertEq(l1CrossDomainMessenger.failedMessages(hash), false);
// Ensures that the `xDomainMsgSender` is set back to `Predeploys.L2_CROSS_DOMAIN_MESSENGER`
vm.expectRevert("CrossDomainMessenger: xDomainMessageSender is not set");
L1Messenger.xDomainMessageSender();
l1CrossDomainMessenger.xDomainMessageSender();
}
}
......@@ -63,7 +63,7 @@ contract CrossDomainOwnableThroughPortal_Test is Portal_Initializer {
vm.recordLogs();
vm.prank(alice);
op.depositTransaction({
optimismPortal.depositTransaction({
_to: address(setter),
_value: 0,
_gasLimit: 30_000,
......
......@@ -44,9 +44,9 @@ contract CrossDomainOwnable2_Test is Messenger_Initializer {
// set the xDomainMsgSender storage slot
bytes32 key = bytes32(uint256(204));
bytes32 value = Bytes32AddressLib.fillLast12Bytes(address(alice));
vm.store(address(L2Messenger), key, value);
vm.store(address(l2CrossDomainMessenger), key, value);
vm.prank(address(L2Messenger));
vm.prank(address(l2CrossDomainMessenger));
vm.expectRevert("CrossDomainOwnable2: caller is not the owner");
setter.set(1);
}
......@@ -69,8 +69,10 @@ contract CrossDomainOwnable2_Test is Messenger_Initializer {
vm.expectEmit(true, true, true, true);
emit FailedRelayedMessage(hash);
vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)));
L2Messenger.relayMessage(Encoding.encodeVersionedNonce(nonce, 1), sender, target, value, minGasLimit, message);
vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger)));
l2CrossDomainMessenger.relayMessage(
Encoding.encodeVersionedNonce(nonce, 1), sender, target, value, minGasLimit, message
);
assertEq(setter.value(), 0);
}
......@@ -81,8 +83,8 @@ contract CrossDomainOwnable2_Test is Messenger_Initializer {
// Simulate the L2 execution where the call is coming from
// the L1CrossDomainMessenger
vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)));
L2Messenger.relayMessage(
vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger)));
l2CrossDomainMessenger.relayMessage(
Encoding.encodeVersionedNonce(1, 1),
owner,
address(setter),
......
......@@ -73,9 +73,9 @@ contract CrossDomainOwnable3_Test is Messenger_Initializer {
// set the xDomainMsgSender storage slot
bytes32 key = bytes32(uint256(204));
bytes32 value = Bytes32AddressLib.fillLast12Bytes(bob);
vm.store(address(L2Messenger), key, value);
vm.store(address(l2CrossDomainMessenger), key, value);
vm.prank(address(L2Messenger));
vm.prank(address(l2CrossDomainMessenger));
vm.expectRevert("CrossDomainOwnable3: caller is not the owner");
setter.set(1);
}
......@@ -109,11 +109,13 @@ contract CrossDomainOwnable3_Test is Messenger_Initializer {
// It should be a failed message. The revert is caught,
// so we cannot expectRevert here.
vm.expectEmit(true, true, true, true, address(L2Messenger));
vm.expectEmit(true, true, true, true, address(l2CrossDomainMessenger));
emit FailedRelayedMessage(hash);
vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)));
L2Messenger.relayMessage(Encoding.encodeVersionedNonce(nonce, 1), sender, target, value, minGasLimit, message);
vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger)));
l2CrossDomainMessenger.relayMessage(
Encoding.encodeVersionedNonce(nonce, 1), sender, target, value, minGasLimit, message
);
assertEq(setter.value(), 0);
}
......@@ -212,8 +214,8 @@ contract CrossDomainOwnable3_Test is Messenger_Initializer {
// Simulate the L2 execution where the call is coming from
// the L1CrossDomainMessenger
vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)));
L2Messenger.relayMessage(
vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger)));
l2CrossDomainMessenger.relayMessage(
Encoding.encodeVersionedNonce(1, 1),
bob,
address(setter),
......
......@@ -146,7 +146,7 @@ contract DelayedVetoable_HandleCall_TestFail is DelayedVetoable_Init {
/// @dev Only the initiator can initiate a call.
function test_handleCall_unauthorizedInitiation_reverts() external {
vm.expectRevert(abi.encodeWithSelector(Unauthorized.selector, initiator, address(this)));
(bool success,) = address(delayedVetoable).call(NON_ZERO_DATA);
(bool success,) = address(delayedVetoable).call(hex"00001234");
assertTrue(success);
}
......
......@@ -37,9 +37,9 @@ contract FaultDisputeGame_Init is DisputeGameFactory_Init {
vm.warp(1690906994);
// Propose 2 mock outputs
vm.startPrank(oracle.PROPOSER());
vm.startPrank(l2OutputOracle.PROPOSER());
for (uint256 i; i < 2; i++) {
oracle.proposeL2Output(bytes32(i + 1), oracle.nextBlockNumber(), blockhash(i), i);
l2OutputOracle.proposeL2Output(bytes32(i + 1), l2OutputOracle.nextBlockNumber(), blockhash(i), i);
// Advance 1 block
vm.roll(block.number + 1);
......@@ -52,7 +52,7 @@ contract FaultDisputeGame_Init is DisputeGameFactory_Init {
blockOracle.checkpoint();
// Set the extra data for the game creation
extraData = abi.encode(oracle.SUBMISSION_INTERVAL() * 2, block.number - 1);
extraData = abi.encode(l2OutputOracle.SUBMISSION_INTERVAL() * 2, block.number - 1);
// Deploy an implementation of the fault game
gameImpl = new FaultDisputeGame(
......@@ -61,7 +61,7 @@ contract FaultDisputeGame_Init is DisputeGameFactory_Init {
4,
Duration.wrap(7 days),
new AlphabetVM(absolutePrestate),
oracle,
l2OutputOracle,
blockOracle
);
// Register the game implementation with the factory.
......@@ -127,7 +127,7 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
function test_initialize_l1HeadTooOld_reverts() public {
// Store a mock block hash for the genesis block. The timestamp will default to 0.
vm.store(address(gameImpl.BLOCK_ORACLE()), keccak256(abi.encode(0, 0)), bytes32(uint256(1)));
bytes memory _extraData = abi.encode(oracle.SUBMISSION_INTERVAL() * 2, 0);
bytes memory _extraData = abi.encode(l2OutputOracle.SUBMISSION_INTERVAL() * 2, 0);
vm.expectRevert(L1HeadTooOld.selector);
factory.create(GAME_TYPE, ROOT_CLAIM, _extraData);
......@@ -138,11 +138,14 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
/// to dispute the first output root by using genesis as the starting point.
/// For now, it is critical that the first proposed output root of an OP stack
/// chain is done so by an honest party.
/*
function test_initialize_firstOutput_reverts() public {
uint256 submissionInterval = oracle.SUBMISSION_INTERVAL();
vm.expectRevert(abi.encodeWithSignature("Panic(uint256)", 0x11));
factory.create(GAME_TYPE, ROOT_CLAIM, abi.encode(submissionInterval, block.number - 1));
}
*/
/// @dev Tests that the `create` function reverts when the rootClaim does not disagree with the outcome.
function testFuzz_initialize_badRootStatus_reverts(Claim rootClaim, bytes calldata extraData) public {
......@@ -160,12 +163,12 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
// Starting
(FaultDisputeGame.OutputProposal memory startingProp, FaultDisputeGame.OutputProposal memory disputedProp) =
gameProxy.proposals();
Types.OutputProposal memory starting = oracle.getL2Output(startingProp.index);
Types.OutputProposal memory starting = l2OutputOracle.getL2Output(startingProp.index);
assertEq(startingProp.index, 0);
assertEq(startingProp.l2BlockNumber, starting.l2BlockNumber);
assertEq(Hash.unwrap(startingProp.outputRoot), starting.outputRoot);
// Disputed
Types.OutputProposal memory disputed = oracle.getL2Output(disputedProp.index);
Types.OutputProposal memory disputed = l2OutputOracle.getL2Output(disputedProp.index);
assertEq(disputedProp.index, 1);
assertEq(disputedProp.l2BlockNumber, disputed.l2BlockNumber);
assertEq(Hash.unwrap(disputedProp.outputRoot), disputed.outputRoot);
......
......@@ -3,48 +3,23 @@ pragma solidity 0.8.15;
// Testing utilities
import { Bridge_Initializer } from "test/CommonTest.t.sol";
import { BaseFeeVault } from "src/L2/BaseFeeVault.sol";
import { StandardBridge } from "src/universal/StandardBridge.sol";
// Libraries
import { Predeploys } from "src/libraries/Predeploys.sol";
// Target contract dependencies
import { FeeVault } from "src/universal/FeeVault.sol";
// Target contract
import { L1FeeVault } from "src/L2/L1FeeVault.sol";
import { FeeVault } from "src/universal/FeeVault.sol";
// Test the implementations of the FeeVault
contract FeeVault_Test is Bridge_Initializer {
BaseFeeVault baseFeeVault = BaseFeeVault(payable(Predeploys.BASE_FEE_VAULT));
L1FeeVault l1FeeVault = L1FeeVault(payable(Predeploys.L1_FEE_VAULT));
uint256 constant otherMinimumWithdrawalAmount = 10 ether;
/// @dev Sets up the test suite.
function setUp() public override {
super.setUp();
vm.etch(
Predeploys.BASE_FEE_VAULT,
address(new BaseFeeVault(alice, NON_ZERO_VALUE, FeeVault.WithdrawalNetwork.L1)).code
);
vm.etch(
Predeploys.L1_FEE_VAULT,
address(new L1FeeVault(bob, otherMinimumWithdrawalAmount, FeeVault.WithdrawalNetwork.L2)).code
);
vm.label(Predeploys.BASE_FEE_VAULT, "BaseFeeVault");
vm.label(Predeploys.L1_FEE_VAULT, "L1FeeVault");
/// @dev Tests that the constructor sets the correct values.
function test_constructor_l1FeeVault_succeeds() external {
assertEq(l1FeeVault.RECIPIENT(), cfg.l1FeeVaultRecipient());
assertEq(l1FeeVault.MIN_WITHDRAWAL_AMOUNT(), cfg.l1FeeVaultMinimumWithdrawalAmount());
assertEq(uint8(l1FeeVault.WITHDRAWAL_NETWORK()), uint8(FeeVault.WithdrawalNetwork.L2));
}
/// @dev Tests that the constructor sets the correct values.
function test_constructor_succeeds() external {
assertEq(baseFeeVault.RECIPIENT(), alice);
assertEq(l1FeeVault.RECIPIENT(), bob);
assertEq(baseFeeVault.MIN_WITHDRAWAL_AMOUNT(), NON_ZERO_VALUE);
assertEq(l1FeeVault.MIN_WITHDRAWAL_AMOUNT(), otherMinimumWithdrawalAmount);
function test_constructor_baseFeeVault_succeeds() external {
assertEq(baseFeeVault.RECIPIENT(), cfg.baseFeeVaultRecipient());
assertEq(baseFeeVault.MIN_WITHDRAWAL_AMOUNT(), cfg.baseFeeVaultMinimumWithdrawalAmount());
assertEq(uint8(baseFeeVault.WITHDRAWAL_NETWORK()), uint8(FeeVault.WithdrawalNetwork.L1));
assertEq(uint8(l1FeeVault.WITHDRAWAL_NETWORK()), uint8(FeeVault.WithdrawalNetwork.L2));
}
}
......@@ -4,20 +4,11 @@ pragma solidity 0.8.15;
// Testing utilities
import { CommonTest } from "test/CommonTest.t.sol";
// Target contract dependencies
import { L1Block } from "src/L2/L1Block.sol";
import { Predeploys } from "src/libraries/Predeploys.sol";
// Target contract
import { GasPriceOracle } from "src/L2/GasPriceOracle.sol";
contract GasPriceOracle_Test is CommonTest {
event OverheadUpdated(uint256);
event ScalarUpdated(uint256);
event DecimalsUpdated(uint256);
GasPriceOracle gasOracle;
L1Block l1Block;
address depositor;
// The initial L1 context values
......@@ -33,17 +24,9 @@ contract GasPriceOracle_Test is CommonTest {
/// @dev Sets up the test suite.
function setUp() public virtual override {
super.setUp();
// place the L1Block contract at the predeploy address
vm.etch(Predeploys.L1_BLOCK_ATTRIBUTES, address(new L1Block()).code);
l1Block = L1Block(Predeploys.L1_BLOCK_ATTRIBUTES);
depositor = l1Block.DEPOSITOR_ACCOUNT();
// We are not setting the gas oracle at its predeploy
// address for simplicity purposes. Nothing in this test
// requires it to be at a particular address
gasOracle = new GasPriceOracle();
vm.prank(depositor);
l1Block.setL1BlockValues({
_number: number,
......@@ -59,43 +42,43 @@ contract GasPriceOracle_Test is CommonTest {
/// @dev Tests that `l1BaseFee` is set correctly.
function test_l1BaseFee_succeeds() external {
assertEq(gasOracle.l1BaseFee(), basefee);
assertEq(gasPriceOracle.l1BaseFee(), basefee);
}
/// @dev Tests that `gasPrice` is set correctly.
function test_gasPrice_succeeds() external {
vm.fee(100);
uint256 gasPrice = gasOracle.gasPrice();
uint256 gasPrice = gasPriceOracle.gasPrice();
assertEq(gasPrice, 100);
}
/// @dev Tests that `baseFee` is set correctly.
function test_baseFee_succeeds() external {
vm.fee(64);
uint256 gasPrice = gasOracle.baseFee();
uint256 gasPrice = gasPriceOracle.baseFee();
assertEq(gasPrice, 64);
}
/// @dev Tests that `scalar` is set correctly.
function test_scalar_succeeds() external {
assertEq(gasOracle.scalar(), l1FeeScalar);
assertEq(gasPriceOracle.scalar(), l1FeeScalar);
}
/// @dev Tests that `overhead` is set correctly.
function test_overhead_succeeds() external {
assertEq(gasOracle.overhead(), l1FeeOverhead);
assertEq(gasPriceOracle.overhead(), l1FeeOverhead);
}
/// @dev Tests that `decimals` is set correctly.
function test_decimals_succeeds() external {
assertEq(gasOracle.decimals(), 6);
assertEq(gasOracle.DECIMALS(), 6);
assertEq(gasPriceOracle.decimals(), 6);
assertEq(gasPriceOracle.DECIMALS(), 6);
}
/// @dev Tests that `setGasPrice` reverts since it was removed in bedrock.
function test_setGasPrice_doesNotExist_reverts() external {
(bool success, bytes memory returndata) =
address(gasOracle).call(abi.encodeWithSignature("setGasPrice(uint256)", 1));
address(gasPriceOracle).call(abi.encodeWithSignature("setGasPrice(uint256)", 1));
assertEq(success, false);
assertEq(returndata, hex"");
......@@ -104,7 +87,7 @@ contract GasPriceOracle_Test is CommonTest {
/// @dev Tests that `setL1BaseFee` reverts since it was removed in bedrock.
function test_setL1BaseFee_doesNotExist_reverts() external {
(bool success, bytes memory returndata) =
address(gasOracle).call(abi.encodeWithSignature("setL1BaseFee(uint256)", 1));
address(gasPriceOracle).call(abi.encodeWithSignature("setL1BaseFee(uint256)", 1));
assertEq(success, false);
assertEq(returndata, hex"");
......
......@@ -4,39 +4,35 @@ pragma solidity 0.8.15;
// Testing utilities
import { CommonTest } from "test/CommonTest.t.sol";
// Target contract
import { GovernanceToken } from "src/governance/GovernanceToken.sol";
contract GovernanceToken_Test is CommonTest {
address constant owner = address(0x1234);
address constant rando = address(0x5678);
GovernanceToken internal gov;
address owner;
address rando;
/// @dev Sets up the test suite.
function setUp() public virtual override {
super.setUp();
vm.prank(owner);
gov = new GovernanceToken();
owner = governanceToken.owner();
rando = makeAddr("rando");
}
/// @dev Tests that the constructor sets the correct initial state.
function test_constructor_succeeds() external {
assertEq(gov.owner(), owner);
assertEq(gov.name(), "Optimism");
assertEq(gov.symbol(), "OP");
assertEq(gov.decimals(), 18);
assertEq(gov.totalSupply(), 0);
assertEq(governanceToken.owner(), owner);
assertEq(governanceToken.name(), "Optimism");
assertEq(governanceToken.symbol(), "OP");
assertEq(governanceToken.decimals(), 18);
assertEq(governanceToken.totalSupply(), 0);
}
/// @dev Tests that the owner can successfully call `mint`.
function test_mint_fromOwner_succeeds() external {
// Mint 100 tokens.
vm.prank(owner);
gov.mint(owner, 100);
governanceToken.mint(owner, 100);
// Balances have updated correctly.
assertEq(gov.balanceOf(owner), 100);
assertEq(gov.totalSupply(), 100);
assertEq(governanceToken.balanceOf(owner), 100);
assertEq(governanceToken.totalSupply(), 100);
}
/// @dev Tests that `mint` reverts when called by a non-owner.
......@@ -44,130 +40,130 @@ contract GovernanceToken_Test is CommonTest {
// Mint 100 tokens as rando.
vm.prank(rando);
vm.expectRevert("Ownable: caller is not the owner");
gov.mint(owner, 100);
governanceToken.mint(owner, 100);
// Balance does not update.
assertEq(gov.balanceOf(owner), 0);
assertEq(gov.totalSupply(), 0);
assertEq(governanceToken.balanceOf(owner), 0);
assertEq(governanceToken.totalSupply(), 0);
}
/// @dev Tests that the owner can successfully call `burn`.
function test_burn_succeeds() external {
// Mint 100 tokens to rando.
vm.prank(owner);
gov.mint(rando, 100);
governanceToken.mint(rando, 100);
// Rando burns their tokens.
vm.prank(rando);
gov.burn(50);
governanceToken.burn(50);
// Balances have updated correctly.
assertEq(gov.balanceOf(rando), 50);
assertEq(gov.totalSupply(), 50);
assertEq(governanceToken.balanceOf(rando), 50);
assertEq(governanceToken.totalSupply(), 50);
}
/// @dev Tests that the owner can successfully call `burnFrom`.
function test_burnFrom_succeeds() external {
// Mint 100 tokens to rando.
vm.prank(owner);
gov.mint(rando, 100);
governanceToken.mint(rando, 100);
// Rando approves owner to burn 50 tokens.
vm.prank(rando);
gov.approve(owner, 50);
governanceToken.approve(owner, 50);
// Owner burns 50 tokens from rando.
vm.prank(owner);
gov.burnFrom(rando, 50);
governanceToken.burnFrom(rando, 50);
// Balances have updated correctly.
assertEq(gov.balanceOf(rando), 50);
assertEq(gov.totalSupply(), 50);
assertEq(governanceToken.balanceOf(rando), 50);
assertEq(governanceToken.totalSupply(), 50);
}
/// @dev Tests that `transfer` correctly transfers tokens.
function test_transfer_succeeds() external {
// Mint 100 tokens to rando.
vm.prank(owner);
gov.mint(rando, 100);
governanceToken.mint(rando, 100);
// Rando transfers 50 tokens to owner.
vm.prank(rando);
gov.transfer(owner, 50);
governanceToken.transfer(owner, 50);
// Balances have updated correctly.
assertEq(gov.balanceOf(owner), 50);
assertEq(gov.balanceOf(rando), 50);
assertEq(gov.totalSupply(), 100);
assertEq(governanceToken.balanceOf(owner), 50);
assertEq(governanceToken.balanceOf(rando), 50);
assertEq(governanceToken.totalSupply(), 100);
}
/// @dev Tests that `approve` correctly sets allowances.
function test_approve_succeeds() external {
// Mint 100 tokens to rando.
vm.prank(owner);
gov.mint(rando, 100);
governanceToken.mint(rando, 100);
// Rando approves owner to spend 50 tokens.
vm.prank(rando);
gov.approve(owner, 50);
governanceToken.approve(owner, 50);
// Allowances have updated.
assertEq(gov.allowance(rando, owner), 50);
assertEq(governanceToken.allowance(rando, owner), 50);
}
/// @dev Tests that `transferFrom` correctly transfers tokens.
function test_transferFrom_succeeds() external {
// Mint 100 tokens to rando.
vm.prank(owner);
gov.mint(rando, 100);
governanceToken.mint(rando, 100);
// Rando approves owner to spend 50 tokens.
vm.prank(rando);
gov.approve(owner, 50);
governanceToken.approve(owner, 50);
// Owner transfers 50 tokens from rando to owner.
vm.prank(owner);
gov.transferFrom(rando, owner, 50);
governanceToken.transferFrom(rando, owner, 50);
// Balances have updated correctly.
assertEq(gov.balanceOf(owner), 50);
assertEq(gov.balanceOf(rando), 50);
assertEq(gov.totalSupply(), 100);
assertEq(governanceToken.balanceOf(owner), 50);
assertEq(governanceToken.balanceOf(rando), 50);
assertEq(governanceToken.totalSupply(), 100);
}
/// @dev Tests that `increaseAllowance` correctly increases allowances.
function test_increaseAllowance_succeeds() external {
// Mint 100 tokens to rando.
vm.prank(owner);
gov.mint(rando, 100);
governanceToken.mint(rando, 100);
// Rando approves owner to spend 50 tokens.
vm.prank(rando);
gov.approve(owner, 50);
governanceToken.approve(owner, 50);
// Rando increases allowance by 50 tokens.
vm.prank(rando);
gov.increaseAllowance(owner, 50);
governanceToken.increaseAllowance(owner, 50);
// Allowances have updated.
assertEq(gov.allowance(rando, owner), 100);
assertEq(governanceToken.allowance(rando, owner), 100);
}
/// @dev Tests that `decreaseAllowance` correctly decreases allowances.
function test_decreaseAllowance_succeeds() external {
// Mint 100 tokens to rando.
vm.prank(owner);
gov.mint(rando, 100);
governanceToken.mint(rando, 100);
// Rando approves owner to spend 100 tokens.
vm.prank(rando);
gov.approve(owner, 100);
governanceToken.approve(owner, 100);
// Rando decreases allowance by 50 tokens.
vm.prank(rando);
gov.decreaseAllowance(owner, 50);
governanceToken.decreaseAllowance(owner, 50);
// Allowances have updated.
assertEq(gov.allowance(rando, owner), 50);
assertEq(governanceToken.allowance(rando, owner), 50);
}
}
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
import { ERC721Bridge_Initializer } from "test/CommonTest.t.sol";
import { console } from "forge-std/console.sol";
import { Bridge_Initializer } from "test/CommonTest.t.sol";
import { CrossDomainMessenger } from "src/universal/CrossDomainMessenger.sol";
import { L2OutputOracle } from "src/L1/L2OutputOracle.sol";
import { SystemConfig } from "src/L1/SystemConfig.sol";
......@@ -13,19 +12,19 @@ import { OptimismPortal } from "src/L1/OptimismPortal.sol";
/// @dev Ensures that the `initialize()` function on contracts cannot be called more than
/// once. This contract inherits from `ERC721Bridge_Initializer` because it is the
/// deepest contract in the inheritance chain for setting up the system contracts.
contract Initializer_Test is ERC721Bridge_Initializer {
contract Initializer_Test is Bridge_Initializer {
function test_cannotReinitializeL1_succeeds() public {
vm.expectRevert("Initializable: contract is already initialized");
L1Messenger.initialize(OptimismPortal(payable(address(0))));
l1CrossDomainMessenger.initialize(OptimismPortal(payable(address(0))));
vm.expectRevert("Initializable: contract is already initialized");
L1Bridge.initialize(CrossDomainMessenger(address(0)));
l1StandardBridge.initialize(CrossDomainMessenger(address(0)));
vm.expectRevert("Initializable: contract is already initialized");
oracle.initialize(0, 0, address(0), address(0));
l2OutputOracle.initialize(0, 0, address(0), address(0));
vm.expectRevert("Initializable: contract is already initialized");
op.initialize(L2OutputOracle(address(0)), address(0), SystemConfig(address(0)), false);
optimismPortal.initialize(L2OutputOracle(address(0)), address(0), SystemConfig(address(0)), false);
vm.expectRevert("Initializable: contract is already initialized");
systemConfig.initialize({
......@@ -56,6 +55,6 @@ contract Initializer_Test is ERC721Bridge_Initializer {
});
vm.expectRevert("Initializable: contract is already initialized");
L1NFTBridge.initialize(CrossDomainMessenger(address(0)));
l1ERC721Bridge.initialize(CrossDomainMessenger(address(0)));
}
}
......@@ -8,21 +8,19 @@ import { CommonTest } from "test/CommonTest.t.sol";
import { L1Block } from "src/L2/L1Block.sol";
contract L1BlockTest is CommonTest {
L1Block lb;
address depositor;
bytes32 immutable NON_ZERO_HASH = keccak256(abi.encode(1));
/// @dev Sets up the test suite.
function setUp() public virtual override {
super.setUp();
lb = new L1Block();
depositor = lb.DEPOSITOR_ACCOUNT();
depositor = l1Block.DEPOSITOR_ACCOUNT();
vm.prank(depositor);
lb.setL1BlockValues({
l1Block.setL1BlockValues({
_number: uint64(1),
_timestamp: uint64(2),
_basefee: 3,
_hash: NON_ZERO_HASH,
_hash: keccak256(abi.encode(block.number)),
_sequenceNumber: uint64(4),
_batcherHash: bytes32(0),
_l1FeeOverhead: 2,
......@@ -44,46 +42,46 @@ contract L1BlockTest is CommonTest {
external
{
vm.prank(depositor);
lb.setL1BlockValues(n, t, b, h, s, bt, fo, fs);
assertEq(lb.number(), n);
assertEq(lb.timestamp(), t);
assertEq(lb.basefee(), b);
assertEq(lb.hash(), h);
assertEq(lb.sequenceNumber(), s);
assertEq(lb.batcherHash(), bt);
assertEq(lb.l1FeeOverhead(), fo);
assertEq(lb.l1FeeScalar(), fs);
l1Block.setL1BlockValues(n, t, b, h, s, bt, fo, fs);
assertEq(l1Block.number(), n);
assertEq(l1Block.timestamp(), t);
assertEq(l1Block.basefee(), b);
assertEq(l1Block.hash(), h);
assertEq(l1Block.sequenceNumber(), s);
assertEq(l1Block.batcherHash(), bt);
assertEq(l1Block.l1FeeOverhead(), fo);
assertEq(l1Block.l1FeeScalar(), fs);
}
/// @dev Tests that `number` returns the correct value.
function test_number_succeeds() external {
assertEq(lb.number(), uint64(1));
assertEq(l1Block.number(), uint64(1));
}
/// @dev Tests that `timestamp` returns the correct value.
function test_timestamp_succeeds() external {
assertEq(lb.timestamp(), uint64(2));
assertEq(l1Block.timestamp(), uint64(2));
}
/// @dev Tests that `basefee` returns the correct value.
function test_basefee_succeeds() external {
assertEq(lb.basefee(), 3);
assertEq(l1Block.basefee(), 3);
}
/// @dev Tests that `hash` returns the correct value.
function test_hash_succeeds() external {
assertEq(lb.hash(), NON_ZERO_HASH);
assertEq(l1Block.hash(), keccak256(abi.encode(block.number)));
}
/// @dev Tests that `sequenceNumber` returns the correct value.
function test_sequenceNumber_succeeds() external {
assertEq(lb.sequenceNumber(), uint64(4));
assertEq(l1Block.sequenceNumber(), uint64(4));
}
/// @dev Tests that `setL1BlockValues` can set max values.
function test_updateValues_succeeds() external {
vm.prank(depositor);
lb.setL1BlockValues({
l1Block.setL1BlockValues({
_number: type(uint64).max,
_timestamp: type(uint64).max,
_basefee: type(uint256).max,
......
......@@ -24,8 +24,8 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
/// @dev Tests that the version can be decoded from the message nonce.
function test_messageVersion_succeeds() external {
(, uint16 version) = Encoding.decodeVersionedNonce(L1Messenger.messageNonce());
assertEq(version, L1Messenger.MESSAGE_VERSION());
(, uint16 version) = Encoding.decodeVersionedNonce(l1CrossDomainMessenger.messageNonce());
assertEq(version, l1CrossDomainMessenger.MESSAGE_VERSION());
}
/// @dev Tests that the sendMessage function is able to send a single message.
......@@ -34,55 +34,57 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
function test_sendMessage_succeeds() external {
// deposit transaction on the optimism portal should be called
vm.expectCall(
address(op),
address(optimismPortal),
abi.encodeWithSelector(
OptimismPortal.depositTransaction.selector,
Predeploys.L2_CROSS_DOMAIN_MESSENGER,
0,
L1Messenger.baseGas(hex"ff", 100),
l1CrossDomainMessenger.baseGas(hex"ff", 100),
false,
Encoding.encodeCrossDomainMessage(L1Messenger.messageNonce(), alice, recipient, 0, 100, hex"ff")
Encoding.encodeCrossDomainMessage(
l1CrossDomainMessenger.messageNonce(), alice, recipient, 0, 100, hex"ff"
)
)
);
// TransactionDeposited event
vm.expectEmit(true, true, true, true);
emitTransactionDeposited(
AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)),
AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger)),
Predeploys.L2_CROSS_DOMAIN_MESSENGER,
0,
0,
L1Messenger.baseGas(hex"ff", 100),
l1CrossDomainMessenger.baseGas(hex"ff", 100),
false,
Encoding.encodeCrossDomainMessage(L1Messenger.messageNonce(), alice, recipient, 0, 100, hex"ff")
Encoding.encodeCrossDomainMessage(l1CrossDomainMessenger.messageNonce(), alice, recipient, 0, 100, hex"ff")
);
// SentMessage event
vm.expectEmit(true, true, true, true);
emit SentMessage(recipient, alice, hex"ff", L1Messenger.messageNonce(), 100);
emit SentMessage(recipient, alice, hex"ff", l1CrossDomainMessenger.messageNonce(), 100);
// SentMessageExtension1 event
vm.expectEmit(true, true, true, true);
emit SentMessageExtension1(alice, 0);
vm.prank(alice);
L1Messenger.sendMessage(recipient, hex"ff", uint32(100));
l1CrossDomainMessenger.sendMessage(recipient, hex"ff", uint32(100));
}
/// @dev Tests that the sendMessage function is able to send
/// the same message twice.
function test_sendMessage_twice_succeeds() external {
uint256 nonce = L1Messenger.messageNonce();
L1Messenger.sendMessage(recipient, hex"aa", uint32(500_000));
L1Messenger.sendMessage(recipient, hex"aa", uint32(500_000));
uint256 nonce = l1CrossDomainMessenger.messageNonce();
l1CrossDomainMessenger.sendMessage(recipient, hex"aa", uint32(500_000));
l1CrossDomainMessenger.sendMessage(recipient, hex"aa", uint32(500_000));
// the nonce increments for each message sent
assertEq(nonce + 2, L1Messenger.messageNonce());
assertEq(nonce + 2, l1CrossDomainMessenger.messageNonce());
}
/// @dev Tests that the xDomainMessageSender reverts when not set.
function test_xDomainSender_notSet_reverts() external {
vm.expectRevert("CrossDomainMessenger: xDomainMessageSender is not set");
L1Messenger.xDomainMessageSender();
l1CrossDomainMessenger.xDomainMessageSender();
}
/// @dev Tests that the relayMessage function reverts when
......@@ -92,14 +94,14 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;
// Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.
vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));
vm.store(address(optimismPortal), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));
// Expect a revert.
vm.expectRevert("CrossDomainMessenger: only version 0 or 1 messages are supported at this time");
// Try to relay a v2 message.
vm.prank(address(op));
L2Messenger.relayMessage(
vm.prank(address(optimismPortal));
l2CrossDomainMessenger.relayMessage(
Encoding.encodeVersionedNonce({ _nonce: 0, _version: 2 }), // nonce
sender,
target,
......@@ -118,8 +120,8 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
vm.expectCall(target, hex"1111");
// set the value of op.l2Sender() to be the L2 Cross Domain Messenger.
vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));
vm.prank(address(op));
vm.store(address(optimismPortal), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));
vm.prank(address(optimismPortal));
vm.expectEmit(true, true, true, true);
......@@ -129,7 +131,7 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
emit RelayedMessage(hash);
L1Messenger.relayMessage(
l1CrossDomainMessenger.relayMessage(
Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), // nonce
sender,
target,
......@@ -139,28 +141,28 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
);
// the message hash is in the successfulMessages mapping
assert(L1Messenger.successfulMessages(hash));
assert(l1CrossDomainMessenger.successfulMessages(hash));
// it is not in the received messages mapping
assertEq(L1Messenger.failedMessages(hash), false);
assertEq(l1CrossDomainMessenger.failedMessages(hash), false);
}
/// @dev Tests that relayMessage reverts if attempting to relay a message
/// sent to an L1 system contract.
function test_relayMessage_toSystemContract_reverts() external {
// set the target to be the OptimismPortal
address target = address(op);
address target = address(optimismPortal);
address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;
bytes memory message = hex"1111";
vm.prank(address(op));
vm.prank(address(optimismPortal));
vm.expectRevert("CrossDomainMessenger: message cannot be replayed");
L1Messenger.relayMessage(
l1CrossDomainMessenger.relayMessage(
Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), sender, target, 0, 0, message
);
vm.store(address(op), 0, bytes32(abi.encode(sender)));
vm.store(address(optimismPortal), 0, bytes32(abi.encode(sender)));
vm.expectRevert("CrossDomainMessenger: message cannot be replayed");
L1Messenger.relayMessage(
l1CrossDomainMessenger.relayMessage(
Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), sender, target, 0, 0, message
);
}
......@@ -173,7 +175,7 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
bytes memory message = hex"1111";
vm.expectRevert("CrossDomainMessenger: value must be zero unless message is from a system address");
L1Messenger.relayMessage{ value: 100 }(
l1CrossDomainMessenger.relayMessage{ value: 100 }(
Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), sender, target, 0, 0, message
);
}
......@@ -182,18 +184,18 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
/// after a message is relayed.
function test_xDomainMessageSender_reset_succeeds() external {
vm.expectRevert("CrossDomainMessenger: xDomainMessageSender is not set");
L1Messenger.xDomainMessageSender();
l1CrossDomainMessenger.xDomainMessageSender();
address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;
vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));
vm.prank(address(op));
L1Messenger.relayMessage(
vm.store(address(optimismPortal), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));
vm.prank(address(optimismPortal));
l1CrossDomainMessenger.relayMessage(
Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), address(0), address(0), 0, 0, hex""
);
vm.expectRevert("CrossDomainMessenger: xDomainMessageSender is not set");
L1Messenger.xDomainMessageSender();
l1CrossDomainMessenger.xDomainMessageSender();
}
/// @dev Tests that relayMessage should successfully call the target contract after
......@@ -210,11 +212,11 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), sender, target, value, 0, hex"1111"
);
vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));
vm.store(address(optimismPortal), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));
vm.etch(target, address(new Reverter()).code);
vm.deal(address(op), value);
vm.prank(address(op));
L1Messenger.relayMessage{ value: value }(
vm.deal(address(optimismPortal), value);
vm.prank(address(optimismPortal));
l1CrossDomainMessenger.relayMessage{ value: value }(
Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), // nonce
sender,
target,
......@@ -223,10 +225,10 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
hex"1111"
);
assertEq(address(L1Messenger).balance, value);
assertEq(address(l1CrossDomainMessenger).balance, value);
assertEq(address(target).balance, 0);
assertEq(L1Messenger.successfulMessages(hash), false);
assertEq(L1Messenger.failedMessages(hash), true);
assertEq(l1CrossDomainMessenger.successfulMessages(hash), false);
assertEq(l1CrossDomainMessenger.failedMessages(hash), true);
vm.expectEmit(true, true, true, true);
......@@ -234,7 +236,7 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
vm.etch(target, address(0).code);
vm.prank(address(sender));
L1Messenger.relayMessage(
l1CrossDomainMessenger.relayMessage(
Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), // nonce
sender,
target,
......@@ -243,10 +245,10 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
hex"1111"
);
assertEq(address(L1Messenger).balance, 0);
assertEq(address(l1CrossDomainMessenger).balance, 0);
assertEq(address(target).balance, value);
assertEq(L1Messenger.successfulMessages(hash), true);
assertEq(L1Messenger.failedMessages(hash), true);
assertEq(l1CrossDomainMessenger.successfulMessages(hash), true);
assertEq(l1CrossDomainMessenger.failedMessages(hash), true);
}
/// @dev Tests that relayMessage should successfully call the target contract after
......@@ -268,7 +270,7 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
);
// Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.
vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));
vm.store(address(optimismPortal), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));
// Target should be called with expected data.
vm.expectCall(target, hex"1111");
......@@ -278,8 +280,8 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
emit RelayedMessage(hash);
// Relay the message.
vm.prank(address(op));
L1Messenger.relayMessage(
vm.prank(address(optimismPortal));
l1CrossDomainMessenger.relayMessage(
Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce
sender,
target,
......@@ -289,8 +291,8 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
);
// Message was successfully relayed.
assertEq(L1Messenger.successfulMessages(hash), true);
assertEq(L1Messenger.failedMessages(hash), false);
assertEq(l1CrossDomainMessenger.successfulMessages(hash), true);
assertEq(l1CrossDomainMessenger.failedMessages(hash), false);
}
/// @dev Tests that relayMessage should revert if the message is already replayed.
......@@ -310,20 +312,19 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
);
// Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.
vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));
vm.store(address(optimismPortal), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));
// Mark legacy message as already relayed.
uint256 successfulMessagesSlot = 203;
bytes32 oldHash = Hashing.hashCrossDomainMessageV0(target, sender, hex"1111", 0);
bytes32 slot = keccak256(abi.encode(oldHash, successfulMessagesSlot));
vm.store(address(L1Messenger), slot, bytes32(uint256(1)));
vm.store(address(l1CrossDomainMessenger), slot, bytes32(uint256(1)));
// Expect revert.
vm.expectRevert("CrossDomainMessenger: legacy withdrawal already relayed");
// Relay the message.
vm.prank(address(op));
L1Messenger.relayMessage(
vm.prank(address(optimismPortal));
l1CrossDomainMessenger.relayMessage(
Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce
sender,
target,
......@@ -333,8 +334,8 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
);
// Message was not relayed.
assertEq(L1Messenger.successfulMessages(hash), false);
assertEq(L1Messenger.failedMessages(hash), false);
assertEq(l1CrossDomainMessenger.successfulMessages(hash), false);
assertEq(l1CrossDomainMessenger.failedMessages(hash), false);
}
/// @dev Tests that relayMessage can be retried after a failure with a legacy message.
......@@ -355,7 +356,7 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
);
// Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.
vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));
vm.store(address(optimismPortal), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));
// Turn the target into a Reverter.
vm.etch(target, address(new Reverter()).code);
......@@ -368,9 +369,9 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
emit FailedRelayedMessage(hash);
// Relay the message.
vm.deal(address(op), value);
vm.prank(address(op));
L1Messenger.relayMessage{ value: value }(
vm.deal(address(optimismPortal), value);
vm.prank(address(optimismPortal));
l1CrossDomainMessenger.relayMessage{ value: value }(
Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce
sender,
target,
......@@ -380,10 +381,10 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
);
// Message failed.
assertEq(address(L1Messenger).balance, value);
assertEq(address(l1CrossDomainMessenger).balance, value);
assertEq(address(target).balance, 0);
assertEq(L1Messenger.successfulMessages(hash), false);
assertEq(L1Messenger.failedMessages(hash), true);
assertEq(l1CrossDomainMessenger.successfulMessages(hash), false);
assertEq(l1CrossDomainMessenger.failedMessages(hash), true);
// Make the target not revert anymore.
vm.etch(target, address(0).code);
......@@ -397,7 +398,7 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
// Retry the message.
vm.prank(address(sender));
L1Messenger.relayMessage(
l1CrossDomainMessenger.relayMessage(
Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce
sender,
target,
......@@ -407,10 +408,10 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
);
// Message was successfully relayed.
assertEq(address(L1Messenger).balance, 0);
assertEq(address(l1CrossDomainMessenger).balance, 0);
assertEq(address(target).balance, value);
assertEq(L1Messenger.successfulMessages(hash), true);
assertEq(L1Messenger.failedMessages(hash), true);
assertEq(l1CrossDomainMessenger.successfulMessages(hash), true);
assertEq(l1CrossDomainMessenger.failedMessages(hash), true);
}
/// @dev Tests that relayMessage cannot be retried after success with a legacy message.
......@@ -431,7 +432,7 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
);
// Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.
vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));
vm.store(address(optimismPortal), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));
// Target should be called with expected data.
vm.expectCall(target, hex"1111");
......@@ -441,9 +442,9 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
emit RelayedMessage(hash);
// Relay the message.
vm.deal(address(op), value);
vm.prank(address(op));
L1Messenger.relayMessage{ value: value }(
vm.deal(address(optimismPortal), value);
vm.prank(address(optimismPortal));
l1CrossDomainMessenger.relayMessage{ value: value }(
Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce
sender,
target,
......@@ -453,17 +454,17 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
);
// Message was successfully relayed.
assertEq(address(L1Messenger).balance, 0);
assertEq(address(l1CrossDomainMessenger).balance, 0);
assertEq(address(target).balance, value);
assertEq(L1Messenger.successfulMessages(hash), true);
assertEq(L1Messenger.failedMessages(hash), false);
assertEq(l1CrossDomainMessenger.successfulMessages(hash), true);
assertEq(l1CrossDomainMessenger.failedMessages(hash), false);
// Expect a revert.
vm.expectRevert("CrossDomainMessenger: message cannot be replayed");
// Retry the message.
vm.prank(address(sender));
L1Messenger.relayMessage(
l1CrossDomainMessenger.relayMessage(
Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce
sender,
target,
......@@ -491,7 +492,7 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
);
// Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.
vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));
vm.store(address(optimismPortal), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));
// Turn the target into a Reverter.
vm.etch(target, address(new Reverter()).code);
......@@ -500,9 +501,9 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
vm.expectCall(target, hex"1111");
// Relay the message.
vm.deal(address(op), value);
vm.prank(address(op));
L1Messenger.relayMessage{ value: value }(
vm.deal(address(optimismPortal), value);
vm.prank(address(optimismPortal));
l1CrossDomainMessenger.relayMessage{ value: value }(
Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce
sender,
target,
......@@ -512,10 +513,10 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
);
// Message failed.
assertEq(address(L1Messenger).balance, value);
assertEq(address(l1CrossDomainMessenger).balance, value);
assertEq(address(target).balance, 0);
assertEq(L1Messenger.successfulMessages(hash), false);
assertEq(L1Messenger.failedMessages(hash), true);
assertEq(l1CrossDomainMessenger.successfulMessages(hash), false);
assertEq(l1CrossDomainMessenger.failedMessages(hash), true);
// Make the target not revert anymore.
vm.etch(target, address(0).code);
......@@ -529,7 +530,7 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
// Retry the message
vm.prank(address(sender));
L1Messenger.relayMessage(
l1CrossDomainMessenger.relayMessage(
Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce
sender,
target,
......@@ -539,17 +540,17 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
);
// Message was successfully relayed.
assertEq(address(L1Messenger).balance, 0);
assertEq(address(l1CrossDomainMessenger).balance, 0);
assertEq(address(target).balance, value);
assertEq(L1Messenger.successfulMessages(hash), true);
assertEq(L1Messenger.failedMessages(hash), true);
assertEq(l1CrossDomainMessenger.successfulMessages(hash), true);
assertEq(l1CrossDomainMessenger.failedMessages(hash), true);
// Expect a revert.
vm.expectRevert("CrossDomainMessenger: message has already been relayed");
// Retry the message again.
vm.prank(address(sender));
L1Messenger.relayMessage(
l1CrossDomainMessenger.relayMessage(
Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce
sender,
target,
......
......@@ -2,7 +2,7 @@
pragma solidity 0.8.15;
// Testing utilities
import { ERC721Bridge_Initializer } from "test/CommonTest.t.sol";
import { Bridge_Initializer } from "test/CommonTest.t.sol";
import { ERC721 } from "@openzeppelin/contracts/token/ERC721/ERC721.sol";
// Target contract dependencies
......@@ -21,7 +21,7 @@ contract TestERC721 is ERC721 {
}
}
contract L1ERC721Bridge_Test is ERC721Bridge_Initializer {
contract L1ERC721Bridge_Test is Bridge_Initializer {
TestERC721 internal localToken;
TestERC721 internal remoteToken;
uint256 internal constant tokenId = 1;
......@@ -56,26 +56,26 @@ contract L1ERC721Bridge_Test is ERC721Bridge_Initializer {
// Approve the bridge to transfer the token.
vm.prank(alice);
localToken.approve(address(L1NFTBridge), tokenId);
localToken.approve(address(l1ERC721Bridge), tokenId);
}
/// @dev Tests that the constructor sets the correct values.
function test_constructor_succeeds() public {
assertEq(address(L1NFTBridge.MESSENGER()), address(L1Messenger));
assertEq(address(L1NFTBridge.OTHER_BRIDGE()), Predeploys.L2_ERC721_BRIDGE);
assertEq(address(L1NFTBridge.messenger()), address(L1Messenger));
assertEq(address(L1NFTBridge.otherBridge()), Predeploys.L2_ERC721_BRIDGE);
assertEq(address(l1ERC721Bridge.MESSENGER()), address(l1CrossDomainMessenger));
assertEq(address(l1ERC721Bridge.OTHER_BRIDGE()), Predeploys.L2_ERC721_BRIDGE);
assertEq(address(l1ERC721Bridge.messenger()), address(l1CrossDomainMessenger));
assertEq(address(l1ERC721Bridge.otherBridge()), Predeploys.L2_ERC721_BRIDGE);
}
/// @dev Tests that the ERC721 can be bridged successfully.
function test_bridgeERC721_succeeds() public {
// Expect a call to the messenger.
vm.expectCall(
address(L1Messenger),
address(l1CrossDomainMessenger),
abi.encodeCall(
L1Messenger.sendMessage,
l1CrossDomainMessenger.sendMessage,
(
address(L2NFTBridge),
address(l2ERC721Bridge),
abi.encodeCall(
L2ERC721Bridge.finalizeBridgeERC721,
(address(remoteToken), address(localToken), alice, alice, tokenId, hex"5678")
......@@ -91,11 +91,11 @@ contract L1ERC721Bridge_Test is ERC721Bridge_Initializer {
// Bridge the token.
vm.prank(alice);
L1NFTBridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex"5678");
l1ERC721Bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex"5678");
// Token is locked in the bridge.
assertEq(L1NFTBridge.deposits(address(localToken), address(remoteToken), tokenId), true);
assertEq(localToken.ownerOf(tokenId), address(L1NFTBridge));
assertEq(l1ERC721Bridge.deposits(address(localToken), address(remoteToken), tokenId), true);
assertEq(localToken.ownerOf(tokenId), address(l1ERC721Bridge));
}
/// @dev Tests that the ERC721 bridge reverts for non externally owned accounts.
......@@ -104,10 +104,10 @@ contract L1ERC721Bridge_Test is ERC721Bridge_Initializer {
vm.etch(alice, hex"01");
vm.prank(alice);
vm.expectRevert("ERC721Bridge: account is not externally owned");
L1NFTBridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex"5678");
l1ERC721Bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex"5678");
// Token is not locked in the bridge.
assertEq(L1NFTBridge.deposits(address(localToken), address(remoteToken), tokenId), false);
assertEq(l1ERC721Bridge.deposits(address(localToken), address(remoteToken), tokenId), false);
assertEq(localToken.ownerOf(tokenId), alice);
}
......@@ -116,10 +116,10 @@ contract L1ERC721Bridge_Test is ERC721Bridge_Initializer {
// Bridge the token.
vm.prank(alice);
vm.expectRevert();
L1NFTBridge.bridgeERC721(address(0), address(remoteToken), tokenId, 1234, hex"5678");
l1ERC721Bridge.bridgeERC721(address(0), address(remoteToken), tokenId, 1234, hex"5678");
// Token is not locked in the bridge.
assertEq(L1NFTBridge.deposits(address(localToken), address(remoteToken), tokenId), false);
assertEq(l1ERC721Bridge.deposits(address(localToken), address(remoteToken), tokenId), false);
assertEq(localToken.ownerOf(tokenId), alice);
}
......@@ -128,10 +128,10 @@ contract L1ERC721Bridge_Test is ERC721Bridge_Initializer {
// Bridge the token.
vm.prank(alice);
vm.expectRevert("L1ERC721Bridge: remote token cannot be address(0)");
L1NFTBridge.bridgeERC721(address(localToken), address(0), tokenId, 1234, hex"5678");
l1ERC721Bridge.bridgeERC721(address(localToken), address(0), tokenId, 1234, hex"5678");
// Token is not locked in the bridge.
assertEq(L1NFTBridge.deposits(address(localToken), address(remoteToken), tokenId), false);
assertEq(l1ERC721Bridge.deposits(address(localToken), address(remoteToken), tokenId), false);
assertEq(localToken.ownerOf(tokenId), alice);
}
......@@ -140,10 +140,10 @@ contract L1ERC721Bridge_Test is ERC721Bridge_Initializer {
// Bridge the token.
vm.prank(bob);
vm.expectRevert("ERC721: transfer from incorrect owner");
L1NFTBridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex"5678");
l1ERC721Bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex"5678");
// Token is not locked in the bridge.
assertEq(L1NFTBridge.deposits(address(localToken), address(remoteToken), tokenId), false);
assertEq(l1ERC721Bridge.deposits(address(localToken), address(remoteToken), tokenId), false);
assertEq(localToken.ownerOf(tokenId), alice);
}
......@@ -152,9 +152,9 @@ contract L1ERC721Bridge_Test is ERC721Bridge_Initializer {
function test_bridgeERC721To_succeeds() external {
// Expect a call to the messenger.
vm.expectCall(
address(L1Messenger),
address(l1CrossDomainMessenger),
abi.encodeCall(
L1Messenger.sendMessage,
l1CrossDomainMessenger.sendMessage,
(
address(Predeploys.L2_ERC721_BRIDGE),
abi.encodeCall(
......@@ -172,11 +172,11 @@ contract L1ERC721Bridge_Test is ERC721Bridge_Initializer {
// Bridge the token.
vm.prank(alice);
L1NFTBridge.bridgeERC721To(address(localToken), address(remoteToken), bob, tokenId, 1234, hex"5678");
l1ERC721Bridge.bridgeERC721To(address(localToken), address(remoteToken), bob, tokenId, 1234, hex"5678");
// Token is locked in the bridge.
assertEq(L1NFTBridge.deposits(address(localToken), address(remoteToken), tokenId), true);
assertEq(localToken.ownerOf(tokenId), address(L1NFTBridge));
assertEq(l1ERC721Bridge.deposits(address(localToken), address(remoteToken), tokenId), true);
assertEq(localToken.ownerOf(tokenId), address(l1ERC721Bridge));
}
/// @dev Tests that the ERC721 bridge reverts for non externally owned accounts
......@@ -185,10 +185,10 @@ contract L1ERC721Bridge_Test is ERC721Bridge_Initializer {
// Bridge the token.
vm.prank(alice);
vm.expectRevert();
L1NFTBridge.bridgeERC721To(address(0), address(remoteToken), bob, tokenId, 1234, hex"5678");
l1ERC721Bridge.bridgeERC721To(address(0), address(remoteToken), bob, tokenId, 1234, hex"5678");
// Token is not locked in the bridge.
assertEq(L1NFTBridge.deposits(address(localToken), address(remoteToken), tokenId), false);
assertEq(l1ERC721Bridge.deposits(address(localToken), address(remoteToken), tokenId), false);
assertEq(localToken.ownerOf(tokenId), alice);
}
......@@ -198,10 +198,10 @@ contract L1ERC721Bridge_Test is ERC721Bridge_Initializer {
// Bridge the token.
vm.prank(alice);
vm.expectRevert("L1ERC721Bridge: remote token cannot be address(0)");
L1NFTBridge.bridgeERC721To(address(localToken), address(0), bob, tokenId, 1234, hex"5678");
l1ERC721Bridge.bridgeERC721To(address(localToken), address(0), bob, tokenId, 1234, hex"5678");
// Token is not locked in the bridge.
assertEq(L1NFTBridge.deposits(address(localToken), address(remoteToken), tokenId), false);
assertEq(l1ERC721Bridge.deposits(address(localToken), address(remoteToken), tokenId), false);
assertEq(localToken.ownerOf(tokenId), alice);
}
......@@ -211,10 +211,10 @@ contract L1ERC721Bridge_Test is ERC721Bridge_Initializer {
// Bridge the token.
vm.prank(bob);
vm.expectRevert("ERC721: transfer from incorrect owner");
L1NFTBridge.bridgeERC721To(address(localToken), address(remoteToken), bob, tokenId, 1234, hex"5678");
l1ERC721Bridge.bridgeERC721To(address(localToken), address(remoteToken), bob, tokenId, 1234, hex"5678");
// Token is not locked in the bridge.
assertEq(L1NFTBridge.deposits(address(localToken), address(remoteToken), tokenId), false);
assertEq(l1ERC721Bridge.deposits(address(localToken), address(remoteToken), tokenId), false);
assertEq(localToken.ownerOf(tokenId), alice);
}
......@@ -222,7 +222,7 @@ contract L1ERC721Bridge_Test is ERC721Bridge_Initializer {
function test_finalizeBridgeERC721_succeeds() external {
// Bridge the token.
vm.prank(alice);
L1NFTBridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex"5678");
l1ERC721Bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex"5678");
// Expect an event to be emitted.
vm.expectEmit(true, true, true, true);
......@@ -230,15 +230,15 @@ contract L1ERC721Bridge_Test is ERC721Bridge_Initializer {
// Finalize a withdrawal.
vm.mockCall(
address(L1Messenger),
abi.encodeWithSelector(L1Messenger.xDomainMessageSender.selector),
address(l1CrossDomainMessenger),
abi.encodeWithSelector(l1CrossDomainMessenger.xDomainMessageSender.selector),
abi.encode(Predeploys.L2_ERC721_BRIDGE)
);
vm.prank(address(L1Messenger));
L1NFTBridge.finalizeBridgeERC721(address(localToken), address(remoteToken), alice, alice, tokenId, hex"5678");
vm.prank(address(l1CrossDomainMessenger));
l1ERC721Bridge.finalizeBridgeERC721(address(localToken), address(remoteToken), alice, alice, tokenId, hex"5678");
// Token is not locked in the bridge.
assertEq(L1NFTBridge.deposits(address(localToken), address(remoteToken), tokenId), false);
assertEq(l1ERC721Bridge.deposits(address(localToken), address(remoteToken), tokenId), false);
assertEq(localToken.ownerOf(tokenId), alice);
}
......@@ -248,7 +248,7 @@ contract L1ERC721Bridge_Test is ERC721Bridge_Initializer {
// Finalize a withdrawal.
vm.prank(alice);
vm.expectRevert("ERC721Bridge: function can only be called from the other bridge");
L1NFTBridge.finalizeBridgeERC721(address(localToken), address(remoteToken), alice, alice, tokenId, hex"5678");
l1ERC721Bridge.finalizeBridgeERC721(address(localToken), address(remoteToken), alice, alice, tokenId, hex"5678");
}
/// @dev Tests that the ERC721 bridge finalize reverts when not called
......@@ -256,11 +256,13 @@ contract L1ERC721Bridge_Test is ERC721Bridge_Initializer {
function test_finalizeBridgeERC721_notFromRemoteMessenger_reverts() external {
// Finalize a withdrawal.
vm.mockCall(
address(L1Messenger), abi.encodeWithSelector(L1Messenger.xDomainMessageSender.selector), abi.encode(alice)
address(l1CrossDomainMessenger),
abi.encodeWithSelector(l1CrossDomainMessenger.xDomainMessageSender.selector),
abi.encode(alice)
);
vm.prank(address(L1Messenger));
vm.prank(address(l1CrossDomainMessenger));
vm.expectRevert("ERC721Bridge: function can only be called from the other bridge");
L1NFTBridge.finalizeBridgeERC721(address(localToken), address(remoteToken), alice, alice, tokenId, hex"5678");
l1ERC721Bridge.finalizeBridgeERC721(address(localToken), address(remoteToken), alice, alice, tokenId, hex"5678");
}
/// @dev Tests that the ERC721 bridge finalize reverts when the local token
......@@ -268,13 +270,15 @@ contract L1ERC721Bridge_Test is ERC721Bridge_Initializer {
function test_finalizeBridgeERC721_selfToken_reverts() external {
// Finalize a withdrawal.
vm.mockCall(
address(L1Messenger),
abi.encodeWithSelector(L1Messenger.xDomainMessageSender.selector),
address(l1CrossDomainMessenger),
abi.encodeWithSelector(l1CrossDomainMessenger.xDomainMessageSender.selector),
abi.encode(Predeploys.L2_ERC721_BRIDGE)
);
vm.prank(address(L1Messenger));
vm.prank(address(l1CrossDomainMessenger));
vm.expectRevert("L1ERC721Bridge: local token cannot be self");
L1NFTBridge.finalizeBridgeERC721(address(L1NFTBridge), address(remoteToken), alice, alice, tokenId, hex"5678");
l1ERC721Bridge.finalizeBridgeERC721(
address(l1ERC721Bridge), address(remoteToken), alice, alice, tokenId, hex"5678"
);
}
/// @dev Tests that the ERC721 bridge finalize reverts when the remote token
......@@ -282,12 +286,12 @@ contract L1ERC721Bridge_Test is ERC721Bridge_Initializer {
function test_finalizeBridgeERC721_notEscrowed_reverts() external {
// Finalize a withdrawal.
vm.mockCall(
address(L1Messenger),
abi.encodeWithSelector(L1Messenger.xDomainMessageSender.selector),
address(l1CrossDomainMessenger),
abi.encodeWithSelector(l1CrossDomainMessenger.xDomainMessageSender.selector),
abi.encode(Predeploys.L2_ERC721_BRIDGE)
);
vm.prank(address(L1Messenger));
vm.prank(address(l1CrossDomainMessenger));
vm.expectRevert("L1ERC721Bridge: Token ID is not escrowed in the L1 Bridge");
L1NFTBridge.finalizeBridgeERC721(address(localToken), address(remoteToken), alice, alice, tokenId, hex"5678");
l1ERC721Bridge.finalizeBridgeERC721(address(localToken), address(remoteToken), alice, alice, tokenId, hex"5678");
}
}
......@@ -22,20 +22,20 @@ import { OptimismPortal } from "src/L1/OptimismPortal.sol";
contract L1StandardBridge_Getter_Test is Bridge_Initializer {
/// @dev Test that the accessors return the correct initialized values.
function test_getters_succeeds() external view {
assert(L1Bridge.l2TokenBridge() == address(L2Bridge));
assert(L1Bridge.OTHER_BRIDGE() == L2Bridge);
assert(L1Bridge.messenger() == L1Messenger);
assert(L1Bridge.MESSENGER() == L1Messenger);
assert(l1StandardBridge.l2TokenBridge() == address(l2StandardBridge));
assert(l1StandardBridge.OTHER_BRIDGE() == l2StandardBridge);
assert(l1StandardBridge.messenger() == l1CrossDomainMessenger);
assert(l1StandardBridge.MESSENGER() == l1CrossDomainMessenger);
}
}
contract L1StandardBridge_Initialize_Test is Bridge_Initializer {
/// @dev Test that the initialize function sets the correct values.
function test_initialize_succeeds() external {
assertEq(address(L1Bridge.messenger()), address(L1Messenger));
assertEq(address(L1Bridge.OTHER_BRIDGE()), Predeploys.L2_STANDARD_BRIDGE);
assertEq(address(L2Bridge), Predeploys.L2_STANDARD_BRIDGE);
bytes32 slot0 = vm.load(address(L1Bridge), bytes32(uint256(0)));
assertEq(address(l1StandardBridge.messenger()), address(l1CrossDomainMessenger));
assertEq(address(l1StandardBridge.OTHER_BRIDGE()), Predeploys.L2_STANDARD_BRIDGE);
assertEq(address(l2StandardBridge), Predeploys.L2_STANDARD_BRIDGE);
bytes32 slot0 = vm.load(address(l1StandardBridge), bytes32(uint256(0)));
assertEq(slot0, bytes32(uint256(Constants.INITIALIZER)));
}
}
......@@ -45,29 +45,29 @@ contract L1StandardBridge_Initialize_TestFail is Bridge_Initializer { }
contract L1StandardBridge_Receive_Test is Bridge_Initializer {
/// @dev Tests receive bridges ETH successfully.
function test_receive_succeeds() external {
assertEq(address(op).balance, 0);
assertEq(address(optimismPortal).balance, 0);
// The legacy event must be emitted for backwards compatibility
vm.expectEmit(true, true, true, true, address(L1Bridge));
vm.expectEmit(true, true, true, true, address(l1StandardBridge));
emit ETHDepositInitiated(alice, alice, 100, hex"");
vm.expectEmit(true, true, true, true, address(L1Bridge));
vm.expectEmit(true, true, true, true, address(l1StandardBridge));
emit ETHBridgeInitiated(alice, alice, 100, hex"");
vm.expectCall(
address(L1Messenger),
address(l1CrossDomainMessenger),
abi.encodeWithSelector(
CrossDomainMessenger.sendMessage.selector,
address(L2Bridge),
address(l2StandardBridge),
abi.encodeWithSelector(StandardBridge.finalizeBridgeETH.selector, alice, alice, 100, hex""),
200_000
)
);
vm.prank(alice, alice);
(bool success,) = address(L1Bridge).call{ value: 100 }(hex"");
(bool success,) = address(l1StandardBridge).call{ value: 100 }(hex"");
assertEq(success, true);
assertEq(address(op).balance, 100);
assertEq(address(optimismPortal).balance, 100);
}
}
......@@ -77,59 +77,76 @@ contract PreBridgeETH is Bridge_Initializer {
/// @dev Asserts the expected calls and events for bridging ETH depending
/// on whether the bridge call is legacy or not.
function _preBridgeETH(bool isLegacy) internal {
assertEq(address(op).balance, 0);
uint256 nonce = L1Messenger.messageNonce();
assertEq(address(optimismPortal).balance, 0);
uint256 nonce = l1CrossDomainMessenger.messageNonce();
uint256 version = 0; // Internal constant in the OptimismPortal: DEPOSIT_VERSION
address l1MessengerAliased = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));
address l1MessengerAliased = AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger));
bytes memory message =
abi.encodeWithSelector(StandardBridge.finalizeBridgeETH.selector, alice, alice, 500, hex"dead");
if (isLegacy) {
vm.expectCall(
address(L1Bridge), 500, abi.encodeWithSelector(L1Bridge.depositETH.selector, 50000, hex"dead")
address(l1StandardBridge),
500,
abi.encodeWithSelector(l1StandardBridge.depositETH.selector, 50000, hex"dead")
);
} else {
vm.expectCall(address(L1Bridge), 500, abi.encodeWithSelector(L1Bridge.bridgeETH.selector, 50000, hex"dead"));
vm.expectCall(
address(l1StandardBridge),
500,
abi.encodeWithSelector(l1StandardBridge.bridgeETH.selector, 50000, hex"dead")
);
}
vm.expectCall(
address(L1Messenger),
address(l1CrossDomainMessenger),
500,
abi.encodeWithSelector(CrossDomainMessenger.sendMessage.selector, address(L2Bridge), message, 50000)
abi.encodeWithSelector(CrossDomainMessenger.sendMessage.selector, address(l2StandardBridge), message, 50000)
);
bytes memory innerMessage = abi.encodeWithSelector(
CrossDomainMessenger.relayMessage.selector, nonce, address(L1Bridge), address(L2Bridge), 500, 50000, message
CrossDomainMessenger.relayMessage.selector,
nonce,
address(l1StandardBridge),
address(l2StandardBridge),
500,
50000,
message
);
uint64 baseGas = L1Messenger.baseGas(message, 50000);
uint64 baseGas = l1CrossDomainMessenger.baseGas(message, 50000);
vm.expectCall(
address(op),
address(optimismPortal),
500,
abi.encodeWithSelector(
OptimismPortal.depositTransaction.selector, address(L2Messenger), 500, baseGas, false, innerMessage
OptimismPortal.depositTransaction.selector,
address(l2CrossDomainMessenger),
500,
baseGas,
false,
innerMessage
)
);
bytes memory opaqueData = abi.encodePacked(uint256(500), uint256(500), baseGas, false, innerMessage);
vm.expectEmit(true, true, true, true, address(L1Bridge));
vm.expectEmit(true, true, true, true, address(l1StandardBridge));
emit ETHDepositInitiated(alice, alice, 500, hex"dead");
vm.expectEmit(true, true, true, true, address(L1Bridge));
vm.expectEmit(true, true, true, true, address(l1StandardBridge));
emit ETHBridgeInitiated(alice, alice, 500, hex"dead");
// OptimismPortal emits a TransactionDeposited event on `depositTransaction` call
vm.expectEmit(true, true, true, true, address(op));
emit TransactionDeposited(l1MessengerAliased, address(L2Messenger), version, opaqueData);
vm.expectEmit(true, true, true, true, address(optimismPortal));
emit TransactionDeposited(l1MessengerAliased, address(l2CrossDomainMessenger), version, opaqueData);
// SentMessage event emitted by the CrossDomainMessenger
vm.expectEmit(true, true, true, true, address(L1Messenger));
emit SentMessage(address(L2Bridge), address(L1Bridge), message, nonce, 50000);
vm.expectEmit(true, true, true, true, address(l1CrossDomainMessenger));
emit SentMessage(address(l2StandardBridge), address(l1StandardBridge), message, nonce, 50000);
// SentMessageExtension1 event emitted by the CrossDomainMessenger
vm.expectEmit(true, true, true, true, address(L1Messenger));
emit SentMessageExtension1(address(L1Bridge), 500);
vm.expectEmit(true, true, true, true, address(l1CrossDomainMessenger));
emit SentMessageExtension1(address(l1StandardBridge), 500);
vm.prank(alice, alice);
}
......@@ -143,8 +160,8 @@ contract L1StandardBridge_DepositETH_Test is PreBridgeETH {
/// ETH ends up in the optimismPortal.
function test_depositETH_succeeds() external {
_preBridgeETH({ isLegacy: true });
L1Bridge.depositETH{ value: 500 }(50000, hex"dead");
assertEq(address(op).balance, 500);
l1StandardBridge.depositETH{ value: 500 }(50000, hex"dead");
assertEq(address(optimismPortal).balance, 500);
}
}
......@@ -156,8 +173,8 @@ contract L1StandardBridge_BridgeETH_Test is PreBridgeETH {
/// ETH ends up in the optimismPortal.
function test_bridgeETH_succeeds() external {
_preBridgeETH({ isLegacy: false });
L1Bridge.bridgeETH{ value: 500 }(50000, hex"dead");
assertEq(address(op).balance, 500);
l1StandardBridge.bridgeETH{ value: 500 }(50000, hex"dead");
assertEq(address(optimismPortal).balance, 500);
}
}
......@@ -167,7 +184,7 @@ contract L1StandardBridge_DepositETH_TestFail is Bridge_Initializer {
vm.etch(alice, address(L1Token).code);
vm.expectRevert("StandardBridge: function can only be called from an EOA");
vm.prank(alice);
L1Bridge.depositETH{ value: 1 }(300, hex"");
l1StandardBridge.depositETH{ value: 1 }(300, hex"");
}
}
......@@ -175,18 +192,22 @@ contract PreBridgeETHTo is Bridge_Initializer {
/// @dev Asserts the expected calls and events for bridging ETH to a different
/// address depending on whether the bridge call is legacy or not.
function _preBridgeETHTo(bool isLegacy) internal {
assertEq(address(op).balance, 0);
uint256 nonce = L1Messenger.messageNonce();
assertEq(address(optimismPortal).balance, 0);
uint256 nonce = l1CrossDomainMessenger.messageNonce();
uint256 version = 0; // Internal constant in the OptimismPortal: DEPOSIT_VERSION
address l1MessengerAliased = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));
address l1MessengerAliased = AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger));
if (isLegacy) {
vm.expectCall(
address(L1Bridge), 600, abi.encodeWithSelector(L1Bridge.depositETHTo.selector, bob, 60000, hex"dead")
address(l1StandardBridge),
600,
abi.encodeWithSelector(l1StandardBridge.depositETHTo.selector, bob, 60000, hex"dead")
);
} else {
vm.expectCall(
address(L1Bridge), 600, abi.encodeWithSelector(L1Bridge.bridgeETHTo.selector, bob, 60000, hex"dead")
address(l1StandardBridge),
600,
abi.encodeWithSelector(l1StandardBridge.bridgeETHTo.selector, bob, 60000, hex"dead")
);
}
......@@ -196,41 +217,52 @@ contract PreBridgeETHTo is Bridge_Initializer {
// the L1 bridge should call
// L1CrossDomainMessenger.sendMessage
vm.expectCall(
address(L1Messenger),
abi.encodeWithSelector(CrossDomainMessenger.sendMessage.selector, address(L2Bridge), message, 60000)
address(l1CrossDomainMessenger),
abi.encodeWithSelector(CrossDomainMessenger.sendMessage.selector, address(l2StandardBridge), message, 60000)
);
bytes memory innerMessage = abi.encodeWithSelector(
CrossDomainMessenger.relayMessage.selector, nonce, address(L1Bridge), address(L2Bridge), 600, 60000, message
CrossDomainMessenger.relayMessage.selector,
nonce,
address(l1StandardBridge),
address(l2StandardBridge),
600,
60000,
message
);
uint64 baseGas = L1Messenger.baseGas(message, 60000);
uint64 baseGas = l1CrossDomainMessenger.baseGas(message, 60000);
vm.expectCall(
address(op),
address(optimismPortal),
abi.encodeWithSelector(
OptimismPortal.depositTransaction.selector, address(L2Messenger), 600, baseGas, false, innerMessage
OptimismPortal.depositTransaction.selector,
address(l2CrossDomainMessenger),
600,
baseGas,
false,
innerMessage
)
);
bytes memory opaqueData = abi.encodePacked(uint256(600), uint256(600), baseGas, false, innerMessage);
vm.expectEmit(true, true, true, true, address(L1Bridge));
vm.expectEmit(true, true, true, true, address(l1StandardBridge));
emit ETHDepositInitiated(alice, bob, 600, hex"dead");
vm.expectEmit(true, true, true, true, address(L1Bridge));
vm.expectEmit(true, true, true, true, address(l1StandardBridge));
emit ETHBridgeInitiated(alice, bob, 600, hex"dead");
// OptimismPortal emits a TransactionDeposited event on `depositTransaction` call
vm.expectEmit(true, true, true, true, address(op));
emit TransactionDeposited(l1MessengerAliased, address(L2Messenger), version, opaqueData);
vm.expectEmit(true, true, true, true, address(optimismPortal));
emit TransactionDeposited(l1MessengerAliased, address(l2CrossDomainMessenger), version, opaqueData);
// SentMessage event emitted by the CrossDomainMessenger
vm.expectEmit(true, true, true, true, address(L1Messenger));
emit SentMessage(address(L2Bridge), address(L1Bridge), message, nonce, 60000);
vm.expectEmit(true, true, true, true, address(l1CrossDomainMessenger));
emit SentMessage(address(l2StandardBridge), address(l1StandardBridge), message, nonce, 60000);
// SentMessageExtension1 event emitted by the CrossDomainMessenger
vm.expectEmit(true, true, true, true, address(L1Messenger));
emit SentMessageExtension1(address(L1Bridge), 600);
vm.expectEmit(true, true, true, true, address(l1CrossDomainMessenger));
emit SentMessageExtension1(address(l1StandardBridge), 600);
// deposit eth to bob
vm.prank(alice, alice);
......@@ -245,8 +277,8 @@ contract L1StandardBridge_DepositETHTo_Test is PreBridgeETHTo {
/// ETH ends up in the optimismPortal.
function test_depositETHTo_succeeds() external {
_preBridgeETHTo({ isLegacy: true });
L1Bridge.depositETHTo{ value: 600 }(bob, 60000, hex"dead");
assertEq(address(op).balance, 600);
l1StandardBridge.depositETHTo{ value: 600 }(bob, 60000, hex"dead");
assertEq(address(optimismPortal).balance, 600);
}
}
......@@ -258,8 +290,8 @@ contract L1StandardBridge_BridgeETHTo_Test is PreBridgeETHTo {
/// ETH ends up in the optimismPortal.
function test_bridgeETHTo_succeeds() external {
_preBridgeETHTo({ isLegacy: false });
L1Bridge.bridgeETHTo{ value: 600 }(bob, 60000, hex"dead");
assertEq(address(op).balance, 600);
l1StandardBridge.bridgeETHTo{ value: 600 }(bob, 60000, hex"dead");
assertEq(address(optimismPortal).balance, 600);
}
}
......@@ -280,18 +312,18 @@ contract L1StandardBridge_DepositERC20_Test is Bridge_Initializer {
/// Calls depositTransaction on the OptimismPortal.
/// Only EOA can call depositERC20.
function test_depositERC20_succeeds() external {
uint256 nonce = L1Messenger.messageNonce();
uint256 nonce = l1CrossDomainMessenger.messageNonce();
uint256 version = 0; // Internal constant in the OptimismPortal: DEPOSIT_VERSION
address l1MessengerAliased = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));
address l1MessengerAliased = AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger));
// Deal Alice's ERC20 State
deal(address(L1Token), alice, 100000, true);
vm.prank(alice);
L1Token.approve(address(L1Bridge), type(uint256).max);
L1Token.approve(address(l1StandardBridge), type(uint256).max);
// The L1Bridge should transfer alice's tokens to itself
// The l1StandardBridge should transfer alice's tokens to itself
vm.expectCall(
address(L1Token), abi.encodeWithSelector(ERC20.transferFrom.selector, alice, address(L1Bridge), 100)
address(L1Token), abi.encodeWithSelector(ERC20.transferFrom.selector, alice, address(l1StandardBridge), 100)
);
bytes memory message = abi.encodeWithSelector(
......@@ -300,46 +332,57 @@ contract L1StandardBridge_DepositERC20_Test is Bridge_Initializer {
// the L1 bridge should call L1CrossDomainMessenger.sendMessage
vm.expectCall(
address(L1Messenger),
abi.encodeWithSelector(CrossDomainMessenger.sendMessage.selector, address(L2Bridge), message, 10000)
address(l1CrossDomainMessenger),
abi.encodeWithSelector(CrossDomainMessenger.sendMessage.selector, address(l2StandardBridge), message, 10000)
);
bytes memory innerMessage = abi.encodeWithSelector(
CrossDomainMessenger.relayMessage.selector, nonce, address(L1Bridge), address(L2Bridge), 0, 10000, message
CrossDomainMessenger.relayMessage.selector,
nonce,
address(l1StandardBridge),
address(l2StandardBridge),
0,
10000,
message
);
uint64 baseGas = L1Messenger.baseGas(message, 10000);
uint64 baseGas = l1CrossDomainMessenger.baseGas(message, 10000);
vm.expectCall(
address(op),
address(optimismPortal),
abi.encodeWithSelector(
OptimismPortal.depositTransaction.selector, address(L2Messenger), 0, baseGas, false, innerMessage
OptimismPortal.depositTransaction.selector,
address(l2CrossDomainMessenger),
0,
baseGas,
false,
innerMessage
)
);
bytes memory opaqueData = abi.encodePacked(uint256(0), uint256(0), baseGas, false, innerMessage);
// Should emit both the bedrock and legacy events
vm.expectEmit(true, true, true, true, address(L1Bridge));
vm.expectEmit(true, true, true, true, address(l1StandardBridge));
emit ERC20DepositInitiated(address(L1Token), address(L2Token), alice, alice, 100, hex"");
vm.expectEmit(true, true, true, true, address(L1Bridge));
vm.expectEmit(true, true, true, true, address(l1StandardBridge));
emit ERC20BridgeInitiated(address(L1Token), address(L2Token), alice, alice, 100, hex"");
// OptimismPortal emits a TransactionDeposited event on `depositTransaction` call
vm.expectEmit(true, true, true, true, address(op));
emit TransactionDeposited(l1MessengerAliased, address(L2Messenger), version, opaqueData);
vm.expectEmit(true, true, true, true, address(optimismPortal));
emit TransactionDeposited(l1MessengerAliased, address(l2CrossDomainMessenger), version, opaqueData);
// SentMessage event emitted by the CrossDomainMessenger
vm.expectEmit(true, true, true, true, address(L1Messenger));
emit SentMessage(address(L2Bridge), address(L1Bridge), message, nonce, 10000);
vm.expectEmit(true, true, true, true, address(l1CrossDomainMessenger));
emit SentMessage(address(l2StandardBridge), address(l1StandardBridge), message, nonce, 10000);
// SentMessageExtension1 event emitted by the CrossDomainMessenger
vm.expectEmit(true, true, true, true, address(L1Messenger));
emit SentMessageExtension1(address(L1Bridge), 0);
vm.expectEmit(true, true, true, true, address(l1CrossDomainMessenger));
emit SentMessageExtension1(address(l1StandardBridge), 0);
vm.prank(alice);
L1Bridge.depositERC20(address(L1Token), address(L2Token), 100, 10000, hex"");
assertEq(L1Bridge.deposits(address(L1Token), address(L2Token)), 100);
l1StandardBridge.depositERC20(address(L1Token), address(L2Token), 100, 10000, hex"");
assertEq(l1StandardBridge.deposits(address(L1Token), address(L2Token)), 100);
}
}
......@@ -352,7 +395,7 @@ contract L1StandardBridge_DepositERC20_TestFail is Bridge_Initializer {
vm.expectRevert("StandardBridge: function can only be called from an EOA");
vm.prank(alice, alice);
L1Bridge.depositERC20(address(0), address(0), 100, 100, hex"");
l1StandardBridge.depositERC20(address(0), address(0), 100, 100, hex"");
}
}
......@@ -364,65 +407,77 @@ contract L1StandardBridge_DepositERC20To_Test is Bridge_Initializer {
/// Calls depositTransaction on the OptimismPortal.
/// Contracts can call depositERC20.
function test_depositERC20To_succeeds() external {
uint256 nonce = L1Messenger.messageNonce();
uint256 nonce = l1CrossDomainMessenger.messageNonce();
uint256 version = 0; // Internal constant in the OptimismPortal: DEPOSIT_VERSION
address l1MessengerAliased = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));
address l1MessengerAliased = AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger));
bytes memory message = abi.encodeWithSelector(
StandardBridge.finalizeBridgeERC20.selector, address(L2Token), address(L1Token), alice, bob, 1000, hex""
);
bytes memory innerMessage = abi.encodeWithSelector(
CrossDomainMessenger.relayMessage.selector, nonce, address(L1Bridge), address(L2Bridge), 0, 10000, message
CrossDomainMessenger.relayMessage.selector,
nonce,
address(l1StandardBridge),
address(l2StandardBridge),
0,
10000,
message
);
uint64 baseGas = L1Messenger.baseGas(message, 10000);
uint64 baseGas = l1CrossDomainMessenger.baseGas(message, 10000);
bytes memory opaqueData = abi.encodePacked(uint256(0), uint256(0), baseGas, false, innerMessage);
deal(address(L1Token), alice, 100000, true);
vm.prank(alice);
L1Token.approve(address(L1Bridge), type(uint256).max);
L1Token.approve(address(l1StandardBridge), type(uint256).max);
// Should emit both the bedrock and legacy events
vm.expectEmit(true, true, true, true, address(L1Bridge));
vm.expectEmit(true, true, true, true, address(l1StandardBridge));
emit ERC20DepositInitiated(address(L1Token), address(L2Token), alice, bob, 1000, hex"");
vm.expectEmit(true, true, true, true, address(L1Bridge));
vm.expectEmit(true, true, true, true, address(l1StandardBridge));
emit ERC20BridgeInitiated(address(L1Token), address(L2Token), alice, bob, 1000, hex"");
// OptimismPortal emits a TransactionDeposited event on `depositTransaction` call
vm.expectEmit(true, true, true, true, address(op));
emit TransactionDeposited(l1MessengerAliased, address(L2Messenger), version, opaqueData);
vm.expectEmit(true, true, true, true, address(optimismPortal));
emit TransactionDeposited(l1MessengerAliased, address(l2CrossDomainMessenger), version, opaqueData);
// SentMessage event emitted by the CrossDomainMessenger
vm.expectEmit(true, true, true, true, address(L1Messenger));
emit SentMessage(address(L2Bridge), address(L1Bridge), message, nonce, 10000);
vm.expectEmit(true, true, true, true, address(l1CrossDomainMessenger));
emit SentMessage(address(l2StandardBridge), address(l1StandardBridge), message, nonce, 10000);
// SentMessageExtension1 event emitted by the CrossDomainMessenger
vm.expectEmit(true, true, true, true, address(L1Messenger));
emit SentMessageExtension1(address(L1Bridge), 0);
vm.expectEmit(true, true, true, true, address(l1CrossDomainMessenger));
emit SentMessageExtension1(address(l1StandardBridge), 0);
// the L1 bridge should call L1CrossDomainMessenger.sendMessage
vm.expectCall(
address(L1Messenger),
abi.encodeWithSelector(CrossDomainMessenger.sendMessage.selector, address(L2Bridge), message, 10000)
address(l1CrossDomainMessenger),
abi.encodeWithSelector(CrossDomainMessenger.sendMessage.selector, address(l2StandardBridge), message, 10000)
);
// The L1 XDM should call OptimismPortal.depositTransaction
vm.expectCall(
address(op),
address(optimismPortal),
abi.encodeWithSelector(
OptimismPortal.depositTransaction.selector, address(L2Messenger), 0, baseGas, false, innerMessage
OptimismPortal.depositTransaction.selector,
address(l2CrossDomainMessenger),
0,
baseGas,
false,
innerMessage
)
);
vm.expectCall(
address(L1Token), abi.encodeWithSelector(ERC20.transferFrom.selector, alice, address(L1Bridge), 1000)
address(L1Token),
abi.encodeWithSelector(ERC20.transferFrom.selector, alice, address(l1StandardBridge), 1000)
);
vm.prank(alice);
L1Bridge.depositERC20To(address(L1Token), address(L2Token), bob, 1000, 10000, hex"");
l1StandardBridge.depositERC20To(address(L1Token), address(L2Token), bob, 1000, 10000, hex"");
assertEq(L1Bridge.deposits(address(L1Token), address(L2Token)), 1000);
assertEq(l1StandardBridge.deposits(address(L1Token), address(L2Token)), 1000);
}
}
......@@ -435,25 +490,25 @@ contract L1StandardBridge_FinalizeETHWithdrawal_Test is Bridge_Initializer {
function test_finalizeETHWithdrawal_succeeds() external {
uint256 aliceBalance = alice.balance;
vm.expectEmit(true, true, true, true, address(L1Bridge));
vm.expectEmit(true, true, true, true, address(l1StandardBridge));
emit ETHWithdrawalFinalized(alice, alice, 100, hex"");
vm.expectEmit(true, true, true, true, address(L1Bridge));
vm.expectEmit(true, true, true, true, address(l1StandardBridge));
emit ETHBridgeFinalized(alice, alice, 100, hex"");
vm.expectCall(alice, hex"");
vm.mockCall(
address(L1Bridge.messenger()),
address(l1StandardBridge.messenger()),
abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),
abi.encode(address(L1Bridge.OTHER_BRIDGE()))
abi.encode(address(l1StandardBridge.OTHER_BRIDGE()))
);
// ensure that the messenger has ETH to call with
vm.deal(address(L1Bridge.messenger()), 100);
vm.prank(address(L1Bridge.messenger()));
L1Bridge.finalizeETHWithdrawal{ value: 100 }(alice, alice, 100, hex"");
vm.deal(address(l1StandardBridge.messenger()), 100);
vm.prank(address(l1StandardBridge.messenger()));
l1StandardBridge.finalizeETHWithdrawal{ value: 100 }(alice, alice, 100, hex"");
assertEq(address(L1Bridge.messenger()).balance, 0);
assertEq(address(l1StandardBridge.messenger()).balance, 0);
assertEq(aliceBalance + 100, alice.balance);
}
}
......@@ -468,32 +523,33 @@ contract L1StandardBridge_FinalizeERC20Withdrawal_Test is Bridge_Initializer {
/// Emits ERC20WithdrawalFinalized event.
/// Only callable by the L2 bridge.
function test_finalizeERC20Withdrawal_succeeds() external {
deal(address(L1Token), address(L1Bridge), 100, true);
deal(address(L1Token), address(l1StandardBridge), 100, true);
uint256 slot = stdstore.target(address(L1Bridge)).sig("deposits(address,address)").with_key(address(L1Token))
.with_key(address(L2Token)).find();
uint256 slot = stdstore.target(address(l1StandardBridge)).sig("deposits(address,address)").with_key(
address(L1Token)
).with_key(address(L2Token)).find();
// Give the L1 bridge some ERC20 tokens
vm.store(address(L1Bridge), bytes32(slot), bytes32(uint256(100)));
assertEq(L1Bridge.deposits(address(L1Token), address(L2Token)), 100);
vm.store(address(l1StandardBridge), bytes32(slot), bytes32(uint256(100)));
assertEq(l1StandardBridge.deposits(address(L1Token), address(L2Token)), 100);
vm.expectEmit(true, true, true, true, address(L1Bridge));
vm.expectEmit(true, true, true, true, address(l1StandardBridge));
emit ERC20WithdrawalFinalized(address(L1Token), address(L2Token), alice, alice, 100, hex"");
vm.expectEmit(true, true, true, true, address(L1Bridge));
vm.expectEmit(true, true, true, true, address(l1StandardBridge));
emit ERC20BridgeFinalized(address(L1Token), address(L2Token), alice, alice, 100, hex"");
vm.expectCall(address(L1Token), abi.encodeWithSelector(ERC20.transfer.selector, alice, 100));
vm.mockCall(
address(L1Bridge.messenger()),
address(l1StandardBridge.messenger()),
abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),
abi.encode(address(L1Bridge.OTHER_BRIDGE()))
abi.encode(address(l1StandardBridge.OTHER_BRIDGE()))
);
vm.prank(address(L1Bridge.messenger()));
L1Bridge.finalizeERC20Withdrawal(address(L1Token), address(L2Token), alice, alice, 100, hex"");
vm.prank(address(l1StandardBridge.messenger()));
l1StandardBridge.finalizeERC20Withdrawal(address(L1Token), address(L2Token), alice, alice, 100, hex"");
assertEq(L1Token.balanceOf(address(L1Bridge)), 0);
assertEq(L1Token.balanceOf(address(l1StandardBridge)), 0);
assertEq(L1Token.balanceOf(address(alice)), 100);
}
}
......@@ -502,87 +558,87 @@ contract L1StandardBridge_FinalizeERC20Withdrawal_TestFail is Bridge_Initializer
/// @dev Tests that finalizing an ERC20 withdrawal reverts if the caller is not the L2 bridge.
function test_finalizeERC20Withdrawal_notMessenger_reverts() external {
vm.mockCall(
address(L1Bridge.messenger()),
address(l1StandardBridge.messenger()),
abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),
abi.encode(address(L1Bridge.OTHER_BRIDGE()))
abi.encode(address(l1StandardBridge.OTHER_BRIDGE()))
);
vm.prank(address(28));
vm.expectRevert("StandardBridge: function can only be called from the other bridge");
L1Bridge.finalizeERC20Withdrawal(address(L1Token), address(L2Token), alice, alice, 100, hex"");
l1StandardBridge.finalizeERC20Withdrawal(address(L1Token), address(L2Token), alice, alice, 100, hex"");
}
/// @dev Tests that finalizing an ERC20 withdrawal reverts if the caller is not the L2 bridge.
function test_finalizeERC20Withdrawal_notOtherBridge_reverts() external {
vm.mockCall(
address(L1Bridge.messenger()),
address(l1StandardBridge.messenger()),
abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),
abi.encode(address(address(0)))
);
vm.prank(address(L1Bridge.messenger()));
vm.prank(address(l1StandardBridge.messenger()));
vm.expectRevert("StandardBridge: function can only be called from the other bridge");
L1Bridge.finalizeERC20Withdrawal(address(L1Token), address(L2Token), alice, alice, 100, hex"");
l1StandardBridge.finalizeERC20Withdrawal(address(L1Token), address(L2Token), alice, alice, 100, hex"");
}
}
contract L1StandardBridge_FinalizeBridgeETH_Test is Bridge_Initializer {
/// @dev Tests that finalizing bridged ETH succeeds.
function test_finalizeBridgeETH_succeeds() external {
address messenger = address(L1Bridge.messenger());
address messenger = address(l1StandardBridge.messenger());
vm.mockCall(
messenger,
abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),
abi.encode(address(L1Bridge.OTHER_BRIDGE()))
abi.encode(address(l1StandardBridge.OTHER_BRIDGE()))
);
vm.deal(messenger, 100);
vm.prank(messenger);
vm.expectEmit(true, true, true, true, address(L1Bridge));
vm.expectEmit(true, true, true, true, address(l1StandardBridge));
emit ETHBridgeFinalized(alice, alice, 100, hex"");
L1Bridge.finalizeBridgeETH{ value: 100 }(alice, alice, 100, hex"");
l1StandardBridge.finalizeBridgeETH{ value: 100 }(alice, alice, 100, hex"");
}
}
contract L1StandardBridge_FinalizeBridgeETH_TestFail is Bridge_Initializer {
/// @dev Tests that finalizing bridged ETH reverts if the amount is incorrect.
function test_finalizeBridgeETH_incorrectValue_reverts() external {
address messenger = address(L1Bridge.messenger());
address messenger = address(l1StandardBridge.messenger());
vm.mockCall(
messenger,
abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),
abi.encode(address(L1Bridge.OTHER_BRIDGE()))
abi.encode(address(l1StandardBridge.OTHER_BRIDGE()))
);
vm.deal(messenger, 100);
vm.prank(messenger);
vm.expectRevert("StandardBridge: amount sent does not match amount required");
L1Bridge.finalizeBridgeETH{ value: 50 }(alice, alice, 100, hex"");
l1StandardBridge.finalizeBridgeETH{ value: 50 }(alice, alice, 100, hex"");
}
/// @dev Tests that finalizing bridged ETH reverts if the destination is the L1 bridge.
function test_finalizeBridgeETH_sendToSelf_reverts() external {
address messenger = address(L1Bridge.messenger());
address messenger = address(l1StandardBridge.messenger());
vm.mockCall(
messenger,
abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),
abi.encode(address(L1Bridge.OTHER_BRIDGE()))
abi.encode(address(l1StandardBridge.OTHER_BRIDGE()))
);
vm.deal(messenger, 100);
vm.prank(messenger);
vm.expectRevert("StandardBridge: cannot send to self");
L1Bridge.finalizeBridgeETH{ value: 100 }(alice, address(L1Bridge), 100, hex"");
l1StandardBridge.finalizeBridgeETH{ value: 100 }(alice, address(l1StandardBridge), 100, hex"");
}
/// @dev Tests that finalizing bridged ETH reverts if the destination is the messenger.
function test_finalizeBridgeETH_sendToMessenger_reverts() external {
address messenger = address(L1Bridge.messenger());
address messenger = address(l1StandardBridge.messenger());
vm.mockCall(
messenger,
abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),
abi.encode(address(L1Bridge.OTHER_BRIDGE()))
abi.encode(address(l1StandardBridge.OTHER_BRIDGE()))
);
vm.deal(messenger, 100);
vm.prank(messenger);
vm.expectRevert("StandardBridge: cannot send to messenger");
L1Bridge.finalizeBridgeETH{ value: 100 }(alice, messenger, 100, hex"");
l1StandardBridge.finalizeBridgeETH{ value: 100 }(alice, messenger, 100, hex"");
}
}
......@@ -20,20 +20,20 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer {
/// @dev Tests that `messageNonce` can be decoded correctly.
function test_messageVersion_succeeds() external {
(, uint16 version) = Encoding.decodeVersionedNonce(L2Messenger.messageNonce());
assertEq(version, L2Messenger.MESSAGE_VERSION());
(, uint16 version) = Encoding.decodeVersionedNonce(l2CrossDomainMessenger.messageNonce());
assertEq(version, l2CrossDomainMessenger.MESSAGE_VERSION());
}
/// @dev Tests that `sendMessage` executes successfully.
function test_sendMessage_succeeds() external {
bytes memory xDomainCallData =
Encoding.encodeCrossDomainMessage(L2Messenger.messageNonce(), alice, recipient, 0, 100, hex"ff");
Encoding.encodeCrossDomainMessage(l2CrossDomainMessenger.messageNonce(), alice, recipient, 0, 100, hex"ff");
vm.expectCall(
address(messagePasser),
address(l2ToL1MessagePasser),
abi.encodeWithSelector(
L2ToL1MessagePasser.initiateWithdrawal.selector,
address(L1Messenger),
L2Messenger.baseGas(hex"ff", 100),
address(l1CrossDomainMessenger),
l2CrossDomainMessenger.baseGas(hex"ff", 100),
xDomainCallData
)
);
......@@ -41,56 +41,56 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer {
// MessagePassed event
vm.expectEmit(true, true, true, true);
emit MessagePassed(
messagePasser.messageNonce(),
address(L2Messenger),
address(L1Messenger),
l2ToL1MessagePasser.messageNonce(),
address(l2CrossDomainMessenger),
address(l1CrossDomainMessenger),
0,
L2Messenger.baseGas(hex"ff", 100),
l2CrossDomainMessenger.baseGas(hex"ff", 100),
xDomainCallData,
Hashing.hashWithdrawal(
Types.WithdrawalTransaction({
nonce: messagePasser.messageNonce(),
sender: address(L2Messenger),
target: address(L1Messenger),
nonce: l2ToL1MessagePasser.messageNonce(),
sender: address(l2CrossDomainMessenger),
target: address(l1CrossDomainMessenger),
value: 0,
gasLimit: L2Messenger.baseGas(hex"ff", 100),
gasLimit: l2CrossDomainMessenger.baseGas(hex"ff", 100),
data: xDomainCallData
})
)
);
vm.prank(alice);
L2Messenger.sendMessage(recipient, hex"ff", uint32(100));
l2CrossDomainMessenger.sendMessage(recipient, hex"ff", uint32(100));
}
/// @dev Tests that `sendMessage` can be called twice and that
/// the nonce increments correctly.
function test_sendMessage_twice_succeeds() external {
uint256 nonce = L2Messenger.messageNonce();
L2Messenger.sendMessage(recipient, hex"aa", uint32(500_000));
L2Messenger.sendMessage(recipient, hex"aa", uint32(500_000));
uint256 nonce = l2CrossDomainMessenger.messageNonce();
l2CrossDomainMessenger.sendMessage(recipient, hex"aa", uint32(500_000));
l2CrossDomainMessenger.sendMessage(recipient, hex"aa", uint32(500_000));
// the nonce increments for each message sent
assertEq(nonce + 2, L2Messenger.messageNonce());
assertEq(nonce + 2, l2CrossDomainMessenger.messageNonce());
}
/// @dev Tests that `sendMessage` reverts if the recipient is the zero address.
function test_xDomainSender_senderNotSet_reverts() external {
vm.expectRevert("CrossDomainMessenger: xDomainMessageSender is not set");
L2Messenger.xDomainMessageSender();
l2CrossDomainMessenger.xDomainMessageSender();
}
/// @dev Tests that `sendMessage` reverts if the message version is not supported.
function test_relayMessage_v2_reverts() external {
address target = address(0xabcd);
address sender = address(L1Messenger);
address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));
address sender = address(l1CrossDomainMessenger);
address caller = AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger));
// Expect a revert.
vm.expectRevert("CrossDomainMessenger: only version 0 or 1 messages are supported at this time");
// Try to relay a v2 message.
vm.prank(caller);
L2Messenger.relayMessage(
l2CrossDomainMessenger.relayMessage(
Encoding.encodeVersionedNonce(0, 2), // nonce
sender,
target,
......@@ -103,8 +103,8 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer {
/// @dev Tests that `relayMessage` executes successfully.
function test_relayMessage_succeeds() external {
address target = address(0xabcd);
address sender = address(L1Messenger);
address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));
address sender = address(l1CrossDomainMessenger);
address caller = AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger));
vm.expectCall(target, hex"1111");
......@@ -117,7 +117,7 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer {
emit RelayedMessage(hash);
L2Messenger.relayMessage(
l2CrossDomainMessenger.relayMessage(
Encoding.encodeVersionedNonce(0, 1), // nonce
sender,
target,
......@@ -127,36 +127,36 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer {
);
// the message hash is in the successfulMessages mapping
assert(L2Messenger.successfulMessages(hash));
assert(l2CrossDomainMessenger.successfulMessages(hash));
// it is not in the received messages mapping
assertEq(L2Messenger.failedMessages(hash), false);
assertEq(l2CrossDomainMessenger.failedMessages(hash), false);
}
/// @dev Tests that `relayMessage` reverts if attempting to relay
/// a message sent to an L1 system contract.
function test_relayMessage_toSystemContract_reverts() external {
address target = address(messagePasser);
address sender = address(L1Messenger);
address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));
address target = address(l2ToL1MessagePasser);
address sender = address(l1CrossDomainMessenger);
address caller = AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger));
bytes memory message = hex"1111";
vm.prank(caller);
vm.expectRevert("CrossDomainMessenger: message cannot be replayed");
L1Messenger.relayMessage(Encoding.encodeVersionedNonce(0, 1), sender, target, 0, 0, message);
l1CrossDomainMessenger.relayMessage(Encoding.encodeVersionedNonce(0, 1), sender, target, 0, 0, message);
}
/// @dev Tests that `relayMessage` correctly resets the `xDomainMessageSender`
/// to the original value after a message is relayed.
function test_xDomainMessageSender_reset_succeeds() external {
vm.expectRevert("CrossDomainMessenger: xDomainMessageSender is not set");
L2Messenger.xDomainMessageSender();
l2CrossDomainMessenger.xDomainMessageSender();
address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));
address caller = AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger));
vm.prank(caller);
L2Messenger.relayMessage(Encoding.encodeVersionedNonce(0, 1), address(0), address(0), 0, 0, hex"");
l2CrossDomainMessenger.relayMessage(Encoding.encodeVersionedNonce(0, 1), address(0), address(0), 0, 0, hex"");
vm.expectRevert("CrossDomainMessenger: xDomainMessageSender is not set");
L2Messenger.xDomainMessageSender();
l2CrossDomainMessenger.xDomainMessageSender();
}
/// @dev Tests that `relayMessage` is able to send a successful call
......@@ -164,8 +164,8 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer {
/// gets stuck, but the second message succeeds.
function test_relayMessage_retry_succeeds() external {
address target = address(0xabcd);
address sender = address(L1Messenger);
address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));
address sender = address(l1CrossDomainMessenger);
address caller = AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger));
uint256 value = 100;
bytes32 hash =
......@@ -174,7 +174,7 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer {
vm.etch(target, address(new Reverter()).code);
vm.deal(address(caller), value);
vm.prank(caller);
L2Messenger.relayMessage{ value: value }(
l2CrossDomainMessenger.relayMessage{ value: value }(
Encoding.encodeVersionedNonce(0, 1), // nonce
sender,
target,
......@@ -183,10 +183,10 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer {
hex"1111"
);
assertEq(address(L2Messenger).balance, value);
assertEq(address(l2CrossDomainMessenger).balance, value);
assertEq(address(target).balance, 0);
assertEq(L2Messenger.successfulMessages(hash), false);
assertEq(L2Messenger.failedMessages(hash), true);
assertEq(l2CrossDomainMessenger.successfulMessages(hash), false);
assertEq(l2CrossDomainMessenger.failedMessages(hash), true);
vm.expectEmit(true, true, true, true);
......@@ -194,7 +194,7 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer {
vm.etch(target, address(0).code);
vm.prank(address(sender));
L2Messenger.relayMessage(
l2CrossDomainMessenger.relayMessage(
Encoding.encodeVersionedNonce(0, 1), // nonce
sender,
target,
......@@ -203,9 +203,9 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer {
hex"1111"
);
assertEq(address(L2Messenger).balance, 0);
assertEq(address(l2CrossDomainMessenger).balance, 0);
assertEq(address(target).balance, value);
assertEq(L2Messenger.successfulMessages(hash), true);
assertEq(L2Messenger.failedMessages(hash), true);
assertEq(l2CrossDomainMessenger.successfulMessages(hash), true);
assertEq(l2CrossDomainMessenger.failedMessages(hash), true);
}
}
......@@ -2,7 +2,7 @@
pragma solidity 0.8.15;
// Testing utilities
import { ERC721Bridge_Initializer } from "test/CommonTest.t.sol";
import { Bridge_Initializer } from "test/CommonTest.t.sol";
// Target contract dependencies
import { ERC721 } from "@openzeppelin/contracts/token/ERC721/ERC721.sol";
......@@ -33,7 +33,7 @@ contract TestMintableERC721 is OptimismMintableERC721 {
}
}
contract L2ERC721Bridge_Test is ERC721Bridge_Initializer {
contract L2ERC721Bridge_Test is Bridge_Initializer {
TestMintableERC721 internal localToken;
TestERC721 internal remoteToken;
uint256 internal constant tokenId = 1;
......@@ -61,22 +61,22 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer {
super.setUp();
remoteToken = new TestERC721();
localToken = new TestMintableERC721(address(L2NFTBridge), address(remoteToken));
localToken = new TestMintableERC721(address(l2ERC721Bridge), address(remoteToken));
// Mint alice a token.
localToken.mint(alice, tokenId);
// Approve the bridge to transfer the token.
vm.prank(alice);
localToken.approve(address(L2NFTBridge), tokenId);
localToken.approve(address(l2ERC721Bridge), tokenId);
}
/// @dev Tests that the constructor sets the correct variables.
function test_constructor_succeeds() public {
assertEq(address(L2NFTBridge.MESSENGER()), address(L2Messenger));
assertEq(address(L2NFTBridge.OTHER_BRIDGE()), address(L1NFTBridge));
assertEq(address(L2NFTBridge.messenger()), address(L2Messenger));
assertEq(address(L2NFTBridge.otherBridge()), address(L1NFTBridge));
assertEq(address(l2ERC721Bridge.MESSENGER()), address(l2CrossDomainMessenger));
assertEq(address(l2ERC721Bridge.OTHER_BRIDGE()), address(l1ERC721Bridge));
assertEq(address(l2ERC721Bridge.messenger()), address(l2CrossDomainMessenger));
assertEq(address(l2ERC721Bridge.otherBridge()), address(l1ERC721Bridge));
}
/// @dev Tests that `bridgeERC721` correctly bridges a token and
......@@ -84,11 +84,11 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer {
function test_bridgeERC721_succeeds() public {
// Expect a call to the messenger.
vm.expectCall(
address(L2Messenger),
address(l2CrossDomainMessenger),
abi.encodeCall(
L2Messenger.sendMessage,
l2CrossDomainMessenger.sendMessage,
(
address(L1NFTBridge),
address(l1ERC721Bridge),
abi.encodeCall(
L2ERC721Bridge.finalizeBridgeERC721,
(address(remoteToken), address(localToken), alice, alice, tokenId, hex"5678")
......@@ -104,7 +104,7 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer {
// Bridge the token.
vm.prank(alice);
L2NFTBridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex"5678");
l2ERC721Bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex"5678");
// Token is burned.
vm.expectRevert("ERC721: invalid token ID");
......@@ -117,7 +117,7 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer {
vm.etch(alice, hex"01");
vm.prank(alice);
vm.expectRevert("ERC721Bridge: account is not externally owned");
L2NFTBridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex"5678");
l2ERC721Bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex"5678");
// Token is not locked in the bridge.
assertEq(localToken.ownerOf(tokenId), alice);
......@@ -128,7 +128,7 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer {
// Bridge the token.
vm.prank(alice);
vm.expectRevert();
L2NFTBridge.bridgeERC721(address(0), address(remoteToken), tokenId, 1234, hex"5678");
l2ERC721Bridge.bridgeERC721(address(0), address(remoteToken), tokenId, 1234, hex"5678");
// Token is not locked in the bridge.
assertEq(localToken.ownerOf(tokenId), alice);
......@@ -139,7 +139,7 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer {
// Bridge the token.
vm.prank(alice);
vm.expectRevert("L2ERC721Bridge: remote token cannot be address(0)");
L2NFTBridge.bridgeERC721(address(localToken), address(0), tokenId, 1234, hex"5678");
l2ERC721Bridge.bridgeERC721(address(localToken), address(0), tokenId, 1234, hex"5678");
// Token is not locked in the bridge.
assertEq(localToken.ownerOf(tokenId), alice);
......@@ -150,7 +150,7 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer {
// Bridge the token.
vm.prank(bob);
vm.expectRevert("L2ERC721Bridge: Withdrawal is not being initiated by NFT owner");
L2NFTBridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex"5678");
l2ERC721Bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex"5678");
// Token is not locked in the bridge.
assertEq(localToken.ownerOf(tokenId), alice);
......@@ -161,11 +161,11 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer {
function test_bridgeERC721To_succeeds() external {
// Expect a call to the messenger.
vm.expectCall(
address(L2Messenger),
address(l2CrossDomainMessenger),
abi.encodeCall(
L2Messenger.sendMessage,
l2CrossDomainMessenger.sendMessage,
(
address(L1NFTBridge),
address(l1ERC721Bridge),
abi.encodeCall(
L1ERC721Bridge.finalizeBridgeERC721,
(address(remoteToken), address(localToken), alice, bob, tokenId, hex"5678")
......@@ -181,7 +181,7 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer {
// Bridge the token.
vm.prank(alice);
L2NFTBridge.bridgeERC721To(address(localToken), address(remoteToken), bob, tokenId, 1234, hex"5678");
l2ERC721Bridge.bridgeERC721To(address(localToken), address(remoteToken), bob, tokenId, 1234, hex"5678");
// Token is burned.
vm.expectRevert("ERC721: invalid token ID");
......@@ -193,7 +193,7 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer {
// Bridge the token.
vm.prank(alice);
vm.expectRevert();
L2NFTBridge.bridgeERC721To(address(0), address(L1NFTBridge), bob, tokenId, 1234, hex"5678");
l2ERC721Bridge.bridgeERC721To(address(0), address(l1ERC721Bridge), bob, tokenId, 1234, hex"5678");
// Token is not locked in the bridge.
assertEq(localToken.ownerOf(tokenId), alice);
......@@ -204,7 +204,7 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer {
// Bridge the token.
vm.prank(alice);
vm.expectRevert("L2ERC721Bridge: remote token cannot be address(0)");
L2NFTBridge.bridgeERC721To(address(localToken), address(0), bob, tokenId, 1234, hex"5678");
l2ERC721Bridge.bridgeERC721To(address(localToken), address(0), bob, tokenId, 1234, hex"5678");
// Token is not locked in the bridge.
assertEq(localToken.ownerOf(tokenId), alice);
......@@ -215,7 +215,7 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer {
// Bridge the token.
vm.prank(bob);
vm.expectRevert("L2ERC721Bridge: Withdrawal is not being initiated by NFT owner");
L2NFTBridge.bridgeERC721To(address(localToken), address(remoteToken), bob, tokenId, 1234, hex"5678");
l2ERC721Bridge.bridgeERC721To(address(localToken), address(remoteToken), bob, tokenId, 1234, hex"5678");
// Token is not locked in the bridge.
assertEq(localToken.ownerOf(tokenId), alice);
......@@ -225,7 +225,7 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer {
function test_finalizeBridgeERC721_succeeds() external {
// Bridge the token.
vm.prank(alice);
L2NFTBridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex"5678");
l2ERC721Bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex"5678");
// Expect an event to be emitted.
vm.expectEmit(true, true, true, true);
......@@ -233,12 +233,12 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer {
// Finalize a withdrawal.
vm.mockCall(
address(L2Messenger),
abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector),
abi.encode(L1NFTBridge)
address(l2CrossDomainMessenger),
abi.encodeWithSelector(l2CrossDomainMessenger.xDomainMessageSender.selector),
abi.encode(l1ERC721Bridge)
);
vm.prank(address(L2Messenger));
L2NFTBridge.finalizeBridgeERC721(address(localToken), address(remoteToken), alice, alice, tokenId, hex"5678");
vm.prank(address(l2CrossDomainMessenger));
l2ERC721Bridge.finalizeBridgeERC721(address(localToken), address(remoteToken), alice, alice, tokenId, hex"5678");
// Token is not locked in the bridge.
assertEq(localToken.ownerOf(tokenId), alice);
......@@ -252,18 +252,18 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer {
// Bridge the non-compliant token.
vm.prank(alice);
L2NFTBridge.bridgeERC721(address(nonCompliantToken), address(0x01), tokenId, 1234, hex"5678");
l2ERC721Bridge.bridgeERC721(address(nonCompliantToken), address(0x01), tokenId, 1234, hex"5678");
// Attempt to finalize the withdrawal. Should revert because the token does not claim
// to be compliant with the `IOptimismMintableERC721` interface.
vm.mockCall(
address(L2Messenger),
abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector),
abi.encode(L1NFTBridge)
address(l2CrossDomainMessenger),
abi.encodeWithSelector(l2CrossDomainMessenger.xDomainMessageSender.selector),
abi.encode(l1ERC721Bridge)
);
vm.prank(address(L2Messenger));
vm.prank(address(l2CrossDomainMessenger));
vm.expectRevert("L2ERC721Bridge: local token interface is not compliant");
L2NFTBridge.finalizeBridgeERC721(
l2ERC721Bridge.finalizeBridgeERC721(
address(address(nonCompliantToken)), address(address(0x01)), alice, alice, tokenId, hex"5678"
);
}
......@@ -273,18 +273,20 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer {
// Finalize a withdrawal.
vm.prank(alice);
vm.expectRevert("ERC721Bridge: function can only be called from the other bridge");
L2NFTBridge.finalizeBridgeERC721(address(localToken), address(remoteToken), alice, alice, tokenId, hex"5678");
l2ERC721Bridge.finalizeBridgeERC721(address(localToken), address(remoteToken), alice, alice, tokenId, hex"5678");
}
/// @dev Tests that `finalizeBridgeERC721` reverts when not called by the remote bridge.
function test_finalizeBridgeERC721_notFromRemoteMessenger_reverts() external {
// Finalize a withdrawal.
vm.mockCall(
address(L2Messenger), abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector), abi.encode(alice)
address(l2CrossDomainMessenger),
abi.encodeWithSelector(l2CrossDomainMessenger.xDomainMessageSender.selector),
abi.encode(alice)
);
vm.prank(address(L2Messenger));
vm.prank(address(l2CrossDomainMessenger));
vm.expectRevert("ERC721Bridge: function can only be called from the other bridge");
L2NFTBridge.finalizeBridgeERC721(address(localToken), address(remoteToken), alice, alice, tokenId, hex"5678");
l2ERC721Bridge.finalizeBridgeERC721(address(localToken), address(remoteToken), alice, alice, tokenId, hex"5678");
}
/// @dev Tests that `finalizeBridgeERC721` reverts when the local token is the
......@@ -292,26 +294,28 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer {
function test_finalizeBridgeERC721_selfToken_reverts() external {
// Finalize a withdrawal.
vm.mockCall(
address(L2Messenger),
abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector),
abi.encode(address(L1NFTBridge))
address(l2CrossDomainMessenger),
abi.encodeWithSelector(l2CrossDomainMessenger.xDomainMessageSender.selector),
abi.encode(address(l1ERC721Bridge))
);
vm.prank(address(L2Messenger));
vm.prank(address(l2CrossDomainMessenger));
vm.expectRevert("L2ERC721Bridge: local token cannot be self");
L2NFTBridge.finalizeBridgeERC721(address(L2NFTBridge), address(remoteToken), alice, alice, tokenId, hex"5678");
l2ERC721Bridge.finalizeBridgeERC721(
address(l2ERC721Bridge), address(remoteToken), alice, alice, tokenId, hex"5678"
);
}
/// @dev Tests that `finalizeBridgeERC721` reverts when already finalized.
function test_finalizeBridgeERC721_alreadyExists_reverts() external {
// Finalize a withdrawal.
vm.mockCall(
address(L2Messenger),
abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector),
abi.encode(address(L1NFTBridge))
address(l2CrossDomainMessenger),
abi.encodeWithSelector(l2CrossDomainMessenger.xDomainMessageSender.selector),
abi.encode(address(l1ERC721Bridge))
);
vm.prank(address(L2Messenger));
vm.prank(address(l2CrossDomainMessenger));
vm.expectRevert("ERC721: token already minted");
L2NFTBridge.finalizeBridgeERC721(address(localToken), address(remoteToken), alice, alice, tokenId, hex"5678");
l2ERC721Bridge.finalizeBridgeERC721(address(localToken), address(remoteToken), alice, alice, tokenId, hex"5678");
}
}
......
......@@ -20,23 +20,32 @@ import { L2OutputOracle } from "src/L1/L2OutputOracle.sol";
contract L2OutputOracle_constructor_Test is L2OutputOracle_Initializer {
/// @dev Tests that constructor sets the initial values correctly.
function test_constructor_succeeds() external {
assertEq(oracle.PROPOSER(), proposer);
assertEq(oracle.proposer(), proposer);
assertEq(oracle.CHALLENGER(), owner);
assertEq(oracle.challenger(), owner);
assertEq(oracle.SUBMISSION_INTERVAL(), submissionInterval);
assertEq(oracle.submissionInterval(), submissionInterval);
assertEq(oracle.latestBlockNumber(), startingBlockNumber);
assertEq(oracle.startingBlockNumber(), startingBlockNumber);
assertEq(oracle.startingTimestamp(), startingTimestamp);
assertEq(oracle.L2_BLOCK_TIME(), l2BlockTime);
assertEq(oracle.l2BlockTime(), l2BlockTime);
assertEq(oracle.finalizationPeriodSeconds(), finalizationPeriodSeconds);
assertEq(oracle.FINALIZATION_PERIOD_SECONDS(), finalizationPeriodSeconds);
address proposer = cfg.l2OutputOracleProposer();
address challenger = cfg.l2OutputOracleChallenger();
uint256 submissionInterval = cfg.l2OutputOracleSubmissionInterval();
uint256 startingBlockNumber = cfg.l2OutputOracleStartingBlockNumber();
uint256 startingTimestamp = cfg.l2OutputOracleStartingTimestamp();
uint256 l2BlockTime = cfg.l2BlockTime();
uint256 finalizationPeriodSeconds = cfg.finalizationPeriodSeconds();
assertEq(l2OutputOracle.PROPOSER(), proposer);
assertEq(l2OutputOracle.proposer(), proposer);
assertEq(l2OutputOracle.CHALLENGER(), challenger);
assertEq(l2OutputOracle.challenger(), challenger);
assertEq(l2OutputOracle.SUBMISSION_INTERVAL(), submissionInterval);
assertEq(l2OutputOracle.submissionInterval(), submissionInterval);
assertEq(l2OutputOracle.latestBlockNumber(), startingBlockNumber);
assertEq(l2OutputOracle.startingBlockNumber(), startingBlockNumber);
assertEq(l2OutputOracle.startingTimestamp(), startingTimestamp);
assertEq(l2OutputOracle.L2_BLOCK_TIME(), l2BlockTime);
assertEq(l2OutputOracle.l2BlockTime(), l2BlockTime);
assertEq(l2OutputOracle.finalizationPeriodSeconds(), finalizationPeriodSeconds);
assertEq(l2OutputOracle.FINALIZATION_PERIOD_SECONDS(), finalizationPeriodSeconds);
}
/// @dev Tests that the constructor reverts if the l2BlockTime is invalid.
function test_constructor_l2BlockTimeZero_reverts() external {
uint256 submissionInterval = cfg.l2OutputOracleSubmissionInterval();
vm.expectRevert("L2OutputOracle: L2 block time must be greater than 0");
new L2OutputOracle({
_submissionInterval: submissionInterval,
......@@ -47,6 +56,7 @@ contract L2OutputOracle_constructor_Test is L2OutputOracle_Initializer {
/// @dev Tests that the constructor reverts if the submissionInterval is zero.
function test_constructor_submissionInterval_reverts() external {
uint256 l2BlockTime = cfg.l2BlockTime();
vm.expectRevert("L2OutputOracle: submission interval must be greater than 0");
new L2OutputOracle({
_submissionInterval: 0,
......@@ -59,9 +69,9 @@ contract L2OutputOracle_constructor_Test is L2OutputOracle_Initializer {
function test_initialize_badTimestamp_reverts() external {
// Reset the initialized field in the 0th storage slot
// so that initialize can be called again.
vm.store(address(oracle), bytes32(uint256(0)), bytes32(uint256(0)));
vm.store(address(l2OutputOracle), bytes32(uint256(0)), bytes32(uint256(0)));
vm.expectRevert("L2OutputOracle: starting L2 timestamp must be less than current time");
oracle.initialize({
l2OutputOracle.initialize({
_startingBlockNumber: 0,
_startingTimestamp: block.timestamp + 1,
_proposer: address(0),
......@@ -75,43 +85,43 @@ contract L2OutputOracle_getter_Test is L2OutputOracle_Initializer {
/// @dev Tests that `latestBlockNumber` returns the correct value.
function test_latestBlockNumber_succeeds() external {
uint256 proposedNumber = oracle.nextBlockNumber();
uint256 proposedNumber = l2OutputOracle.nextBlockNumber();
// Roll to after the block number we'll propose
warpToProposeTime(proposedNumber);
vm.prank(proposer);
oracle.proposeL2Output(proposedOutput1, proposedNumber, 0, 0);
assertEq(oracle.latestBlockNumber(), proposedNumber);
vm.prank(cfg.l2OutputOracleProposer());
l2OutputOracle.proposeL2Output(proposedOutput1, proposedNumber, 0, 0);
assertEq(l2OutputOracle.latestBlockNumber(), proposedNumber);
}
/// @dev Tests that `getL2Output` returns the correct value.
function test_getL2Output_succeeds() external {
uint256 nextBlockNumber = oracle.nextBlockNumber();
uint256 nextOutputIndex = oracle.nextOutputIndex();
uint256 nextBlockNumber = l2OutputOracle.nextBlockNumber();
uint256 nextOutputIndex = l2OutputOracle.nextOutputIndex();
warpToProposeTime(nextBlockNumber);
vm.prank(proposer);
oracle.proposeL2Output(proposedOutput1, nextBlockNumber, 0, 0);
vm.prank(cfg.l2OutputOracleProposer());
l2OutputOracle.proposeL2Output(proposedOutput1, nextBlockNumber, 0, 0);
Types.OutputProposal memory proposal = oracle.getL2Output(nextOutputIndex);
Types.OutputProposal memory proposal = l2OutputOracle.getL2Output(nextOutputIndex);
assertEq(proposal.outputRoot, proposedOutput1);
assertEq(proposal.timestamp, block.timestamp);
// The block number is larger than the latest proposed output:
vm.expectRevert(stdError.indexOOBError);
oracle.getL2Output(nextOutputIndex + 1);
l2OutputOracle.getL2Output(nextOutputIndex + 1);
}
/// @dev Tests that `getL2OutputIndexAfter` returns the correct value
/// when the input is the exact block number of the proposal.
function test_getL2OutputIndexAfter_sameBlock_succeeds() external {
bytes32 output1 = keccak256(abi.encode(1));
uint256 nextBlockNumber1 = oracle.nextBlockNumber();
uint256 nextBlockNumber1 = l2OutputOracle.nextBlockNumber();
warpToProposeTime(nextBlockNumber1);
vm.prank(proposer);
oracle.proposeL2Output(output1, nextBlockNumber1, 0, 0);
vm.prank(cfg.l2OutputOracleProposer());
l2OutputOracle.proposeL2Output(output1, nextBlockNumber1, 0, 0);
// Querying with exact same block as proposed returns the proposal.
uint256 index1 = oracle.getL2OutputIndexAfter(nextBlockNumber1);
uint256 index1 = l2OutputOracle.getL2OutputIndexAfter(nextBlockNumber1);
assertEq(index1, 0);
}
......@@ -119,84 +129,90 @@ contract L2OutputOracle_getter_Test is L2OutputOracle_Initializer {
/// when the input is the previous block number of the proposal.
function test_getL2OutputIndexAfter_previousBlock_succeeds() external {
bytes32 output1 = keccak256(abi.encode(1));
uint256 nextBlockNumber1 = oracle.nextBlockNumber();
uint256 nextBlockNumber1 = l2OutputOracle.nextBlockNumber();
warpToProposeTime(nextBlockNumber1);
vm.prank(proposer);
oracle.proposeL2Output(output1, nextBlockNumber1, 0, 0);
vm.prank(cfg.l2OutputOracleProposer());
l2OutputOracle.proposeL2Output(output1, nextBlockNumber1, 0, 0);
// Querying with previous block returns the proposal too.
uint256 index1 = oracle.getL2OutputIndexAfter(nextBlockNumber1 - 1);
uint256 index1 = l2OutputOracle.getL2OutputIndexAfter(nextBlockNumber1 - 1);
assertEq(index1, 0);
}
/// @dev Tests that `getL2OutputIndexAfter` returns the correct value.
function test_getL2OutputIndexAfter_multipleOutputsExist_succeeds() external {
bytes32 output1 = keccak256(abi.encode(1));
uint256 nextBlockNumber1 = oracle.nextBlockNumber();
uint256 nextBlockNumber1 = l2OutputOracle.nextBlockNumber();
warpToProposeTime(nextBlockNumber1);
vm.prank(proposer);
oracle.proposeL2Output(output1, nextBlockNumber1, 0, 0);
vm.prank(cfg.l2OutputOracleProposer());
l2OutputOracle.proposeL2Output(output1, nextBlockNumber1, 0, 0);
bytes32 output2 = keccak256(abi.encode(2));
uint256 nextBlockNumber2 = oracle.nextBlockNumber();
uint256 nextBlockNumber2 = l2OutputOracle.nextBlockNumber();
warpToProposeTime(nextBlockNumber2);
vm.prank(proposer);
oracle.proposeL2Output(output2, nextBlockNumber2, 0, 0);
vm.prank(cfg.l2OutputOracleProposer());
l2OutputOracle.proposeL2Output(output2, nextBlockNumber2, 0, 0);
bytes32 output3 = keccak256(abi.encode(3));
uint256 nextBlockNumber3 = oracle.nextBlockNumber();
uint256 nextBlockNumber3 = l2OutputOracle.nextBlockNumber();
warpToProposeTime(nextBlockNumber3);
vm.prank(proposer);
oracle.proposeL2Output(output3, nextBlockNumber3, 0, 0);
vm.prank(cfg.l2OutputOracleProposer());
l2OutputOracle.proposeL2Output(output3, nextBlockNumber3, 0, 0);
bytes32 output4 = keccak256(abi.encode(4));
uint256 nextBlockNumber4 = oracle.nextBlockNumber();
uint256 nextBlockNumber4 = l2OutputOracle.nextBlockNumber();
warpToProposeTime(nextBlockNumber4);
vm.prank(proposer);
oracle.proposeL2Output(output4, nextBlockNumber4, 0, 0);
vm.prank(cfg.l2OutputOracleProposer());
l2OutputOracle.proposeL2Output(output4, nextBlockNumber4, 0, 0);
// Querying with a block number between the first and second proposal
uint256 index1 = oracle.getL2OutputIndexAfter(nextBlockNumber1 + 1);
uint256 index1 = l2OutputOracle.getL2OutputIndexAfter(nextBlockNumber1 + 1);
assertEq(index1, 1);
// Querying with a block number between the second and third proposal
uint256 index2 = oracle.getL2OutputIndexAfter(nextBlockNumber2 + 1);
uint256 index2 = l2OutputOracle.getL2OutputIndexAfter(nextBlockNumber2 + 1);
assertEq(index2, 2);
// Querying with a block number between the third and fourth proposal
uint256 index3 = oracle.getL2OutputIndexAfter(nextBlockNumber3 + 1);
uint256 index3 = l2OutputOracle.getL2OutputIndexAfter(nextBlockNumber3 + 1);
assertEq(index3, 3);
}
/// @dev Tests that `getL2OutputIndexAfter` reverts when no output exists.
function test_getL2OutputIndexAfter_noOutputsExis_reverts() external {
vm.expectRevert("L2OutputOracle: cannot get output as no outputs have been proposed yet");
oracle.getL2OutputIndexAfter(0);
l2OutputOracle.getL2OutputIndexAfter(0);
}
/// @dev Tests that `nextBlockNumber` returns the correct value.
function test_nextBlockNumber_succeeds() external {
assertEq(
oracle.nextBlockNumber(),
l2OutputOracle.nextBlockNumber(),
// The return value should match this arithmetic
oracle.latestBlockNumber() + oracle.SUBMISSION_INTERVAL()
l2OutputOracle.latestBlockNumber() + l2OutputOracle.SUBMISSION_INTERVAL()
);
}
/// @dev Tests that `computeL2Timestamp` returns the correct value.
function test_computeL2Timestamp_succeeds() external {
uint256 startingBlockNumber = cfg.l2OutputOracleStartingBlockNumber();
uint256 startingTimestamp = cfg.l2OutputOracleStartingTimestamp();
uint256 l2BlockTime = cfg.l2BlockTime();
// reverts if timestamp is too low
vm.expectRevert(stdError.arithmeticError);
oracle.computeL2Timestamp(startingBlockNumber - 1);
l2OutputOracle.computeL2Timestamp(startingBlockNumber - 1);
// check timestamp for the very first block
assertEq(oracle.computeL2Timestamp(startingBlockNumber), startingTimestamp);
assertEq(l2OutputOracle.computeL2Timestamp(startingBlockNumber), startingTimestamp);
// check timestamp for the first block after the starting block
assertEq(oracle.computeL2Timestamp(startingBlockNumber + 1), startingTimestamp + l2BlockTime);
assertEq(l2OutputOracle.computeL2Timestamp(startingBlockNumber + 1), startingTimestamp + l2BlockTime);
// check timestamp for some other block number
assertEq(oracle.computeL2Timestamp(startingBlockNumber + 96024), startingTimestamp + l2BlockTime * 96024);
assertEq(
l2OutputOracle.computeL2Timestamp(startingBlockNumber + 96024), startingTimestamp + l2BlockTime * 96024
);
}
}
......@@ -214,62 +230,62 @@ contract L2OutputOracle_proposeL2Output_Test is L2OutputOracle_Initializer {
uint256 prevL1BlockNumber = block.number - 1;
bytes32 prevL1BlockHash = blockhash(prevL1BlockNumber);
uint256 nextBlockNumber = oracle.nextBlockNumber();
uint256 nextBlockNumber = l2OutputOracle.nextBlockNumber();
warpToProposeTime(nextBlockNumber);
vm.prank(proposer);
oracle.proposeL2Output(nonZeroHash, nextBlockNumber, prevL1BlockHash, prevL1BlockNumber);
vm.prank(cfg.l2OutputOracleProposer());
l2OutputOracle.proposeL2Output(nonZeroHash, nextBlockNumber, prevL1BlockHash, prevL1BlockNumber);
}
/// @dev Tests that `proposeL2Output` reverts when called by a party
/// that is not the proposer.
function test_proposeL2Output_notProposer_reverts() external {
uint256 nextBlockNumber = oracle.nextBlockNumber();
uint256 nextBlockNumber = l2OutputOracle.nextBlockNumber();
warpToProposeTime(nextBlockNumber);
vm.prank(address(128));
vm.expectRevert("L2OutputOracle: only the proposer address can propose new outputs");
oracle.proposeL2Output(nonZeroHash, nextBlockNumber, 0, 0);
l2OutputOracle.proposeL2Output(nonZeroHash, nextBlockNumber, 0, 0);
}
/// @dev Tests that `proposeL2Output` reverts when given a zero blockhash.
function test_proposeL2Output_emptyOutput_reverts() external {
bytes32 outputToPropose = bytes32(0);
uint256 nextBlockNumber = oracle.nextBlockNumber();
uint256 nextBlockNumber = l2OutputOracle.nextBlockNumber();
warpToProposeTime(nextBlockNumber);
vm.prank(proposer);
vm.prank(cfg.l2OutputOracleProposer());
vm.expectRevert("L2OutputOracle: L2 output proposal cannot be the zero hash");
oracle.proposeL2Output(outputToPropose, nextBlockNumber, 0, 0);
l2OutputOracle.proposeL2Output(outputToPropose, nextBlockNumber, 0, 0);
}
/// @dev Tests that `proposeL2Output` reverts when given a block number
/// that does not match the next expected block number.
function test_proposeL2Output_unexpectedBlockNumber_reverts() external {
uint256 nextBlockNumber = oracle.nextBlockNumber();
uint256 nextBlockNumber = l2OutputOracle.nextBlockNumber();
warpToProposeTime(nextBlockNumber);
vm.prank(proposer);
vm.prank(cfg.l2OutputOracleProposer());
vm.expectRevert("L2OutputOracle: block number must be equal to next expected block number");
oracle.proposeL2Output(nonZeroHash, nextBlockNumber - 1, 0, 0);
l2OutputOracle.proposeL2Output(nonZeroHash, nextBlockNumber - 1, 0, 0);
}
/// @dev Tests that `proposeL2Output` reverts when given a block number
/// that has a timestamp in the future.
function test_proposeL2Output_futureTimetamp_reverts() external {
uint256 nextBlockNumber = oracle.nextBlockNumber();
uint256 nextTimestamp = oracle.computeL2Timestamp(nextBlockNumber);
uint256 nextBlockNumber = l2OutputOracle.nextBlockNumber();
uint256 nextTimestamp = l2OutputOracle.computeL2Timestamp(nextBlockNumber);
vm.warp(nextTimestamp);
vm.prank(proposer);
vm.prank(cfg.l2OutputOracleProposer());
vm.expectRevert("L2OutputOracle: cannot propose L2 output in the future");
oracle.proposeL2Output(nonZeroHash, nextBlockNumber, 0, 0);
l2OutputOracle.proposeL2Output(nonZeroHash, nextBlockNumber, 0, 0);
}
/// @dev Tests that `proposeL2Output` reverts when given a block number
/// whose hash does not match the given block hash.
function test_proposeL2Output_wrongFork_reverts() external {
uint256 nextBlockNumber = oracle.nextBlockNumber();
uint256 nextBlockNumber = l2OutputOracle.nextBlockNumber();
warpToProposeTime(nextBlockNumber);
vm.prank(proposer);
vm.prank(cfg.l2OutputOracleProposer());
vm.expectRevert("L2OutputOracle: block hash does not match the hash at the expected height");
oracle.proposeL2Output(nonZeroHash, nextBlockNumber, bytes32(uint256(0x01)), block.number - 1);
l2OutputOracle.proposeL2Output(nonZeroHash, nextBlockNumber, bytes32(uint256(0x01)), block.number);
}
/// @dev Tests that `proposeL2Output` reverts when given a block number
......@@ -282,13 +298,13 @@ contract L2OutputOracle_proposeL2Output_Test is L2OutputOracle_Initializer {
uint256 l1BlockNumber = block.number - 1;
bytes32 l1BlockHash = blockhash(l1BlockNumber);
uint256 nextBlockNumber = oracle.nextBlockNumber();
uint256 nextBlockNumber = l2OutputOracle.nextBlockNumber();
warpToProposeTime(nextBlockNumber);
vm.prank(proposer);
vm.prank(cfg.l2OutputOracleProposer());
// This will fail when foundry no longer returns zerod block hashes
vm.expectRevert("L2OutputOracle: block hash does not match the hash at the expected height");
oracle.proposeL2Output(nonZeroHash, nextBlockNumber, l1BlockHash, l1BlockNumber - 1);
l2OutputOracle.proposeL2Output(nonZeroHash, nextBlockNumber, l1BlockHash, l1BlockNumber - 1);
}
}
......@@ -298,22 +314,23 @@ contract L2OutputOracle_deleteOutputs_Test is L2OutputOracle_Initializer {
proposeAnotherOutput();
proposeAnotherOutput();
uint256 latestBlockNumber = oracle.latestBlockNumber();
uint256 latestOutputIndex = oracle.latestOutputIndex();
Types.OutputProposal memory newLatestOutput = oracle.getL2Output(latestOutputIndex - 1);
uint256 latestBlockNumber = l2OutputOracle.latestBlockNumber();
uint256 latestOutputIndex = l2OutputOracle.latestOutputIndex();
Types.OutputProposal memory newLatestOutput = l2OutputOracle.getL2Output(latestOutputIndex - 1);
vm.prank(owner);
vm.prank(l2OutputOracle.challenger());
vm.expectEmit(true, true, false, false);
emit OutputsDeleted(latestOutputIndex + 1, latestOutputIndex);
oracle.deleteL2Outputs(latestOutputIndex);
l2OutputOracle.deleteL2Outputs(latestOutputIndex);
// validate latestBlockNumber has been reduced
uint256 latestBlockNumberAfter = oracle.latestBlockNumber();
uint256 latestOutputIndexAfter = oracle.latestOutputIndex();
uint256 latestBlockNumberAfter = l2OutputOracle.latestBlockNumber();
uint256 latestOutputIndexAfter = l2OutputOracle.latestOutputIndex();
uint256 submissionInterval = cfg.l2OutputOracleSubmissionInterval();
assertEq(latestBlockNumber - submissionInterval, latestBlockNumberAfter);
// validate that the new latest output is as expected.
Types.OutputProposal memory proposal = oracle.getL2Output(latestOutputIndexAfter);
Types.OutputProposal memory proposal = l2OutputOracle.getL2Output(latestOutputIndexAfter);
assertEq(newLatestOutput.outputRoot, proposal.outputRoot);
assertEq(newLatestOutput.timestamp, proposal.timestamp);
}
......@@ -325,43 +342,44 @@ contract L2OutputOracle_deleteOutputs_Test is L2OutputOracle_Initializer {
proposeAnotherOutput();
proposeAnotherOutput();
uint256 latestBlockNumber = oracle.latestBlockNumber();
uint256 latestOutputIndex = oracle.latestOutputIndex();
Types.OutputProposal memory newLatestOutput = oracle.getL2Output(latestOutputIndex - 3);
uint256 latestBlockNumber = l2OutputOracle.latestBlockNumber();
uint256 latestOutputIndex = l2OutputOracle.latestOutputIndex();
Types.OutputProposal memory newLatestOutput = l2OutputOracle.getL2Output(latestOutputIndex - 3);
vm.prank(owner);
vm.prank(l2OutputOracle.challenger());
vm.expectEmit(true, true, false, false);
emit OutputsDeleted(latestOutputIndex + 1, latestOutputIndex - 2);
oracle.deleteL2Outputs(latestOutputIndex - 2);
l2OutputOracle.deleteL2Outputs(latestOutputIndex - 2);
// validate latestBlockNumber has been reduced
uint256 latestBlockNumberAfter = oracle.latestBlockNumber();
uint256 latestOutputIndexAfter = oracle.latestOutputIndex();
uint256 latestBlockNumberAfter = l2OutputOracle.latestBlockNumber();
uint256 latestOutputIndexAfter = l2OutputOracle.latestOutputIndex();
uint256 submissionInterval = cfg.l2OutputOracleSubmissionInterval();
assertEq(latestBlockNumber - submissionInterval * 3, latestBlockNumberAfter);
// validate that the new latest output is as expected.
Types.OutputProposal memory proposal = oracle.getL2Output(latestOutputIndexAfter);
Types.OutputProposal memory proposal = l2OutputOracle.getL2Output(latestOutputIndexAfter);
assertEq(newLatestOutput.outputRoot, proposal.outputRoot);
assertEq(newLatestOutput.timestamp, proposal.timestamp);
}
/// @dev Tests that `deleteL2Outputs` reverts when not called by the challenger.
function test_deleteL2Outputs_ifNotChallenger_reverts() external {
uint256 latestBlockNumber = oracle.latestBlockNumber();
uint256 latestBlockNumber = l2OutputOracle.latestBlockNumber();
vm.expectRevert("L2OutputOracle: only the challenger address can delete outputs");
oracle.deleteL2Outputs(latestBlockNumber);
l2OutputOracle.deleteL2Outputs(latestBlockNumber);
}
/// @dev Tests that `deleteL2Outputs` reverts for a non-existant output index.
function test_deleteL2Outputs_nonExistent_reverts() external {
proposeAnotherOutput();
uint256 latestBlockNumber = oracle.latestBlockNumber();
uint256 latestBlockNumber = l2OutputOracle.latestBlockNumber();
vm.prank(owner);
vm.prank(l2OutputOracle.challenger());
vm.expectRevert("L2OutputOracle: cannot delete outputs after the latest output index");
oracle.deleteL2Outputs(latestBlockNumber + 1);
l2OutputOracle.deleteL2Outputs(latestBlockNumber + 1);
}
/// @dev Tests that `deleteL2Outputs` reverts when trying to delete outputs
......@@ -372,14 +390,14 @@ contract L2OutputOracle_deleteOutputs_Test is L2OutputOracle_Initializer {
proposeAnotherOutput();
// Delete the latest two outputs
uint256 latestOutputIndex = oracle.latestOutputIndex();
vm.prank(owner);
oracle.deleteL2Outputs(latestOutputIndex - 2);
uint256 latestOutputIndex = l2OutputOracle.latestOutputIndex();
vm.prank(l2OutputOracle.challenger());
l2OutputOracle.deleteL2Outputs(latestOutputIndex - 2);
// Now try to delete the same output again
vm.prank(owner);
vm.prank(l2OutputOracle.challenger());
vm.expectRevert("L2OutputOracle: cannot delete outputs after the latest output index");
oracle.deleteL2Outputs(latestOutputIndex - 2);
l2OutputOracle.deleteL2Outputs(latestOutputIndex - 2);
}
/// @dev Tests that `deleteL2Outputs` reverts for finalized outputs.
......@@ -387,43 +405,48 @@ contract L2OutputOracle_deleteOutputs_Test is L2OutputOracle_Initializer {
proposeAnotherOutput();
// Warp past the finalization period + 1 second
vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);
vm.warp(block.timestamp + l2OutputOracle.FINALIZATION_PERIOD_SECONDS() + 1);
uint256 latestOutputIndex = oracle.latestOutputIndex();
uint256 latestOutputIndex = l2OutputOracle.latestOutputIndex();
// Try to delete a finalized output
vm.prank(owner);
vm.prank(l2OutputOracle.challenger());
vm.expectRevert("L2OutputOracle: cannot delete outputs that have already been finalized");
oracle.deleteL2Outputs(latestOutputIndex);
l2OutputOracle.deleteL2Outputs(latestOutputIndex);
}
}
contract L2OutputOracleUpgradeable_Test is L2OutputOracle_Initializer {
Proxy internal proxy;
function setUp() public override {
super.setUp();
proxy = Proxy(payable(address(oracle)));
}
/// @dev Tests that the proxy is initialized with the correct values.
function test_initValuesOnProxy_succeeds() external {
assertEq(oracle.SUBMISSION_INTERVAL(), submissionInterval);
assertEq(oracle.submissionInterval(), submissionInterval);
assertEq(oracle.L2_BLOCK_TIME(), l2BlockTime);
assertEq(oracle.l2BlockTime(), l2BlockTime);
assertEq(oracle.startingBlockNumber(), startingBlockNumber);
assertEq(oracle.startingTimestamp(), startingTimestamp);
assertEq(oracle.finalizationPeriodSeconds(), finalizationPeriodSeconds);
assertEq(oracle.PROPOSER(), proposer);
assertEq(oracle.proposer(), proposer);
assertEq(oracle.CHALLENGER(), owner);
assertEq(oracle.challenger(), owner);
address proposer = cfg.l2OutputOracleProposer();
address challenger = cfg.l2OutputOracleChallenger();
uint256 submissionInterval = cfg.l2OutputOracleSubmissionInterval();
uint256 startingBlockNumber = cfg.l2OutputOracleStartingBlockNumber();
uint256 startingTimestamp = cfg.l2OutputOracleStartingTimestamp();
uint256 l2BlockTime = cfg.l2BlockTime();
uint256 finalizationPeriodSeconds = cfg.finalizationPeriodSeconds();
assertEq(l2OutputOracle.SUBMISSION_INTERVAL(), submissionInterval);
assertEq(l2OutputOracle.submissionInterval(), submissionInterval);
assertEq(l2OutputOracle.L2_BLOCK_TIME(), l2BlockTime);
assertEq(l2OutputOracle.l2BlockTime(), l2BlockTime);
assertEq(l2OutputOracle.startingBlockNumber(), startingBlockNumber);
assertEq(l2OutputOracle.startingTimestamp(), startingTimestamp);
assertEq(l2OutputOracle.finalizationPeriodSeconds(), finalizationPeriodSeconds);
assertEq(l2OutputOracle.PROPOSER(), proposer);
assertEq(l2OutputOracle.proposer(), proposer);
assertEq(l2OutputOracle.CHALLENGER(), challenger);
assertEq(l2OutputOracle.challenger(), challenger);
}
/// @dev Tests that the impl is created with the correct values.
function test_initValuesOnImpl_succeeds() external {
L2OutputOracle oracleImpl = L2OutputOracle(mustGetAddress("L2OutputOracle"));
uint256 submissionInterval = cfg.l2OutputOracleSubmissionInterval();
assertEq(submissionInterval, oracleImpl.SUBMISSION_INTERVAL());
uint256 l2BlockTime = cfg.l2BlockTime();
assertEq(l2BlockTime, oracleImpl.L2_BLOCK_TIME());
// The values that are set in the initialize function should be all
......@@ -438,8 +461,10 @@ contract L2OutputOracleUpgradeable_Test is L2OutputOracle_Initializer {
/// @dev Tests that the proxy cannot be initialized twice.
function test_initializeProxy_alreadyInitialized_reverts() external {
uint256 startingBlockNumber = cfg.l2OutputOracleStartingBlockNumber();
uint256 startingTimestamp = cfg.l2OutputOracleStartingTimestamp();
vm.expectRevert("Initializable: contract is already initialized");
L2OutputOracle(payable(proxy)).initialize({
l2OutputOracle.initialize({
_startingBlockNumber: startingBlockNumber,
_startingTimestamp: startingTimestamp,
_proposer: address(1),
......@@ -449,8 +474,11 @@ contract L2OutputOracleUpgradeable_Test is L2OutputOracle_Initializer {
/// @dev Tests that the implementation contract cannot be initialized twice.
function test_initializeImpl_alreadyInitialized_reverts() external {
L2OutputOracle oracleImpl = L2OutputOracle(mustGetAddress("L2OutputOracle"));
uint256 startingBlockNumber = cfg.l2OutputOracleStartingBlockNumber();
uint256 startingTimestamp = cfg.l2OutputOracleStartingTimestamp();
vm.expectRevert("Initializable: contract is already initialized");
L2OutputOracle(oracleImpl).initialize({
oracleImpl.initialize({
_startingBlockNumber: startingBlockNumber,
_startingTimestamp: startingTimestamp,
_proposer: address(1),
......@@ -460,8 +488,9 @@ contract L2OutputOracleUpgradeable_Test is L2OutputOracle_Initializer {
/// @dev Tests that the proxy can be successfully upgraded.
function test_upgrading_succeeds() external {
Proxy proxy = Proxy(mustGetAddress("L2OutputOracleProxy"));
// Check an unused slot before upgrading.
bytes32 slot21Before = vm.load(address(oracle), bytes32(uint256(21)));
bytes32 slot21Before = vm.load(address(l2OutputOracle), bytes32(uint256(21)));
assertEq(bytes32(0), slot21Before);
NextImpl nextImpl = new NextImpl();
......@@ -472,8 +501,8 @@ contract L2OutputOracleUpgradeable_Test is L2OutputOracle_Initializer {
assertEq(proxy.implementation(), address(nextImpl));
// Verify that the NextImpl contract initialized its values according as expected
bytes32 slot21After = vm.load(address(oracle), bytes32(uint256(21)));
bytes32 slot21Expected = NextImpl(address(oracle)).slot21Init();
bytes32 slot21After = vm.load(address(l2OutputOracle), bytes32(uint256(21)));
bytes32 slot21Expected = NextImpl(address(l2OutputOracle)).slot21Init();
assertEq(slot21Expected, slot21After);
}
}
......@@ -23,24 +23,24 @@ contract L2StandardBridge_Test is Bridge_Initializer {
/// @dev Tests that the bridge is initialized correctly.
function test_initialize_succeeds() external {
assertEq(address(L2Bridge.messenger()), address(L2Messenger));
assertEq(L1Bridge.l2TokenBridge(), address(L2Bridge));
assertEq(address(L2Bridge.OTHER_BRIDGE()), address(L1Bridge));
assertEq(address(l2StandardBridge.messenger()), address(l2CrossDomainMessenger));
assertEq(l1StandardBridge.l2TokenBridge(), address(l2StandardBridge));
assertEq(address(l2StandardBridge.OTHER_BRIDGE()), address(l1StandardBridge));
}
/// @dev Tests that the bridge receives ETH and successfully initiates a withdrawal.
function test_receive_succeeds() external {
assertEq(address(messagePasser).balance, 0);
uint256 nonce = L2Messenger.messageNonce();
assertEq(address(l2ToL1MessagePasser).balance, 0);
uint256 nonce = l2CrossDomainMessenger.messageNonce();
bytes memory message =
abi.encodeWithSelector(StandardBridge.finalizeBridgeETH.selector, alice, alice, 100, hex"");
uint64 baseGas = L2Messenger.baseGas(message, 200_000);
uint64 baseGas = l2CrossDomainMessenger.baseGas(message, 200_000);
bytes memory withdrawalData = abi.encodeWithSelector(
CrossDomainMessenger.relayMessage.selector,
nonce,
address(L2Bridge),
address(L1Bridge),
address(l2StandardBridge),
address(l1StandardBridge),
100,
200_000,
message
......@@ -48,8 +48,8 @@ contract L2StandardBridge_Test is Bridge_Initializer {
bytes32 withdrawalHash = Hashing.hashWithdrawal(
Types.WithdrawalTransaction({
nonce: nonce,
sender: address(L2Messenger),
target: address(L1Messenger),
sender: address(l2CrossDomainMessenger),
target: address(l1CrossDomainMessenger),
value: 100,
gasLimit: baseGas,
data: withdrawalData
......@@ -63,24 +63,30 @@ contract L2StandardBridge_Test is Bridge_Initializer {
emit ETHBridgeInitiated(alice, alice, 100, hex"");
// L2ToL1MessagePasser will emit a MessagePassed event
vm.expectEmit(true, true, true, true, address(messagePasser));
vm.expectEmit(true, true, true, true, address(l2ToL1MessagePasser));
emit MessagePassed(
nonce, address(L2Messenger), address(L1Messenger), 100, baseGas, withdrawalData, withdrawalHash
nonce,
address(l2CrossDomainMessenger),
address(l1CrossDomainMessenger),
100,
baseGas,
withdrawalData,
withdrawalHash
);
// SentMessage event emitted by the CrossDomainMessenger
vm.expectEmit(true, true, true, true, address(L2Messenger));
emit SentMessage(address(L1Bridge), address(L2Bridge), message, nonce, 200_000);
vm.expectEmit(true, true, true, true, address(l2CrossDomainMessenger));
emit SentMessage(address(l1StandardBridge), address(l2StandardBridge), message, nonce, 200_000);
// SentMessageExtension1 event emitted by the CrossDomainMessenger
vm.expectEmit(true, true, true, true, address(L2Messenger));
emit SentMessageExtension1(address(L2Bridge), 100);
vm.expectEmit(true, true, true, true, address(l2CrossDomainMessenger));
emit SentMessageExtension1(address(l2StandardBridge), 100);
vm.expectCall(
address(L2Messenger),
address(l2CrossDomainMessenger),
abi.encodeWithSelector(
CrossDomainMessenger.sendMessage.selector,
address(L1Bridge),
address(l1StandardBridge),
message,
200_000 // StandardBridge's RECEIVE_DEFAULT_GAS_LIMIT
)
......@@ -89,23 +95,26 @@ contract L2StandardBridge_Test is Bridge_Initializer {
vm.expectCall(
Predeploys.L2_TO_L1_MESSAGE_PASSER,
abi.encodeWithSelector(
L2ToL1MessagePasser.initiateWithdrawal.selector, address(L1Messenger), baseGas, withdrawalData
L2ToL1MessagePasser.initiateWithdrawal.selector,
address(l1CrossDomainMessenger),
baseGas,
withdrawalData
)
);
vm.prank(alice, alice);
(bool success,) = address(L2Bridge).call{ value: 100 }(hex"");
(bool success,) = address(l2StandardBridge).call{ value: 100 }(hex"");
assertEq(success, true);
assertEq(address(messagePasser).balance, 100);
assertEq(address(l2ToL1MessagePasser).balance, 100);
}
/// @dev Tests that `withdraw` reverts if the amount is not equal to the value sent.
function test_withdraw_insufficientValue_reverts() external {
assertEq(address(messagePasser).balance, 0);
assertEq(address(l2ToL1MessagePasser).balance, 0);
vm.expectRevert("StandardBridge: bridging ETH must include sufficient ETH value");
vm.prank(alice, alice);
L2Bridge.withdraw(address(Predeploys.LEGACY_ERC20_ETH), 100, 1000, hex"");
l2StandardBridge.withdraw(address(Predeploys.LEGACY_ERC20_ETH), 100, 1000, hex"");
}
/// @dev Tests that the legacy `withdraw` interface on the L2StandardBridge
......@@ -114,7 +123,7 @@ contract L2StandardBridge_Test is Bridge_Initializer {
assertTrue(alice.balance >= 100);
assertEq(Predeploys.L2_TO_L1_MESSAGE_PASSER.balance, 0);
vm.expectEmit(true, true, true, true, address(L2Bridge));
vm.expectEmit(true, true, true, true, address(l2StandardBridge));
emit WithdrawalInitiated({
l1Token: address(0),
l2Token: Predeploys.LEGACY_ERC20_ETH,
......@@ -124,11 +133,11 @@ contract L2StandardBridge_Test is Bridge_Initializer {
data: hex""
});
vm.expectEmit(true, true, true, true, address(L2Bridge));
vm.expectEmit(true, true, true, true, address(l2StandardBridge));
emit ETHBridgeInitiated({ from: alice, to: alice, amount: 100, data: hex"" });
vm.prank(alice, alice);
L2Bridge.withdraw{ value: 100 }({
l2StandardBridge.withdraw{ value: 100 }({
_l2Token: Predeploys.LEGACY_ERC20_ETH,
_amount: 100,
_minGasLimit: 1000,
......@@ -145,19 +154,25 @@ contract PreBridgeERC20 is Bridge_Initializer {
// Alice has 100 L2Token
deal(_l2Token, alice, 100, true);
assertEq(ERC20(_l2Token).balanceOf(alice), 100);
uint256 nonce = L2Messenger.messageNonce();
uint256 nonce = l2CrossDomainMessenger.messageNonce();
bytes memory message = abi.encodeWithSelector(
StandardBridge.finalizeBridgeERC20.selector, address(L1Token), _l2Token, alice, alice, 100, hex""
);
uint64 baseGas = L2Messenger.baseGas(message, 1000);
uint64 baseGas = l2CrossDomainMessenger.baseGas(message, 1000);
bytes memory withdrawalData = abi.encodeWithSelector(
CrossDomainMessenger.relayMessage.selector, nonce, address(L2Bridge), address(L1Bridge), 0, 1000, message
CrossDomainMessenger.relayMessage.selector,
nonce,
address(l2StandardBridge),
address(l1StandardBridge),
0,
1000,
message
);
bytes32 withdrawalHash = Hashing.hashWithdrawal(
Types.WithdrawalTransaction({
nonce: nonce,
sender: address(L2Messenger),
target: address(L1Messenger),
sender: address(l2CrossDomainMessenger),
target: address(l1CrossDomainMessenger),
value: 0,
gasLimit: baseGas,
data: withdrawalData
......@@ -166,28 +181,34 @@ contract PreBridgeERC20 is Bridge_Initializer {
if (_isLegacy) {
vm.expectCall(
address(L2Bridge), abi.encodeWithSelector(L2Bridge.withdraw.selector, _l2Token, 100, 1000, hex"")
address(l2StandardBridge),
abi.encodeWithSelector(l2StandardBridge.withdraw.selector, _l2Token, 100, 1000, hex"")
);
} else {
vm.expectCall(
address(L2Bridge),
abi.encodeWithSelector(L2Bridge.bridgeERC20.selector, _l2Token, address(L1Token), 100, 1000, hex"")
address(l2StandardBridge),
abi.encodeWithSelector(
l2StandardBridge.bridgeERC20.selector, _l2Token, address(L1Token), 100, 1000, hex""
)
);
}
vm.expectCall(
address(L2Messenger),
abi.encodeWithSelector(CrossDomainMessenger.sendMessage.selector, address(L1Bridge), message, 1000)
address(l2CrossDomainMessenger),
abi.encodeWithSelector(CrossDomainMessenger.sendMessage.selector, address(l1StandardBridge), message, 1000)
);
vm.expectCall(
Predeploys.L2_TO_L1_MESSAGE_PASSER,
abi.encodeWithSelector(
L2ToL1MessagePasser.initiateWithdrawal.selector, address(L1Messenger), baseGas, withdrawalData
L2ToL1MessagePasser.initiateWithdrawal.selector,
address(l1CrossDomainMessenger),
baseGas,
withdrawalData
)
);
// The L2Bridge should burn the tokens
// The l2StandardBridge should burn the tokens
vm.expectCall(_l2Token, abi.encodeWithSelector(OptimismMintableERC20.burn.selector, alice, 100));
vm.expectEmit(true, true, true, true);
......@@ -198,16 +219,22 @@ contract PreBridgeERC20 is Bridge_Initializer {
vm.expectEmit(true, true, true, true);
emit MessagePassed(
nonce, address(L2Messenger), address(L1Messenger), 0, baseGas, withdrawalData, withdrawalHash
nonce,
address(l2CrossDomainMessenger),
address(l1CrossDomainMessenger),
0,
baseGas,
withdrawalData,
withdrawalHash
);
// SentMessage event emitted by the CrossDomainMessenger
vm.expectEmit(true, true, true, true);
emit SentMessage(address(L1Bridge), address(L2Bridge), message, nonce, 1000);
emit SentMessage(address(l1StandardBridge), address(l2StandardBridge), message, nonce, 1000);
// SentMessageExtension1 event emitted by the CrossDomainMessenger
vm.expectEmit(true, true, true, true);
emit SentMessageExtension1(address(L2Bridge), 0);
emit SentMessageExtension1(address(l2StandardBridge), 0);
vm.prank(alice, alice);
}
......@@ -220,7 +247,7 @@ contract L2StandardBridge_BridgeERC20_Test is PreBridgeERC20 {
// - calls Withdrawer.initiateWithdrawal
function test_withdraw_withdrawingERC20_succeeds() external {
_preBridgeERC20({ _isLegacy: true, _l2Token: address(L2Token) });
L2Bridge.withdraw(address(L2Token), 100, 1000, hex"");
l2StandardBridge.withdraw(address(L2Token), 100, 1000, hex"");
assertEq(L2Token.balanceOf(alice), 0);
}
......@@ -231,21 +258,21 @@ contract L2StandardBridge_BridgeERC20_Test is PreBridgeERC20 {
// - calls Withdrawer.initiateWithdrawal
function test_bridgeERC20_succeeds() external {
_preBridgeERC20({ _isLegacy: false, _l2Token: address(L2Token) });
L2Bridge.bridgeERC20(address(L2Token), address(L1Token), 100, 1000, hex"");
l2StandardBridge.bridgeERC20(address(L2Token), address(L1Token), 100, 1000, hex"");
assertEq(L2Token.balanceOf(alice), 0);
}
function test_withdrawLegacyERC20_succeeds() external {
_preBridgeERC20({ _isLegacy: true, _l2Token: address(LegacyL2Token) });
L2Bridge.withdraw(address(LegacyL2Token), 100, 1000, hex"");
l2StandardBridge.withdraw(address(LegacyL2Token), 100, 1000, hex"");
assertEq(L2Token.balanceOf(alice), 0);
}
function test_bridgeLegacyERC20_succeeds() external {
_preBridgeERC20({ _isLegacy: false, _l2Token: address(LegacyL2Token) });
L2Bridge.bridgeERC20(address(LegacyL2Token), address(L1Token), 100, 1000, hex"");
l2StandardBridge.bridgeERC20(address(LegacyL2Token), address(L1Token), 100, 1000, hex"");
assertEq(L2Token.balanceOf(alice), 0);
}
......@@ -255,7 +282,7 @@ contract L2StandardBridge_BridgeERC20_Test is PreBridgeERC20 {
deal(address(L2Token), address(this), 100, true);
vm.expectRevert("StandardBridge: function can only be called from an EOA");
L2Bridge.withdraw(address(L2Token), 100, 1000, hex"");
l2StandardBridge.withdraw(address(L2Token), 100, 1000, hex"");
}
}
......@@ -265,70 +292,86 @@ contract PreBridgeERC20To is Bridge_Initializer {
function _preBridgeERC20To(bool _isLegacy, address _l2Token) internal {
deal(_l2Token, alice, 100, true);
assertEq(ERC20(L2Token).balanceOf(alice), 100);
uint256 nonce = L2Messenger.messageNonce();
uint256 nonce = l2CrossDomainMessenger.messageNonce();
bytes memory message = abi.encodeWithSelector(
StandardBridge.finalizeBridgeERC20.selector, address(L1Token), _l2Token, alice, bob, 100, hex""
);
uint64 baseGas = L2Messenger.baseGas(message, 1000);
uint64 baseGas = l2CrossDomainMessenger.baseGas(message, 1000);
bytes memory withdrawalData = abi.encodeWithSelector(
CrossDomainMessenger.relayMessage.selector, nonce, address(L2Bridge), address(L1Bridge), 0, 1000, message
CrossDomainMessenger.relayMessage.selector,
nonce,
address(l2StandardBridge),
address(l1StandardBridge),
0,
1000,
message
);
bytes32 withdrawalHash = Hashing.hashWithdrawal(
Types.WithdrawalTransaction({
nonce: nonce,
sender: address(L2Messenger),
target: address(L1Messenger),
sender: address(l2CrossDomainMessenger),
target: address(l1CrossDomainMessenger),
value: 0,
gasLimit: baseGas,
data: withdrawalData
})
);
vm.expectEmit(true, true, true, true, address(L2Bridge));
vm.expectEmit(true, true, true, true, address(l2StandardBridge));
emit WithdrawalInitiated(address(L1Token), _l2Token, alice, bob, 100, hex"");
vm.expectEmit(true, true, true, true, address(L2Bridge));
vm.expectEmit(true, true, true, true, address(l2StandardBridge));
emit ERC20BridgeInitiated(_l2Token, address(L1Token), alice, bob, 100, hex"");
vm.expectEmit(true, true, true, true, address(messagePasser));
vm.expectEmit(true, true, true, true, address(l2ToL1MessagePasser));
emit MessagePassed(
nonce, address(L2Messenger), address(L1Messenger), 0, baseGas, withdrawalData, withdrawalHash
nonce,
address(l2CrossDomainMessenger),
address(l1CrossDomainMessenger),
0,
baseGas,
withdrawalData,
withdrawalHash
);
// SentMessage event emitted by the CrossDomainMessenger
vm.expectEmit(true, true, true, true, address(L2Messenger));
emit SentMessage(address(L1Bridge), address(L2Bridge), message, nonce, 1000);
vm.expectEmit(true, true, true, true, address(l2CrossDomainMessenger));
emit SentMessage(address(l1StandardBridge), address(l2StandardBridge), message, nonce, 1000);
// SentMessageExtension1 event emitted by the CrossDomainMessenger
vm.expectEmit(true, true, true, true, address(L2Messenger));
emit SentMessageExtension1(address(L2Bridge), 0);
vm.expectEmit(true, true, true, true, address(l2CrossDomainMessenger));
emit SentMessageExtension1(address(l2StandardBridge), 0);
if (_isLegacy) {
vm.expectCall(
address(L2Bridge), abi.encodeWithSelector(L2Bridge.withdrawTo.selector, _l2Token, bob, 100, 1000, hex"")
address(l2StandardBridge),
abi.encodeWithSelector(l2StandardBridge.withdrawTo.selector, _l2Token, bob, 100, 1000, hex"")
);
} else {
vm.expectCall(
address(L2Bridge),
address(l2StandardBridge),
abi.encodeWithSelector(
L2Bridge.bridgeERC20To.selector, _l2Token, address(L1Token), bob, 100, 1000, hex""
l2StandardBridge.bridgeERC20To.selector, _l2Token, address(L1Token), bob, 100, 1000, hex""
)
);
}
vm.expectCall(
address(L2Messenger),
abi.encodeWithSelector(CrossDomainMessenger.sendMessage.selector, address(L1Bridge), message, 1000)
address(l2CrossDomainMessenger),
abi.encodeWithSelector(CrossDomainMessenger.sendMessage.selector, address(l1StandardBridge), message, 1000)
);
vm.expectCall(
Predeploys.L2_TO_L1_MESSAGE_PASSER,
abi.encodeWithSelector(
L2ToL1MessagePasser.initiateWithdrawal.selector, address(L1Messenger), baseGas, withdrawalData
L2ToL1MessagePasser.initiateWithdrawal.selector,
address(l1CrossDomainMessenger),
baseGas,
withdrawalData
)
);
// The L2Bridge should burn the tokens
// The l2StandardBridge should burn the tokens
vm.expectCall(address(L2Token), abi.encodeWithSelector(OptimismMintableERC20.burn.selector, alice, 100));
vm.prank(alice, alice);
......@@ -340,7 +383,7 @@ contract L2StandardBridge_BridgeERC20To_Test is PreBridgeERC20To {
/// and initiates a withdrawal with `Withdrawer.initiateWithdrawal`.
function test_withdrawTo_withdrawingERC20_succeeds() external {
_preBridgeERC20To({ _isLegacy: true, _l2Token: address(L2Token) });
L2Bridge.withdrawTo(address(L2Token), bob, 100, 1000, hex"");
l2StandardBridge.withdrawTo(address(L2Token), bob, 100, 1000, hex"");
assertEq(L2Token.balanceOf(alice), 0);
}
......@@ -349,7 +392,7 @@ contract L2StandardBridge_BridgeERC20To_Test is PreBridgeERC20To {
/// and initiates a withdrawal with `Withdrawer.initiateWithdrawal`.
function test_bridgeERC20To_succeeds() external {
_preBridgeERC20To({ _isLegacy: false, _l2Token: address(L2Token) });
L2Bridge.bridgeERC20To(address(L2Token), address(L1Token), bob, 100, 1000, hex"");
l2StandardBridge.bridgeERC20To(address(L2Token), address(L1Token), bob, 100, 1000, hex"");
assertEq(L2Token.balanceOf(alice), 0);
}
}
......@@ -361,37 +404,37 @@ contract L2StandardBridge_Bridge_Test is Bridge_Initializer {
/// - call `Withdrawer.initiateWithdrawal` if the token pair is not supported
function test_finalizeDeposit_depositingERC20_succeeds() external {
vm.mockCall(
address(L2Bridge.messenger()),
address(l2StandardBridge.messenger()),
abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),
abi.encode(address(L2Bridge.OTHER_BRIDGE()))
abi.encode(address(l2StandardBridge.OTHER_BRIDGE()))
);
vm.expectCall(address(L2Token), abi.encodeWithSelector(OptimismMintableERC20.mint.selector, alice, 100));
// Should emit both the bedrock and legacy events
vm.expectEmit(true, true, true, true, address(L2Bridge));
vm.expectEmit(true, true, true, true, address(l2StandardBridge));
emit DepositFinalized(address(L1Token), address(L2Token), alice, alice, 100, hex"");
vm.expectEmit(true, true, true, true, address(L2Bridge));
vm.expectEmit(true, true, true, true, address(l2StandardBridge));
emit ERC20BridgeFinalized(address(L2Token), address(L1Token), alice, alice, 100, hex"");
vm.prank(address(L2Messenger));
L2Bridge.finalizeDeposit(address(L1Token), address(L2Token), alice, alice, 100, hex"");
vm.prank(address(l2CrossDomainMessenger));
l2StandardBridge.finalizeDeposit(address(L1Token), address(L2Token), alice, alice, 100, hex"");
}
/// @dev Tests that `finalizeDeposit` succeeds when depositing ETH.
function test_finalizeDeposit_depositingETH_succeeds() external {
vm.mockCall(
address(L2Bridge.messenger()),
address(l2StandardBridge.messenger()),
abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),
abi.encode(address(L2Bridge.OTHER_BRIDGE()))
abi.encode(address(l2StandardBridge.OTHER_BRIDGE()))
);
// Should emit both the bedrock and legacy events
vm.expectEmit(true, true, true, true, address(L2Bridge));
vm.expectEmit(true, true, true, true, address(l2StandardBridge));
emit DepositFinalized(address(L1Token), address(L2Token), alice, alice, 100, hex"");
vm.expectEmit(true, true, true, true, address(L2Bridge));
vm.expectEmit(true, true, true, true, address(l2StandardBridge));
emit ERC20BridgeFinalized(
address(L2Token), // localToken
address(L1Token), // remoteToken
......@@ -401,58 +444,58 @@ contract L2StandardBridge_Bridge_Test is Bridge_Initializer {
hex""
);
vm.prank(address(L2Messenger));
L2Bridge.finalizeDeposit(address(L1Token), address(L2Token), alice, alice, 100, hex"");
vm.prank(address(l2CrossDomainMessenger));
l2StandardBridge.finalizeDeposit(address(L1Token), address(L2Token), alice, alice, 100, hex"");
}
/// @dev Tests that `finalizeDeposit` reverts if the amounts do not match.
function test_finalizeBridgeETH_incorrectValue_reverts() external {
vm.mockCall(
address(L2Bridge.messenger()),
address(l2StandardBridge.messenger()),
abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),
abi.encode(address(L2Bridge.OTHER_BRIDGE()))
abi.encode(address(l2StandardBridge.OTHER_BRIDGE()))
);
vm.deal(address(L2Messenger), 100);
vm.prank(address(L2Messenger));
vm.deal(address(l2CrossDomainMessenger), 100);
vm.prank(address(l2CrossDomainMessenger));
vm.expectRevert("StandardBridge: amount sent does not match amount required");
L2Bridge.finalizeBridgeETH{ value: 50 }(alice, alice, 100, hex"");
l2StandardBridge.finalizeBridgeETH{ value: 50 }(alice, alice, 100, hex"");
}
/// @dev Tests that `finalizeDeposit` reverts if the receipient is the other bridge.
function test_finalizeBridgeETH_sendToSelf_reverts() external {
vm.mockCall(
address(L2Bridge.messenger()),
address(l2StandardBridge.messenger()),
abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),
abi.encode(address(L2Bridge.OTHER_BRIDGE()))
abi.encode(address(l2StandardBridge.OTHER_BRIDGE()))
);
vm.deal(address(L2Messenger), 100);
vm.prank(address(L2Messenger));
vm.deal(address(l2CrossDomainMessenger), 100);
vm.prank(address(l2CrossDomainMessenger));
vm.expectRevert("StandardBridge: cannot send to self");
L2Bridge.finalizeBridgeETH{ value: 100 }(alice, address(L2Bridge), 100, hex"");
l2StandardBridge.finalizeBridgeETH{ value: 100 }(alice, address(l2StandardBridge), 100, hex"");
}
/// @dev Tests that `finalizeDeposit` reverts if the receipient is the messenger.
function test_finalizeBridgeETH_sendToMessenger_reverts() external {
vm.mockCall(
address(L2Bridge.messenger()),
address(l2StandardBridge.messenger()),
abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),
abi.encode(address(L2Bridge.OTHER_BRIDGE()))
abi.encode(address(l2StandardBridge.OTHER_BRIDGE()))
);
vm.deal(address(L2Messenger), 100);
vm.prank(address(L2Messenger));
vm.deal(address(l2CrossDomainMessenger), 100);
vm.prank(address(l2CrossDomainMessenger));
vm.expectRevert("StandardBridge: cannot send to messenger");
L2Bridge.finalizeBridgeETH{ value: 100 }(alice, address(L2Messenger), 100, hex"");
l2StandardBridge.finalizeBridgeETH{ value: 100 }(alice, address(l2CrossDomainMessenger), 100, hex"");
}
}
contract L2StandardBridge_FinalizeBridgeETH_Test is Bridge_Initializer {
/// @dev Tests that `finalizeBridgeETH` succeeds.
function test_finalizeBridgeETH_succeeds() external {
address messenger = address(L2Bridge.messenger());
address messenger = address(l2StandardBridge.messenger());
vm.mockCall(
messenger,
abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),
abi.encode(address(L2Bridge.OTHER_BRIDGE()))
abi.encode(address(l2StandardBridge.OTHER_BRIDGE()))
);
vm.deal(messenger, 100);
vm.prank(messenger);
......@@ -463,6 +506,6 @@ contract L2StandardBridge_FinalizeBridgeETH_Test is Bridge_Initializer {
vm.expectEmit(true, true, true, true);
emit ETHBridgeFinalized(alice, alice, 100, hex"");
L2Bridge.finalizeBridgeETH{ value: 100 }(alice, alice, 100, hex"");
l2StandardBridge.finalizeBridgeETH{ value: 100 }(alice, alice, 100, hex"");
}
}
......@@ -8,12 +8,7 @@ import { CommonTest } from "test/CommonTest.t.sol";
import { Types } from "src/libraries/Types.sol";
import { Hashing } from "src/libraries/Hashing.sol";
// Target contract
import { L2ToL1MessagePasser } from "src/L2/L2ToL1MessagePasser.sol";
contract L2ToL1MessagePasserTest is CommonTest {
L2ToL1MessagePasser messagePasser;
event MessagePassed(
uint256 indexed nonce,
address indexed sender,
......@@ -26,12 +21,6 @@ contract L2ToL1MessagePasserTest is CommonTest {
event WithdrawerBalanceBurnt(uint256 indexed amount);
/// @dev Sets up the test suite.
function setUp() public virtual override {
super.setUp();
messagePasser = new L2ToL1MessagePasser();
}
/// @dev Tests that `initiateWithdrawal` succeeds and correctly sets the state
/// of the message passer for the withdrawal hash.
function testFuzz_initiateWithdrawal_succeeds(
......@@ -43,7 +32,7 @@ contract L2ToL1MessagePasserTest is CommonTest {
)
external
{
uint256 nonce = messagePasser.messageNonce();
uint256 nonce = l2ToL1MessagePasser.messageNonce();
bytes32 withdrawalHash = Hashing.hashWithdrawal(
Types.WithdrawalTransaction({
......@@ -56,18 +45,18 @@ contract L2ToL1MessagePasserTest is CommonTest {
})
);
vm.expectEmit(true, true, true, true);
vm.expectEmit(address(l2ToL1MessagePasser));
emit MessagePassed(nonce, _sender, _target, _value, _gasLimit, _data, withdrawalHash);
vm.deal(_sender, _value);
vm.prank(_sender);
messagePasser.initiateWithdrawal{ value: _value }(_target, _gasLimit, _data);
l2ToL1MessagePasser.initiateWithdrawal{ value: _value }(_target, _gasLimit, _data);
assertEq(messagePasser.sentMessages(withdrawalHash), true);
assertEq(l2ToL1MessagePasser.sentMessages(withdrawalHash), true);
bytes32 slot = keccak256(bytes.concat(withdrawalHash, bytes32(0)));
assertEq(vm.load(address(messagePasser), slot), bytes32(uint256(1)));
assertEq(vm.load(address(l2ToL1MessagePasser), slot), bytes32(uint256(1)));
}
/// @dev Tests that `initiateWithdrawal` succeeds and emits the correct MessagePassed
......@@ -82,7 +71,7 @@ contract L2ToL1MessagePasserTest is CommonTest {
{
bytes32 withdrawalHash = Hashing.hashWithdrawal(
Types.WithdrawalTransaction({
nonce: messagePasser.messageNonce(),
nonce: l2ToL1MessagePasser.messageNonce(),
sender: address(this),
target: _target,
value: _value,
......@@ -91,13 +80,13 @@ contract L2ToL1MessagePasserTest is CommonTest {
})
);
vm.expectEmit(address(messagePasser));
vm.expectEmit(address(l2ToL1MessagePasser));
emit MessagePassed(
messagePasser.messageNonce(), address(this), _target, _value, _gasLimit, _data, withdrawalHash
l2ToL1MessagePasser.messageNonce(), address(this), _target, _value, _gasLimit, _data, withdrawalHash
);
vm.deal(address(this), _value);
messagePasser.initiateWithdrawal{ value: _value }(_target, _gasLimit, _data);
l2ToL1MessagePasser.initiateWithdrawal{ value: _value }(_target, _gasLimit, _data);
}
/// @dev Tests that `initiateWithdrawal` succeeds and emits the correct MessagePassed
......@@ -110,7 +99,7 @@ contract L2ToL1MessagePasserTest is CommonTest {
)
external
{
uint256 nonce = messagePasser.messageNonce();
uint256 nonce = l2ToL1MessagePasser.messageNonce();
// EOA emulation
vm.prank(alice, alice);
......@@ -118,29 +107,28 @@ contract L2ToL1MessagePasserTest is CommonTest {
bytes32 withdrawalHash =
Hashing.hashWithdrawal(Types.WithdrawalTransaction(nonce, alice, _target, _value, _gasLimit, _data));
vm.expectEmit(address(messagePasser));
vm.expectEmit(address(l2ToL1MessagePasser));
emit MessagePassed(nonce, alice, _target, _value, _gasLimit, _data, withdrawalHash);
messagePasser.initiateWithdrawal{ value: _value }({ _target: _target, _gasLimit: _gasLimit, _data: _data });
l2ToL1MessagePasser.initiateWithdrawal{ value: _value }({ _target: _target, _gasLimit: _gasLimit, _data: _data });
// the sent messages mapping is filled
assertEq(messagePasser.sentMessages(withdrawalHash), true);
assertEq(l2ToL1MessagePasser.sentMessages(withdrawalHash), true);
// the nonce increments
assertEq(nonce + 1, messagePasser.messageNonce());
assertEq(nonce + 1, l2ToL1MessagePasser.messageNonce());
}
/// @dev Tests that `burn` succeeds and destroys the ETH held in the contract.
function testFuzz_burn_succeeds(uint256 _value, address _target, uint256 _gasLimit, bytes memory _data) external {
vm.deal(address(this), _value);
messagePasser.initiateWithdrawal{ value: _value }({ _target: _target, _gasLimit: _gasLimit, _data: _data });
l2ToL1MessagePasser.initiateWithdrawal{ value: _value }({ _target: _target, _gasLimit: _gasLimit, _data: _data });
assertEq(address(messagePasser).balance, _value);
vm.expectEmit(true, false, false, false);
assertEq(address(l2ToL1MessagePasser).balance, _value);
emit WithdrawerBalanceBurnt(_value);
messagePasser.burn();
l2ToL1MessagePasser.burn();
// The Withdrawer should have no balance
assertEq(address(messagePasser).balance, 0);
assertEq(address(l2ToL1MessagePasser).balance, 0);
}
}
......@@ -4,25 +4,11 @@ pragma solidity 0.8.15;
// Testing utilities
import { CommonTest } from "test/CommonTest.t.sol";
// Testing contract dependencies
import { Predeploys } from "src/libraries/Predeploys.sol";
// Target contract
import { LegacyMessagePasser } from "src/legacy/LegacyMessagePasser.sol";
contract LegacyMessagePasser_Test is CommonTest {
LegacyMessagePasser messagePasser;
/// @dev Sets up the test suite.
function setUp() public virtual override {
super.setUp();
messagePasser = new LegacyMessagePasser();
}
/// @dev Tests that `passMessageToL1` succeeds.
function test_passMessageToL1_succeeds() external {
vm.prank(alice);
messagePasser.passMessageToL1(hex"ff");
assert(messagePasser.sentMessages(keccak256(abi.encodePacked(hex"ff", alice))));
legacyMessagePasser.passMessageToL1(hex"ff");
assert(legacyMessagePasser.sentMessages(keccak256(abi.encodePacked(hex"ff", alice))));
}
}
......@@ -14,7 +14,7 @@ contract OptimismMintableERC20_Test is Bridge_Initializer {
}
function test_bridge_succeeds() external {
assertEq(L2Token.bridge(), address(L2Bridge));
assertEq(L2Token.bridge(), address(l2StandardBridge));
}
function test_l1Token_succeeds() external {
......@@ -22,7 +22,7 @@ contract OptimismMintableERC20_Test is Bridge_Initializer {
}
function test_l2Bridge_succeeds() external {
assertEq(L2Token.l2Bridge(), address(L2Bridge));
assertEq(L2Token.l2Bridge(), address(l2StandardBridge));
}
function test_legacy_succeeds() external {
......@@ -31,16 +31,16 @@ contract OptimismMintableERC20_Test is Bridge_Initializer {
assertEq(L2Token.remoteToken(), address(L1Token));
assertEq(L2Token.l1Token(), address(L1Token));
// Getters for the bridge
assertEq(L2Token.BRIDGE(), address(L2Bridge));
assertEq(L2Token.bridge(), address(L2Bridge));
assertEq(L2Token.l2Bridge(), address(L2Bridge));
assertEq(L2Token.BRIDGE(), address(l2StandardBridge));
assertEq(L2Token.bridge(), address(l2StandardBridge));
assertEq(L2Token.l2Bridge(), address(l2StandardBridge));
}
function test_mint_succeeds() external {
vm.expectEmit(true, true, true, true);
emit Mint(alice, 100);
vm.prank(address(L2Bridge));
vm.prank(address(l2StandardBridge));
L2Token.mint(alice, 100);
assertEq(L2Token.balanceOf(alice), 100);
......@@ -54,13 +54,13 @@ contract OptimismMintableERC20_Test is Bridge_Initializer {
}
function test_burn_succeeds() external {
vm.prank(address(L2Bridge));
vm.prank(address(l2StandardBridge));
L2Token.mint(alice, 100);
vm.expectEmit(true, true, true, true);
emit Burn(alice, 100);
vm.prank(address(L2Bridge));
vm.prank(address(l2StandardBridge));
L2Token.burn(alice, 100);
assertEq(L2Token.balanceOf(alice), 0);
......
......@@ -8,12 +8,8 @@ contract OptimismMintableTokenFactory_Test is Bridge_Initializer {
event StandardL2TokenCreated(address indexed remoteToken, address indexed localToken);
event OptimismMintableERC20Created(address indexed localToken, address indexed remoteToken, address deployer);
function setUp() public override {
super.setUp();
}
function test_bridge_succeeds() external {
assertEq(address(L2TokenFactory.BRIDGE()), address(L2Bridge));
assertEq(address(l2OptimismMintableERC20Factory.BRIDGE()), address(l2StandardBridge));
}
function test_createStandardL2Token_succeeds() external {
......@@ -29,7 +25,7 @@ contract OptimismMintableTokenFactory_Test is Bridge_Initializer {
emit OptimismMintableERC20Created(local, remote, alice);
vm.prank(alice);
address addr = L2TokenFactory.createStandardL2Token(remote, "Beep", "BOOP");
address addr = l2OptimismMintableERC20Factory.createStandardL2Token(remote, "Beep", "BOOP");
assertTrue(addr == local);
assertTrue(OptimismMintableERC20(local).decimals() == 18);
}
......@@ -45,7 +41,7 @@ contract OptimismMintableTokenFactory_Test is Bridge_Initializer {
emit OptimismMintableERC20Created(local, remote, alice);
vm.prank(alice);
address addr = L2TokenFactory.createOptimismMintableERC20WithDecimals(remote, "Beep", "BOOP", 6);
address addr = l2OptimismMintableERC20Factory.createOptimismMintableERC20WithDecimals(remote, "Beep", "BOOP", 6);
assertTrue(addr == local);
assertTrue(OptimismMintableERC20(local).decimals() == 6);
......@@ -55,18 +51,18 @@ contract OptimismMintableTokenFactory_Test is Bridge_Initializer {
address remote = address(4);
vm.prank(alice);
L2TokenFactory.createStandardL2Token(remote, "Beep", "BOOP");
l2OptimismMintableERC20Factory.createStandardL2Token(remote, "Beep", "BOOP");
vm.expectRevert();
vm.prank(alice);
L2TokenFactory.createStandardL2Token(remote, "Beep", "BOOP");
l2OptimismMintableERC20Factory.createStandardL2Token(remote, "Beep", "BOOP");
}
function test_createStandardL2Token_remoteIsZero_reverts() external {
address remote = address(0);
vm.expectRevert("OptimismMintableERC20Factory: must provide remote token address");
L2TokenFactory.createStandardL2Token(remote, "Beep", "BOOP");
l2OptimismMintableERC20Factory.createStandardL2Token(remote, "Beep", "BOOP");
}
function calculateTokenAddress(
......@@ -79,10 +75,12 @@ contract OptimismMintableTokenFactory_Test is Bridge_Initializer {
view
returns (address)
{
bytes memory constructorArgs = abi.encode(address(L2Bridge), _remote, _name, _symbol, _decimals);
bytes memory constructorArgs = abi.encode(address(l2StandardBridge), _remote, _name, _symbol, _decimals);
bytes memory bytecode = abi.encodePacked(type(OptimismMintableERC20).creationCode, constructorArgs);
bytes32 salt = keccak256(abi.encode(_remote, _name, _symbol, _decimals));
bytes32 hash = keccak256(abi.encodePacked(bytes1(0xff), address(L2TokenFactory), salt, keccak256(bytecode)));
bytes32 hash = keccak256(
abi.encodePacked(bytes1(0xff), address(l2OptimismMintableERC20Factory), salt, keccak256(bytecode))
);
return address(uint160(uint256(hash)));
}
}
......@@ -5,10 +5,10 @@ import { ERC721, IERC721 } from "@openzeppelin/contracts/token/ERC721/ERC721.sol
import { IERC721Enumerable } from "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
import { Strings } from "@openzeppelin/contracts/utils/Strings.sol";
import { ERC721Bridge_Initializer } from "test/CommonTest.t.sol";
import { Bridge_Initializer } from "test/CommonTest.t.sol";
import { OptimismMintableERC721, IOptimismMintableERC721 } from "src/universal/OptimismMintableERC721.sol";
contract OptimismMintableERC721_Test is ERC721Bridge_Initializer {
contract OptimismMintableERC721_Test is Bridge_Initializer {
ERC721 internal L1NFT;
OptimismMintableERC721 internal L2NFT;
......@@ -24,7 +24,7 @@ contract OptimismMintableERC721_Test is ERC721Bridge_Initializer {
// Set up the token pair.
L1NFT = new ERC721("L1NFT", "L1T");
L2NFT = new OptimismMintableERC721(
address(L2NFTBridge),
address(l2ERC721Bridge),
1,
address(L1NFT),
"L2NFT",
......@@ -40,10 +40,10 @@ contract OptimismMintableERC721_Test is ERC721Bridge_Initializer {
assertEq(L2NFT.name(), "L2NFT");
assertEq(L2NFT.symbol(), "L2T");
assertEq(L2NFT.remoteToken(), address(L1NFT));
assertEq(L2NFT.bridge(), address(L2NFTBridge));
assertEq(L2NFT.bridge(), address(l2ERC721Bridge));
assertEq(L2NFT.remoteChainId(), 1);
assertEq(L2NFT.REMOTE_TOKEN(), address(L1NFT));
assertEq(L2NFT.BRIDGE(), address(L2NFTBridge));
assertEq(L2NFT.BRIDGE(), address(l2ERC721Bridge));
assertEq(L2NFT.REMOTE_CHAIN_ID(), 1);
}
......@@ -69,7 +69,7 @@ contract OptimismMintableERC721_Test is ERC721Bridge_Initializer {
emit Mint(alice, 1);
// Mint the token.
vm.prank(address(L2NFTBridge));
vm.prank(address(l2ERC721Bridge));
L2NFT.safeMint(alice, 1);
// Token should be owned by alice.
......@@ -85,7 +85,7 @@ contract OptimismMintableERC721_Test is ERC721Bridge_Initializer {
function test_burn_succeeds() external {
// Mint the token first.
vm.prank(address(L2NFTBridge));
vm.prank(address(l2ERC721Bridge));
L2NFT.safeMint(alice, 1);
// Expect a transfer event.
......@@ -97,7 +97,7 @@ contract OptimismMintableERC721_Test is ERC721Bridge_Initializer {
emit Burn(alice, 1);
// Burn the token.
vm.prank(address(L2NFTBridge));
vm.prank(address(l2ERC721Bridge));
L2NFT.burn(alice, 1);
// Token should be owned by address(0).
......@@ -107,7 +107,7 @@ contract OptimismMintableERC721_Test is ERC721Bridge_Initializer {
function test_burn_notBridge_reverts() external {
// Mint the token first.
vm.prank(address(L2NFTBridge));
vm.prank(address(l2ERC721Bridge));
L2NFT.safeMint(alice, 1);
// Try to burn the token.
......@@ -118,7 +118,7 @@ contract OptimismMintableERC721_Test is ERC721Bridge_Initializer {
function test_tokenURI_succeeds() external {
// Mint the token first.
vm.prank(address(L2NFTBridge));
vm.prank(address(l2ERC721Bridge));
L2NFT.safeMint(alice, 1);
// Token URI should be correct.
......
......@@ -2,11 +2,11 @@
pragma solidity 0.8.15;
import { ERC721 } from "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import { ERC721Bridge_Initializer } from "test/CommonTest.t.sol";
import { Bridge_Initializer } from "test/CommonTest.t.sol";
import { OptimismMintableERC721 } from "src/universal/OptimismMintableERC721.sol";
import { OptimismMintableERC721Factory } from "src/universal/OptimismMintableERC721Factory.sol";
contract OptimismMintableERC721Factory_Test is ERC721Bridge_Initializer {
contract OptimismMintableERC721Factory_Test is Bridge_Initializer {
OptimismMintableERC721Factory internal factory;
event OptimismMintableERC721Created(address indexed localToken, address indexed remoteToken, address deployer);
......@@ -15,14 +15,14 @@ contract OptimismMintableERC721Factory_Test is ERC721Bridge_Initializer {
super.setUp();
// Set up the token pair.
factory = new OptimismMintableERC721Factory(address(L2NFTBridge), 1);
factory = new OptimismMintableERC721Factory(address(l2ERC721Bridge), 1);
// Label the addresses for nice traces.
vm.label(address(factory), "OptimismMintableERC721Factory");
}
function test_constructor_succeeds() external {
assertEq(factory.BRIDGE(), address(L2NFTBridge));
assertEq(factory.BRIDGE(), address(l2ERC721Bridge));
assertEq(factory.REMOTE_CHAIN_ID(), 1);
}
......@@ -49,7 +49,7 @@ contract OptimismMintableERC721Factory_Test is ERC721Bridge_Initializer {
assertEq(created.name(), "L2Token");
assertEq(created.symbol(), "L2T");
assertEq(created.REMOTE_TOKEN(), remote);
assertEq(created.BRIDGE(), address(L2NFTBridge));
assertEq(created.BRIDGE(), address(l2ERC721Bridge));
assertEq(created.REMOTE_CHAIN_ID(), 1);
}
......@@ -80,7 +80,7 @@ contract OptimismMintableERC721Factory_Test is ERC721Bridge_Initializer {
view
returns (address)
{
bytes memory constructorArgs = abi.encode(address(L2NFTBridge), 1, _remote, _name, _symbol);
bytes memory constructorArgs = abi.encode(address(l2ERC721Bridge), 1, _remote, _name, _symbol);
bytes memory bytecode = abi.encodePacked(type(OptimismMintableERC721).creationCode, constructorArgs);
bytes32 salt = keccak256(abi.encode(_remote, _name, _symbol));
bytes32 hash = keccak256(abi.encodePacked(bytes1(0xff), address(factory), salt, keccak256(bytecode)));
......
......@@ -5,6 +5,7 @@ pragma solidity 0.8.15;
import { stdError } from "forge-std/Test.sol";
import { Portal_Initializer } from "test/CommonTest.t.sol";
import { NextImpl } from "test/mocks/NextImpl.sol";
import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol";
// Libraries
import { Types } from "src/libraries/Types.sol";
......@@ -17,8 +18,6 @@ import { ResourceMetering } from "src/L1/ResourceMetering.sol";
import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol";
import { L2OutputOracle } from "src/L1/L2OutputOracle.sol";
import { SystemConfig } from "src/L1/SystemConfig.sol";
// Target contract
import { OptimismPortal } from "src/L1/OptimismPortal.sol";
contract OptimismPortal_Test is Portal_Initializer {
......@@ -34,87 +33,96 @@ contract OptimismPortal_Test is Portal_Initializer {
/// @dev Tests that the constructor sets the correct values.
function test_constructor_succeeds() external {
assertEq(address(op.L2_ORACLE()), address(oracle));
assertEq(address(op.l2Oracle()), address(oracle));
assertEq(op.GUARDIAN(), guardian);
assertEq(op.guardian(), guardian);
assertEq(op.l2Sender(), 0x000000000000000000000000000000000000dEaD);
assertEq(op.paused(), false);
address guardian = cfg.portalGuardian();
assertEq(address(optimismPortal.L2_ORACLE()), address(l2OutputOracle));
assertEq(address(optimismPortal.l2Oracle()), address(l2OutputOracle));
assertEq(optimismPortal.GUARDIAN(), guardian);
assertEq(optimismPortal.guardian(), guardian);
assertEq(optimismPortal.l2Sender(), 0x000000000000000000000000000000000000dEaD);
assertEq(optimismPortal.paused(), false);
}
/// @dev Tests that `pause` successfully pauses
/// when called by the GUARDIAN.
function test_pause_succeeds() external {
address guardian = op.GUARDIAN();
address guardian = optimismPortal.GUARDIAN();
assertEq(op.paused(), false);
assertEq(optimismPortal.paused(), false);
vm.expectEmit(true, true, true, true, address(op));
vm.expectEmit(address(optimismPortal));
emit Paused(guardian);
vm.prank(guardian);
op.pause();
optimismPortal.pause();
assertEq(op.paused(), true);
assertEq(optimismPortal.paused(), true);
}
/// @dev Tests that `pause` reverts when called by a non-GUARDIAN.
function test_pause_onlyGuardian_reverts() external {
assertEq(op.paused(), false);
assertEq(optimismPortal.paused(), false);
assertTrue(op.GUARDIAN() != alice);
assertTrue(optimismPortal.GUARDIAN() != alice);
vm.expectRevert("OptimismPortal: only guardian can pause");
vm.prank(alice);
op.pause();
optimismPortal.pause();
assertEq(op.paused(), false);
assertEq(optimismPortal.paused(), false);
}
/// @dev Tests that `unpause` successfully unpauses
/// when called by the GUARDIAN.
function test_unpause_succeeds() external {
address guardian = op.GUARDIAN();
address guardian = optimismPortal.GUARDIAN();
vm.prank(guardian);
op.pause();
assertEq(op.paused(), true);
optimismPortal.pause();
assertEq(optimismPortal.paused(), true);
vm.expectEmit(true, true, true, true, address(op));
vm.expectEmit(address(optimismPortal));
emit Unpaused(guardian);
vm.prank(guardian);
op.unpause();
optimismPortal.unpause();
assertEq(op.paused(), false);
assertEq(optimismPortal.paused(), false);
}
/// @dev Tests that `unpause` reverts when called by a non-GUARDIAN.
function test_unpause_onlyGuardian_reverts() external {
address guardian = op.GUARDIAN();
address guardian = optimismPortal.GUARDIAN();
vm.prank(guardian);
op.pause();
assertEq(op.paused(), true);
optimismPortal.pause();
assertEq(optimismPortal.paused(), true);
assertTrue(op.GUARDIAN() != alice);
assertTrue(optimismPortal.GUARDIAN() != alice);
vm.expectRevert("OptimismPortal: only guardian can unpause");
vm.prank(alice);
op.unpause();
optimismPortal.unpause();
assertEq(op.paused(), true);
assertEq(optimismPortal.paused(), true);
}
/// @dev Tests that `receive` successdully deposits ETH.
function test_receive_succeeds() external {
vm.expectEmit(true, true, false, true);
emitTransactionDeposited(alice, alice, 100, 100, 100_000, false, hex"");
function testFuzz_receive_succeeds(uint256 _value) external {
vm.expectEmit(address(optimismPortal));
emitTransactionDeposited({
_from: alice,
_to: alice,
_value: _value,
_mint: _value,
_gasLimit: 100_000,
_isCreation: false,
_data: hex""
});
// give alice money and send as an eoa
vm.deal(alice, 2 ** 64);
vm.deal(alice, _value);
vm.prank(alice, alice);
(bool s,) = address(op).call{ value: 100 }(hex"");
(bool s,) = address(optimismPortal).call{ value: _value }(hex"");
assert(s);
assertEq(address(op).balance, 100);
assertTrue(s);
assertEq(address(optimismPortal).balance, _value);
}
/// @dev Tests that `depositTransaction` reverts when the destination address is non-zero
......@@ -122,16 +130,16 @@ contract OptimismPortal_Test is Portal_Initializer {
function test_depositTransaction_contractCreation_reverts() external {
// contract creation must have a target of address(0)
vm.expectRevert("OptimismPortal: must send to address(0) when creating a contract");
op.depositTransaction(address(1), 1, 0, true, hex"");
optimismPortal.depositTransaction(address(1), 1, 0, true, hex"");
}
/// @dev Tests that `depositTransaction` reverts when the data is too large.
/// This places an upper bound on unsafe blocks sent over p2p.
function test_depositTransaction_largeData_reverts() external {
uint256 size = 120_001;
uint64 gasLimit = op.minimumGasLimit(uint64(size));
uint64 gasLimit = optimismPortal.minimumGasLimit(uint64(size));
vm.expectRevert("OptimismPortal: data too large");
op.depositTransaction({
optimismPortal.depositTransaction({
_to: address(0),
_value: 0,
_gasLimit: gasLimit,
......@@ -143,30 +151,34 @@ contract OptimismPortal_Test is Portal_Initializer {
/// @dev Tests that `depositTransaction` reverts when the gas limit is too small.
function test_depositTransaction_smallGasLimit_reverts() external {
vm.expectRevert("OptimismPortal: gas limit too small");
op.depositTransaction({ _to: address(1), _value: 0, _gasLimit: 0, _isCreation: false, _data: hex"" });
optimismPortal.depositTransaction({ _to: address(1), _value: 0, _gasLimit: 0, _isCreation: false, _data: hex"" });
}
/// @dev Tests that `depositTransaction` succeeds for small,
/// but sufficient, gas limits.
function testFuzz_depositTransaction_smallGasLimit_succeeds(bytes memory _data, bool _shouldFail) external {
vm.assume(_data.length <= type(uint64).max);
uint64 gasLimit = op.minimumGasLimit(uint64(_data.length));
uint64 gasLimit = optimismPortal.minimumGasLimit(uint64(_data.length));
if (_shouldFail) {
gasLimit = uint64(bound(gasLimit, 0, gasLimit - 1));
vm.expectRevert("OptimismPortal: gas limit too small");
}
op.depositTransaction({ _to: address(0x40), _value: 0, _gasLimit: gasLimit, _isCreation: false, _data: _data });
optimismPortal.depositTransaction({
_to: address(0x40),
_value: 0,
_gasLimit: gasLimit,
_isCreation: false,
_data: _data
});
}
/// @dev Tests that `minimumGasLimit` succeeds for small calldata sizes.
/// The gas limit should be 21k for 0 calldata and increase linearly
/// for larger calldata sizes.
function test_minimumGasLimit_succeeds() external {
assertEq(op.minimumGasLimit(0), 21_000);
assertTrue(op.minimumGasLimit(2) > op.minimumGasLimit(1));
assertTrue(op.minimumGasLimit(3) > op.minimumGasLimit(2));
assertEq(optimismPortal.minimumGasLimit(0), 21_000);
assertTrue(optimismPortal.minimumGasLimit(2) > optimismPortal.minimumGasLimit(1));
assertTrue(optimismPortal.minimumGasLimit(3) > optimismPortal.minimumGasLimit(2));
}
/// @dev Tests that `depositTransaction` succeeds for an EOA.
......@@ -181,12 +193,12 @@ contract OptimismPortal_Test is Portal_Initializer {
external
{
_gasLimit = uint64(
bound(_gasLimit, op.minimumGasLimit(uint64(_data.length)), systemConfig.resourceConfig().maxResourceLimit)
bound(_gasLimit, optimismPortal.minimumGasLimit(uint64(_data.length)), systemConfig.resourceConfig().maxResourceLimit)
);
if (_isCreation) _to = address(0);
// EOA emulation
vm.expectEmit(address(op));
vm.expectEmit(address(optimismPortal));
emitTransactionDeposited({
_from: depositor,
_to: _to,
......@@ -199,14 +211,14 @@ contract OptimismPortal_Test is Portal_Initializer {
vm.deal(depositor, _mint);
vm.prank(depositor, depositor);
op.depositTransaction{ value: _mint }({
optimismPortal.depositTransaction{ value: _mint }({
_to: _to,
_value: _value,
_gasLimit: _gasLimit,
_isCreation: _isCreation,
_data: _data
});
assertEq(address(op).balance, _mint);
assertEq(address(optimismPortal).balance, _mint);
}
/// @dev Tests that `depositTransaction` succeeds for a contract.
......@@ -220,12 +232,10 @@ contract OptimismPortal_Test is Portal_Initializer {
)
external
{
_gasLimit = uint64(
bound(_gasLimit, op.minimumGasLimit(uint64(_data.length)), systemConfig.resourceConfig().maxResourceLimit)
);
_gasLimit = uint64(bound(_gasLimit, optimismPortal.minimumGasLimit(uint64(_data.length)), systemConfig.resourceConfig().maxResourceLimit));
if (_isCreation) _to = address(0);
vm.expectEmit(address(op));
vm.expectEmit(address(optimismPortal));
emitTransactionDeposited({
_from: AddressAliasHelper.applyL1ToL2Alias(address(this)),
_to: _to,
......@@ -236,43 +246,63 @@ contract OptimismPortal_Test is Portal_Initializer {
_data: _data
});
vm.deal(address(this), _mint);
vm.prank(address(this));
op.depositTransaction{ value: _mint }({
optimismPortal.depositTransaction{ value: _mint }({
_to: _to,
_value: _value,
_gasLimit: _gasLimit,
_isCreation: _isCreation,
_data: _data
});
assertEq(address(op).balance, _mint);
assertEq(address(optimismPortal).balance, _mint);
}
/// @dev Tests that `isOutputFinalized` succeeds for an EOA depositing a tx with ETH and data.
function test_simple_isOutputFinalized_succeeds() external {
uint256 startingBlockNumber = cfg.l2OutputOracleStartingBlockNumber();
uint256 ts = block.timestamp;
vm.mockCall(
address(optimismPortal.L2_ORACLE()),
abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),
abi.encode(Types.OutputProposal(bytes32(uint256(1)), uint128(ts), uint128(startingBlockNumber)))
);
// warp to the finalization period
vm.warp(ts + l2OutputOracle.FINALIZATION_PERIOD_SECONDS());
assertEq(optimismPortal.isOutputFinalized(0), false);
// warp past the finalization period
vm.warp(ts + l2OutputOracle.FINALIZATION_PERIOD_SECONDS() + 1);
assertEq(optimismPortal.isOutputFinalized(0), true);
}
/// @dev Tests `isOutputFinalized` for a finalized output.
function test_isOutputFinalized_succeeds() external {
uint256 checkpoint = oracle.nextBlockNumber();
uint256 nextOutputIndex = oracle.nextOutputIndex();
uint256 checkpoint = l2OutputOracle.nextBlockNumber();
uint256 nextOutputIndex = l2OutputOracle.nextOutputIndex();
vm.roll(checkpoint);
vm.warp(oracle.computeL2Timestamp(checkpoint) + 1);
vm.prank(oracle.PROPOSER());
oracle.proposeL2Output(keccak256(abi.encode(2)), checkpoint, 0, 0);
vm.warp(l2OutputOracle.computeL2Timestamp(checkpoint) + 1);
vm.prank(l2OutputOracle.PROPOSER());
l2OutputOracle.proposeL2Output(keccak256(abi.encode(2)), checkpoint, 0, 0);
// warp to the final second of the finalization period
uint256 finalizationHorizon = block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS();
uint256 finalizationHorizon = block.timestamp + l2OutputOracle.FINALIZATION_PERIOD_SECONDS();
vm.warp(finalizationHorizon);
// The checkpointed block should not be finalized until 1 second from now.
assertEq(op.isOutputFinalized(nextOutputIndex), false);
assertEq(optimismPortal.isOutputFinalized(nextOutputIndex), false);
// Nor should a block after it
vm.expectRevert(stdError.indexOOBError);
assertEq(op.isOutputFinalized(nextOutputIndex + 1), false);
assertEq(optimismPortal.isOutputFinalized(nextOutputIndex + 1), false);
// warp past the finalization period
vm.warp(finalizationHorizon + 1);
// It should now be finalized.
assertEq(op.isOutputFinalized(nextOutputIndex), true);
assertEq(optimismPortal.isOutputFinalized(nextOutputIndex), true);
// But not the block after it.
vm.expectRevert(stdError.indexOOBError);
assertEq(op.isOutputFinalized(nextOutputIndex + 1), false);
assertEq(optimismPortal.isOutputFinalized(nextOutputIndex + 1), false);
}
}
......@@ -311,21 +341,24 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
messagePasserStorageRoot: _storageRoot,
latestBlockhash: bytes32(uint256(0))
});
_proposedBlockNumber = oracle.nextBlockNumber();
_proposedOutputIndex = oracle.nextOutputIndex();
_proposedBlockNumber = l2OutputOracle.nextBlockNumber();
_proposedOutputIndex = l2OutputOracle.nextOutputIndex();
}
/// @dev Setup the system for a ready-to-use state.
function setUp() public override {
// Configure the oracle to return the output root we've prepared.
vm.warp(oracle.computeL2Timestamp(_proposedBlockNumber) + 1);
vm.prank(oracle.PROPOSER());
oracle.proposeL2Output(_outputRoot, _proposedBlockNumber, 0, 0);
vm.warp(l2OutputOracle.computeL2Timestamp(_proposedBlockNumber) + 1);
vm.prank(l2OutputOracle.PROPOSER());
l2OutputOracle.proposeL2Output(_outputRoot, _proposedBlockNumber, 0, 0);
// Warp beyond the finalization period for the block we've proposed.
vm.warp(oracle.getL2Output(_proposedOutputIndex).timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);
vm.warp(
l2OutputOracle.getL2Output(_proposedOutputIndex).timestamp + l2OutputOracle.FINALIZATION_PERIOD_SECONDS()
+ 1
);
// Fund the portal so that we can withdraw ETH.
vm.deal(address(op), 0xFFFFFFFF);
vm.deal(address(optimismPortal), 0xFFFFFFFF);
}
/// @dev Asserts that the reentrant call will revert.
......@@ -333,18 +366,18 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
vm.expectRevert("OptimismPortal: can only trigger one withdrawal per transaction");
// Arguments here don't matter, as the require check is the first thing that happens.
// We assume that this has already been proven.
op.finalizeWithdrawalTransaction(_defaultTx);
optimismPortal.finalizeWithdrawalTransaction(_defaultTx);
// Assert that the withdrawal was not finalized.
assertFalse(op.finalizedWithdrawals(Hashing.hashWithdrawal(_defaultTx)));
assertFalse(optimismPortal.finalizedWithdrawals(Hashing.hashWithdrawal(_defaultTx)));
}
/// @dev Tests that `proveWithdrawalTransaction` reverts when paused.
function test_proveWithdrawalTransaction_paused_reverts() external {
vm.prank(op.GUARDIAN());
op.pause();
vm.prank(optimismPortal.GUARDIAN());
optimismPortal.pause();
vm.expectRevert("OptimismPortal: paused");
op.proveWithdrawalTransaction({
optimismPortal.proveWithdrawalTransaction({
_tx: _defaultTx,
_l2OutputIndex: _proposedOutputIndex,
_outputRootProof: _outputRootProof,
......@@ -354,9 +387,9 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
/// @dev Tests that `proveWithdrawalTransaction` reverts when the target is the portal contract.
function test_proveWithdrawalTransaction_onSelfCall_reverts() external {
_defaultTx.target = address(op);
_defaultTx.target = address(optimismPortal);
vm.expectRevert("OptimismPortal: you cannot send messages to the portal contract");
op.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof);
optimismPortal.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof);
}
/// @dev Tests that `proveWithdrawalTransaction` reverts when
......@@ -365,7 +398,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
// Modify the version to invalidate the withdrawal proof.
_outputRootProof.version = bytes32(uint256(1));
vm.expectRevert("OptimismPortal: invalid output root proof");
op.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof);
optimismPortal.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof);
}
/// @dev Tests that `proveWithdrawalTransaction` reverts when the withdrawal is missing.
......@@ -373,7 +406,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
// modify the default test values to invalidate the proof.
_defaultTx.data = hex"abcd";
vm.expectRevert("MerkleTrie: path remainder must share all nibbles with key");
op.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof);
optimismPortal.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof);
}
/// @dev Tests that `proveWithdrawalTransaction` reverts when the withdrawal has already
......@@ -381,10 +414,10 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
function test_proveWithdrawalTransaction_replayProve_reverts() external {
vm.expectEmit(true, true, true, true);
emit WithdrawalProven(_withdrawalHash, alice, bob);
op.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof);
optimismPortal.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof);
vm.expectRevert("OptimismPortal: withdrawal hash has already been proven");
op.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof);
optimismPortal.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof);
}
/// @dev Tests that `proveWithdrawalTransaction` succeeds when the withdrawal has already
......@@ -392,7 +425,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
function test_proveWithdrawalTransaction_replayProveChangedOutputRoot_succeeds() external {
vm.expectEmit(true, true, true, true);
emit WithdrawalProven(_withdrawalHash, alice, bob);
op.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof);
optimismPortal.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof);
// Compute the storage slot of the outputRoot corresponding to the `withdrawalHash`
// inside of the `provenWithdrawal`s mapping.
......@@ -405,7 +438,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
// Store a different output root within the `provenWithdrawals` mapping without
// touching the l2BlockNumber or timestamp.
vm.store(address(op), slot, bytes32(0));
vm.store(address(optimismPortal), slot, bytes32(0));
// Warp ahead 1 second
vm.warp(block.timestamp + 1);
......@@ -414,10 +447,10 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
// our proof with a changed outputRoot
vm.expectEmit(true, true, true, true);
emit WithdrawalProven(_withdrawalHash, alice, bob);
op.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof);
optimismPortal.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof);
// Ensure that the withdrawal was updated within the mapping
(, uint128 timestamp,) = op.provenWithdrawals(_withdrawalHash);
(, uint128 timestamp,) = optimismPortal.provenWithdrawals(_withdrawalHash);
assertEq(timestamp, block.timestamp);
}
......@@ -426,7 +459,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
function test_proveWithdrawalTransaction_replayProveChangedOutputRootAndOutputIndex_succeeds() external {
vm.expectEmit(true, true, true, true);
emit WithdrawalProven(_withdrawalHash, alice, bob);
op.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof);
optimismPortal.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof);
// Compute the storage slot of the outputRoot corresponding to the `withdrawalHash`
// inside of the `provenWithdrawal`s mapping.
......@@ -439,15 +472,15 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
// Store a dummy output root within the `provenWithdrawals` mapping without touching the
// l2BlockNumber or timestamp.
vm.store(address(op), slot, bytes32(0));
vm.store(address(optimismPortal), slot, bytes32(0));
// Fetch the output proposal at `_proposedOutputIndex` from the L2OutputOracle
Types.OutputProposal memory proposal = op.L2_ORACLE().getL2Output(_proposedOutputIndex);
Types.OutputProposal memory proposal = optimismPortal.L2_ORACLE().getL2Output(_proposedOutputIndex);
// Propose the same output root again, creating the same output at a different index + l2BlockNumber.
vm.startPrank(op.L2_ORACLE().PROPOSER());
op.L2_ORACLE().proposeL2Output(
proposal.outputRoot, op.L2_ORACLE().nextBlockNumber(), blockhash(block.number), block.number
vm.startPrank(optimismPortal.L2_ORACLE().PROPOSER());
optimismPortal.L2_ORACLE().proposeL2Output(
proposal.outputRoot, optimismPortal.L2_ORACLE().nextBlockNumber(), blockhash(block.number), block.number
);
vm.stopPrank();
......@@ -458,10 +491,12 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
// our proof with a changed outputRoot + a different output index
vm.expectEmit(true, true, true, true);
emit WithdrawalProven(_withdrawalHash, alice, bob);
op.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex + 1, _outputRootProof, _withdrawalProof);
optimismPortal.proveWithdrawalTransaction(
_defaultTx, _proposedOutputIndex + 1, _outputRootProof, _withdrawalProof
);
// Ensure that the withdrawal was updated within the mapping
(, uint128 timestamp,) = op.provenWithdrawals(_withdrawalHash);
(, uint128 timestamp,) = optimismPortal.provenWithdrawals(_withdrawalHash);
assertEq(timestamp, block.timestamp);
}
......@@ -469,7 +504,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
function test_proveWithdrawalTransaction_validWithdrawalProof_succeeds() external {
vm.expectEmit(true, true, true, true);
emit WithdrawalProven(_withdrawalHash, alice, bob);
op.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof);
optimismPortal.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof);
}
/// @dev Tests that `finalizeWithdrawalTransaction` succeeds.
......@@ -478,23 +513,23 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
vm.expectEmit(true, true, true, true);
emit WithdrawalProven(_withdrawalHash, alice, bob);
op.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof);
optimismPortal.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof);
vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);
vm.warp(block.timestamp + l2OutputOracle.FINALIZATION_PERIOD_SECONDS() + 1);
vm.expectEmit(true, true, false, true);
emit WithdrawalFinalized(_withdrawalHash, true);
op.finalizeWithdrawalTransaction(_defaultTx);
optimismPortal.finalizeWithdrawalTransaction(_defaultTx);
assert(address(bob).balance == bobBalanceBefore + 100);
}
/// @dev Tests that `finalizeWithdrawalTransaction` reverts if the contract is paused.
function test_finalizeWithdrawalTransaction_paused_reverts() external {
vm.prank(op.GUARDIAN());
op.pause();
vm.prank(optimismPortal.GUARDIAN());
optimismPortal.pause();
vm.expectRevert("OptimismPortal: paused");
op.finalizeWithdrawalTransaction(_defaultTx);
optimismPortal.finalizeWithdrawalTransaction(_defaultTx);
}
/// @dev Tests that `finalizeWithdrawalTransaction` reverts if the withdrawal has not been
......@@ -502,7 +537,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
uint256 bobBalanceBefore = address(bob).balance;
vm.expectRevert("OptimismPortal: withdrawal has not been proven yet");
op.finalizeWithdrawalTransaction(_defaultTx);
optimismPortal.finalizeWithdrawalTransaction(_defaultTx);
assert(address(bob).balance == bobBalanceBefore);
}
......@@ -514,18 +549,18 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
vm.expectEmit(true, true, true, true);
emit WithdrawalProven(_withdrawalHash, alice, bob);
op.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof);
optimismPortal.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof);
// Mock a call where the resulting output root is anything but the original output root. In
// this case we just use bytes32(uint256(1)).
vm.mockCall(
address(op.L2_ORACLE()),
address(optimismPortal.L2_ORACLE()),
abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),
abi.encode(bytes32(uint256(1)), _proposedBlockNumber)
);
vm.expectRevert("OptimismPortal: proven withdrawal finalization period has not elapsed");
op.finalizeWithdrawalTransaction(_defaultTx);
optimismPortal.finalizeWithdrawalTransaction(_defaultTx);
assert(address(bob).balance == bobBalanceBefore);
}
......@@ -538,19 +573,21 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
// Prove our withdrawal
vm.expectEmit(true, true, true, true);
emit WithdrawalProven(_withdrawalHash, alice, bob);
op.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof);
optimismPortal.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof);
// Warp to after the finalization period
vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);
vm.warp(block.timestamp + l2OutputOracle.FINALIZATION_PERIOD_SECONDS() + 1);
// Mock a startingTimestamp change on the L2 Oracle
vm.mockCall(
address(op.L2_ORACLE()), abi.encodeWithSignature("startingTimestamp()"), abi.encode(block.timestamp + 1)
address(optimismPortal.L2_ORACLE()),
abi.encodeWithSignature("startingTimestamp()"),
abi.encode(block.timestamp + 1)
);
// Attempt to finalize the withdrawal
vm.expectRevert("OptimismPortal: withdrawal timestamp less than L2 Oracle starting timestamp");
op.finalizeWithdrawalTransaction(_defaultTx);
optimismPortal.finalizeWithdrawalTransaction(_defaultTx);
// Ensure that bob's balance has remained the same
assertEq(bobBalanceBefore, address(bob).balance);
......@@ -564,15 +601,15 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
// Prove our withdrawal
vm.expectEmit(true, true, true, true);
emit WithdrawalProven(_withdrawalHash, alice, bob);
op.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof);
optimismPortal.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof);
// Warp to after the finalization period
vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);
vm.warp(block.timestamp + l2OutputOracle.FINALIZATION_PERIOD_SECONDS() + 1);
// Mock an outputRoot change on the output proposal before attempting
// to finalize the withdrawal.
vm.mockCall(
address(op.L2_ORACLE()),
address(optimismPortal.L2_ORACLE()),
abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),
abi.encode(
Types.OutputProposal(bytes32(uint256(0)), uint128(block.timestamp), uint128(_proposedBlockNumber))
......@@ -581,7 +618,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
// Attempt to finalize the withdrawal
vm.expectRevert("OptimismPortal: output root proven is not the same as current output root");
op.finalizeWithdrawalTransaction(_defaultTx);
optimismPortal.finalizeWithdrawalTransaction(_defaultTx);
// Ensure that bob's balance has remained the same
assertEq(bobBalanceBefore, address(bob).balance);
......@@ -595,22 +632,22 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
// Prove our withdrawal
vm.expectEmit(true, true, true, true);
emit WithdrawalProven(_withdrawalHash, alice, bob);
op.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof);
optimismPortal.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof);
// Warp to after the finalization period
vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);
vm.warp(block.timestamp + l2OutputOracle.FINALIZATION_PERIOD_SECONDS() + 1);
// Mock a timestamp change on the output proposal that has not passed the
// finalization period.
vm.mockCall(
address(op.L2_ORACLE()),
address(optimismPortal.L2_ORACLE()),
abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),
abi.encode(Types.OutputProposal(_outputRoot, uint128(block.timestamp + 1), uint128(_proposedBlockNumber)))
);
// Attempt to finalize the withdrawal
vm.expectRevert("OptimismPortal: output proposal finalization period has not elapsed");
op.finalizeWithdrawalTransaction(_defaultTx);
optimismPortal.finalizeWithdrawalTransaction(_defaultTx);
// Ensure that bob's balance has remained the same
assertEq(bobBalanceBefore, address(bob).balance);
......@@ -623,12 +660,12 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
vm.expectEmit(true, true, true, true);
emit WithdrawalProven(_withdrawalHash, alice, bob);
op.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof);
optimismPortal.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof);
vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);
vm.warp(block.timestamp + l2OutputOracle.FINALIZATION_PERIOD_SECONDS() + 1);
vm.expectEmit(true, true, true, true);
emit WithdrawalFinalized(_withdrawalHash, false);
op.finalizeWithdrawalTransaction(_defaultTx);
optimismPortal.finalizeWithdrawalTransaction(_defaultTx);
assert(address(bob).balance == bobBalanceBefore);
}
......@@ -637,17 +674,17 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
/// has not yet passed.
function test_finalizeWithdrawalTransaction_onRecentWithdrawal_reverts() external {
// Setup the Oracle to return an output with a recent timestamp
uint256 recentTimestamp = block.timestamp - 1000;
uint256 recentTimestamp = block.timestamp - 1;
vm.mockCall(
address(op.L2_ORACLE()),
address(optimismPortal.L2_ORACLE()),
abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),
abi.encode(Types.OutputProposal(_outputRoot, uint128(recentTimestamp), uint128(_proposedBlockNumber)))
);
op.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof);
optimismPortal.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof);
vm.expectRevert("OptimismPortal: proven withdrawal finalization period has not elapsed");
op.finalizeWithdrawalTransaction(_defaultTx);
optimismPortal.finalizeWithdrawalTransaction(_defaultTx);
}
/// @dev Tests that `finalizeWithdrawalTransaction` reverts if the withdrawal has already been
......@@ -655,15 +692,15 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
function test_finalizeWithdrawalTransaction_onReplay_reverts() external {
vm.expectEmit(true, true, true, true);
emit WithdrawalProven(_withdrawalHash, alice, bob);
op.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof);
optimismPortal.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof);
vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);
vm.warp(block.timestamp + l2OutputOracle.FINALIZATION_PERIOD_SECONDS() + 1);
vm.expectEmit(true, true, true, true);
emit WithdrawalFinalized(_withdrawalHash, true);
op.finalizeWithdrawalTransaction(_defaultTx);
optimismPortal.finalizeWithdrawalTransaction(_defaultTx);
vm.expectRevert("OptimismPortal: withdrawal has already been finalized");
op.finalizeWithdrawalTransaction(_defaultTx);
optimismPortal.finalizeWithdrawalTransaction(_defaultTx);
}
/// @dev Tests that `finalizeWithdrawalTransaction` reverts if the withdrawal transaction
......@@ -691,7 +728,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
});
vm.mockCall(
address(op.L2_ORACLE()),
address(optimismPortal.L2_ORACLE()),
abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),
abi.encode(
Types.OutputProposal(
......@@ -702,11 +739,13 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
)
);
op.proveWithdrawalTransaction(insufficientGasTx, _proposedOutputIndex, outputRootProof, withdrawalProof);
optimismPortal.proveWithdrawalTransaction(
insufficientGasTx, _proposedOutputIndex, outputRootProof, withdrawalProof
);
vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);
vm.warp(block.timestamp + l2OutputOracle.FINALIZATION_PERIOD_SECONDS() + 1);
vm.expectRevert("SafeCall: Not enough gas");
op.finalizeWithdrawalTransaction{ gas: gasLimit }(insufficientGasTx);
optimismPortal.finalizeWithdrawalTransaction{ gas: gasLimit }(insufficientGasTx);
}
/// @dev Tests that `finalizeWithdrawalTransaction` reverts if a sub-call attempts to finalize
......@@ -736,22 +775,22 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
});
// Setup the Oracle to return the outputRoot we want as well as a finalized timestamp.
uint256 finalizedTimestamp = block.timestamp - oracle.FINALIZATION_PERIOD_SECONDS() - 1;
uint256 finalizedTimestamp = block.timestamp - l2OutputOracle.FINALIZATION_PERIOD_SECONDS() - 1;
vm.mockCall(
address(op.L2_ORACLE()),
address(optimismPortal.L2_ORACLE()),
abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),
abi.encode(Types.OutputProposal(outputRoot, uint128(finalizedTimestamp), uint128(_proposedBlockNumber)))
);
vm.expectEmit(true, true, true, true);
emit WithdrawalProven(withdrawalHash, alice, address(this));
op.proveWithdrawalTransaction(_testTx, _proposedBlockNumber, outputRootProof, withdrawalProof);
optimismPortal.proveWithdrawalTransaction(_testTx, _proposedBlockNumber, outputRootProof, withdrawalProof);
vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);
vm.warp(block.timestamp + l2OutputOracle.FINALIZATION_PERIOD_SECONDS() + 1);
vm.expectCall(address(this), _testTx.data);
vm.expectEmit(true, true, true, true);
emit WithdrawalFinalized(withdrawalHash, true);
op.finalizeWithdrawalTransaction(_testTx);
optimismPortal.finalizeWithdrawalTransaction(_testTx);
// Ensure that bob's balance was not changed by the reentrant call.
assert(address(bob).balance == bobBalanceBefore);
......@@ -768,7 +807,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
external
{
vm.assume(
_target != address(op) // Cannot call the optimism portal or a contract
_target != address(optimismPortal) // Cannot call the optimism portal or a contract
&& _target.code.length == 0 // No accounts with code
&& _target != CONSOLE // The console has no code but behaves like a contract
&& uint160(_target) > 9 // No precompiles (or zero address)
......@@ -776,10 +815,10 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
// Total ETH supply is currently about 120M ETH.
uint256 value = bound(_value, 0, 200_000_000 ether);
vm.deal(address(op), value);
vm.deal(address(optimismPortal), value);
uint256 gasLimit = bound(_gasLimit, 0, 50_000_000);
uint256 nonce = messagePasser.messageNonce();
uint256 nonce = l2ToL1MessagePasser.messageNonce();
// Get a withdrawal transaction and mock proof from the differential testing script.
Types.WithdrawalTransaction memory _tx = Types.WithdrawalTransaction({
......@@ -812,58 +851,46 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
// Setup the Oracle to return the outputRoot
vm.mockCall(
address(oracle),
abi.encodeWithSelector(oracle.getL2Output.selector),
address(l2OutputOracle),
abi.encodeWithSelector(l2OutputOracle.getL2Output.selector),
abi.encode(outputRoot, block.timestamp, 100)
);
// Prove the withdrawal transaction
op.proveWithdrawalTransaction(
optimismPortal.proveWithdrawalTransaction(
_tx,
100, // l2BlockNumber
proof,
withdrawalProof
);
(bytes32 _root,,) = op.provenWithdrawals(withdrawalHash);
(bytes32 _root,,) = optimismPortal.provenWithdrawals(withdrawalHash);
assertTrue(_root != bytes32(0));
// Warp past the finalization period
vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);
vm.warp(block.timestamp + l2OutputOracle.FINALIZATION_PERIOD_SECONDS() + 1);
// Finalize the withdrawal transaction
vm.expectCallMinGas(_tx.target, _tx.value, uint64(_tx.gasLimit), _tx.data);
op.finalizeWithdrawalTransaction(_tx);
assertTrue(op.finalizedWithdrawals(withdrawalHash));
optimismPortal.finalizeWithdrawalTransaction(_tx);
assertTrue(optimismPortal.finalizedWithdrawals(withdrawalHash));
}
}
contract OptimismPortalUpgradeable_Test is Portal_Initializer {
Proxy internal proxy;
uint64 initialBlockNum;
/// @dev Sets up the test.
function setUp() public override {
super.setUp();
initialBlockNum = uint64(block.number);
proxy = Proxy(payable(address(op)));
}
/// @dev Tests that the proxy is initialized correctly.
function test_params_initValuesOnProxy_succeeds() external {
OptimismPortal p = OptimismPortal(payable(address(proxy)));
(uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = p.params();
(uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = optimismPortal.params();
ResourceMetering.ResourceConfig memory rcfg = systemConfig.resourceConfig();
assertEq(prevBaseFee, rcfg.minimumBaseFee);
assertEq(prevBoughtGas, 0);
assertEq(prevBlockNum, initialBlockNum);
assertEq(prevBlockNum, block.number - 1);
}
/// @dev Tests that the proxy cannot be initialized twice.
function test_initialize_cannotInitProxy_reverts() external {
vm.expectRevert("Initializable: contract is already initialized");
OptimismPortal(payable(proxy)).initialize({
optimismPortal.initialize({
_l2Oracle: L2OutputOracle(address(0)),
_systemConfig: SystemConfig(address(0)),
_guardian: address(0),
......@@ -873,8 +900,9 @@ contract OptimismPortalUpgradeable_Test is Portal_Initializer {
/// @dev Tests that the implementation cannot be initialized twice.
function test_initialize_cannotInitImpl_reverts() external {
address opImpl = mustGetAddress("OptimismPortal");
vm.expectRevert("Initializable: contract is already initialized");
OptimismPortal(opImpl).initialize({
OptimismPortal(payable(opImpl)).initialize({
_l2Oracle: L2OutputOracle(address(0)),
_systemConfig: SystemConfig(address(0)),
_guardian: address(0),
......@@ -885,21 +913,22 @@ contract OptimismPortalUpgradeable_Test is Portal_Initializer {
/// @dev Tests that the proxy can be upgraded.
function test_upgradeToAndCall_upgrading_succeeds() external {
// Check an unused slot before upgrading.
bytes32 slot21Before = vm.load(address(op), bytes32(uint256(21)));
bytes32 slot21Before = vm.load(address(optimismPortal), bytes32(uint256(21)));
assertEq(bytes32(0), slot21Before);
NextImpl nextImpl = new NextImpl();
vm.startPrank(multisig);
vm.startPrank(EIP1967Helper.getAdmin(address(optimismPortal)));
// The value passed to the initialize must be larger than the last value
// that initialize was called with.
proxy.upgradeToAndCall(
Proxy(payable(address(optimismPortal))).upgradeToAndCall(
address(nextImpl), abi.encodeWithSelector(NextImpl.initialize.selector, Constants.INITIALIZER + 1)
);
assertEq(proxy.implementation(), address(nextImpl));
assertEq(Proxy(payable(address(optimismPortal))).implementation(), address(nextImpl));
// Verify that the NextImpl contract initialized its values according as expected
bytes32 slot21After = vm.load(address(op), bytes32(uint256(21)));
bytes32 slot21Expected = NextImpl(address(op)).slot21Init();
bytes32 slot21After = vm.load(address(optimismPortal), bytes32(uint256(21)));
bytes32 slot21Expected = NextImpl(address(optimismPortal)).slot21Init();
assertEq(slot21Expected, slot21After);
}
}
......@@ -945,6 +974,8 @@ contract OptimismPortalResourceFuzz_Test is Portal_Initializer {
// Pick a pseudorandom block number
vm.roll(uint256(keccak256(abi.encode(_blockDiff))) % uint256(type(uint16).max) + uint256(_blockDiff));
vm.roll(uint256(keccak256(abi.encode(_blockDiff))) % uint256(type(uint16).max));
// Create a resource config to mock the call to the system config with
ResourceMetering.ResourceConfig memory rcfg = ResourceMetering.ResourceConfig({
maxResourceLimit: _maxResourceLimit,
......@@ -961,18 +992,18 @@ contract OptimismPortalResourceFuzz_Test is Portal_Initializer {
// Set the resource params
uint256 _prevBlockNum = block.number - _blockDiff;
vm.store(
address(op),
address(optimismPortal),
bytes32(uint256(1)),
bytes32((_prevBlockNum << 192) | (uint256(_prevBoughtGas) << 128) | _prevBaseFee)
);
// Ensure that the storage setting is correct
(uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = op.params();
(uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = optimismPortal.params();
assertEq(prevBaseFee, _prevBaseFee);
assertEq(prevBoughtGas, _prevBoughtGas);
assertEq(prevBlockNum, _prevBlockNum);
// Do a deposit, should not revert
op.depositTransaction{ gas: MAX_GAS_LIMIT }({
optimismPortal.depositTransaction{ gas: MAX_GAS_LIMIT }({
_to: address(0x20),
_value: 0x40,
_gasLimit: _gasLimit,
......
......@@ -3,6 +3,7 @@ pragma solidity 0.8.15;
// Testing utilities
import { CommonTest } from "test/CommonTest.t.sol";
import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol";
// Libraries
import { Constants } from "src/libraries/Constants.sol";
......@@ -14,44 +15,27 @@ import { Proxy } from "src/universal/Proxy.sol";
import { ProtocolVersions, ProtocolVersion } from "src/L1/ProtocolVersions.sol";
contract ProtocolVersions_Init is CommonTest {
ProtocolVersions protocolVersions;
ProtocolVersions protocolVersionsImpl;
event ConfigUpdate(uint256 indexed version, ProtocolVersions.UpdateType indexed updateType, bytes data);
// Dummy values used to test getters
ProtocolVersion constant required = ProtocolVersion.wrap(0xabcd);
ProtocolVersion constant recommended = ProtocolVersion.wrap(0x1234);
ProtocolVersion required;
ProtocolVersion recommended;
function setUp() public virtual override {
super.setUp();
Proxy proxy = new Proxy(multisig);
protocolVersionsImpl = new ProtocolVersions();
vm.prank(multisig);
proxy.upgradeToAndCall(
address(protocolVersionsImpl),
abi.encodeCall(
ProtocolVersions.initialize,
(
alice, // _owner,
required,
recommended
)
)
);
protocolVersions = ProtocolVersions(address(proxy));
required = ProtocolVersion.wrap(cfg.requiredProtocolVersion());
recommended = ProtocolVersion.wrap(cfg.recommendedProtocolVersion());
}
}
contract ProtocolVersions_Initialize_Test is ProtocolVersions_Init {
/// @dev Tests that initialization sets the correct values.
function test_initialize_values_succeeds() external {
ProtocolVersions protocolVersionsImpl = ProtocolVersions(mustGetAddress("ProtocolVersions"));
address owner = cfg.finalSystemOwner();
assertEq(ProtocolVersion.unwrap(protocolVersions.required()), ProtocolVersion.unwrap(required));
assertEq(ProtocolVersion.unwrap(protocolVersions.recommended()), ProtocolVersion.unwrap(recommended));
assertEq(protocolVersions.owner(), alice);
assertEq(protocolVersions.owner(), owner);
assertEq(ProtocolVersion.unwrap(protocolVersionsImpl.required()), 0);
assertEq(ProtocolVersion.unwrap(protocolVersionsImpl.recommended()), 0);
......@@ -60,6 +44,7 @@ contract ProtocolVersions_Initialize_Test is ProtocolVersions_Init {
/// @dev Ensures that the events are emitted during initialization.
function test_initialize_events_succeeds() external {
ProtocolVersions protocolVersionsImpl = ProtocolVersions(mustGetAddress("ProtocolVersions"));
assertEq(protocolVersionsImpl.owner(), address(0xdEad));
// Wipe out the initialized slot so the proxy can be initialized again
......@@ -71,7 +56,7 @@ contract ProtocolVersions_Initialize_Test is ProtocolVersions_Init {
vm.expectEmit(true, true, true, true, address(protocolVersions));
emit ConfigUpdate(0, ProtocolVersions.UpdateType.RECOMMENDED_PROTOCOL_VERSION, abi.encode(recommended));
vm.prank(multisig);
vm.prank(EIP1967Helper.getAdmin(address(protocolVersions)));
Proxy(payable(address(protocolVersions))).upgradeToAndCall(
address(protocolVersionsImpl),
abi.encodeCall(
......
......@@ -16,126 +16,142 @@ import { FeeVault } from "src/universal/FeeVault.sol";
import { SequencerFeeVault } from "src/L2/SequencerFeeVault.sol";
contract SequencerFeeVault_Test is FeeVault_Initializer {
address recipient;
/// @dev Sets up the test suite.
function setUp() public override {
super.setUp();
vm.etch(
Predeploys.SEQUENCER_FEE_WALLET,
address(new SequencerFeeVault(recipient, NON_ZERO_VALUE, FeeVault.WithdrawalNetwork.L1)).code
);
vm.label(Predeploys.SEQUENCER_FEE_WALLET, "SequencerFeeVault");
recipient = cfg.sequencerFeeVaultRecipient();
}
/// @dev Tests that the minimum withdrawal amount is correct.
function test_minWithdrawalAmount_succeeds() external {
assertEq(vault.MIN_WITHDRAWAL_AMOUNT(), NON_ZERO_VALUE);
assertEq(sequencerFeeVault.MIN_WITHDRAWAL_AMOUNT(), cfg.sequencerFeeVaultMinimumWithdrawalAmount());
}
/// @dev Tests that the l1 fee wallet is correct.
function test_constructor_succeeds() external {
assertEq(vault.l1FeeWallet(), recipient);
assertEq(sequencerFeeVault.l1FeeWallet(), recipient);
}
/// @dev Tests that the fee vault is able to receive ETH.
function test_receive_succeeds() external {
uint256 balance = address(vault).balance;
uint256 balance = address(sequencerFeeVault).balance;
vm.prank(alice);
(bool success,) = address(vault).call{ value: 100 }(hex"");
(bool success,) = address(sequencerFeeVault).call{ value: 100 }(hex"");
assertEq(success, true);
assertEq(address(vault).balance, balance + 100);
assertEq(address(sequencerFeeVault).balance, balance + 100);
}
/// @dev Tests that `withdraw` reverts if the balance is less than the minimum
/// withdrawal amount.
function test_withdraw_notEnough_reverts() external {
assert(address(vault).balance < vault.MIN_WITHDRAWAL_AMOUNT());
assert(address(sequencerFeeVault).balance < sequencerFeeVault.MIN_WITHDRAWAL_AMOUNT());
vm.expectRevert("FeeVault: withdrawal amount must be greater than minimum withdrawal amount");
vault.withdraw();
sequencerFeeVault.withdraw();
}
/// @dev Tests that `withdraw` successfully initiates a withdrawal to L1.
function test_withdraw_toL1_succeeds() external {
uint256 amount = vault.MIN_WITHDRAWAL_AMOUNT() + 1;
vm.deal(address(vault), amount);
// Set the code with the withdrawal network set to L1
vm.etch(
Predeploys.SEQUENCER_FEE_WALLET,
address(
new SequencerFeeVault(cfg.sequencerFeeVaultRecipient(), cfg.sequencerFeeVaultMinimumWithdrawalAmount(), FeeVault.WithdrawalNetwork.L1)
).code
);
uint256 amount = sequencerFeeVault.MIN_WITHDRAWAL_AMOUNT() + 1;
vm.deal(address(sequencerFeeVault), amount);
// No ether has been withdrawn yet
assertEq(vault.totalProcessed(), 0);
assertEq(sequencerFeeVault.totalProcessed(), 0);
vm.expectEmit(true, true, true, true, address(Predeploys.SEQUENCER_FEE_WALLET));
emit Withdrawal(address(vault).balance, vault.RECIPIENT(), address(this));
emit Withdrawal(address(sequencerFeeVault).balance, sequencerFeeVault.RECIPIENT(), address(this));
vm.expectEmit(true, true, true, true, address(Predeploys.SEQUENCER_FEE_WALLET));
emit Withdrawal(address(vault).balance, vault.RECIPIENT(), address(this), FeeVault.WithdrawalNetwork.L1);
emit Withdrawal(
address(sequencerFeeVault).balance,
sequencerFeeVault.RECIPIENT(),
address(this),
FeeVault.WithdrawalNetwork.L1
);
// The entire vault's balance is withdrawn
vm.expectCall(
Predeploys.L2_STANDARD_BRIDGE,
address(vault).balance,
abi.encodeWithSelector(StandardBridge.bridgeETHTo.selector, vault.l1FeeWallet(), 35_000, bytes(""))
address(sequencerFeeVault).balance,
abi.encodeWithSelector(
StandardBridge.bridgeETHTo.selector, sequencerFeeVault.l1FeeWallet(), 35_000, bytes("")
)
);
vault.withdraw();
sequencerFeeVault.withdraw();
// The withdrawal was successful
assertEq(vault.totalProcessed(), amount);
assertEq(address(vault).balance, ZERO_VALUE);
assertEq(sequencerFeeVault.totalProcessed(), amount);
assertEq(address(sequencerFeeVault).balance, 0);
assertEq(Predeploys.L2_TO_L1_MESSAGE_PASSER.balance, amount);
}
}
contract SequencerFeeVault_L2Withdrawal_Test is FeeVault_Initializer {
address recipient;
/// @dev Sets up the test suite.
function setUp() public override {
super.setUp();
vm.etch(
Predeploys.SEQUENCER_FEE_WALLET,
address(new SequencerFeeVault(recipient, NON_ZERO_VALUE, FeeVault.WithdrawalNetwork.L2)).code
);
vm.label(Predeploys.SEQUENCER_FEE_WALLET, "SequencerFeeVault");
recipient = cfg.sequencerFeeVaultRecipient();
}
/// @dev Tests that `withdraw` successfully initiates a withdrawal to L2.
function test_withdraw_toL2_succeeds() external {
uint256 amount = vault.MIN_WITHDRAWAL_AMOUNT() + 1;
vm.deal(address(vault), amount);
uint256 amount = sequencerFeeVault.MIN_WITHDRAWAL_AMOUNT() + 1;
vm.deal(address(sequencerFeeVault), amount);
// No ether has been withdrawn yet
assertEq(vault.totalProcessed(), 0);
assertEq(sequencerFeeVault.totalProcessed(), 0);
vm.expectEmit(true, true, true, true, address(Predeploys.SEQUENCER_FEE_WALLET));
emit Withdrawal(address(vault).balance, vault.RECIPIENT(), address(this));
emit Withdrawal(address(sequencerFeeVault).balance, sequencerFeeVault.RECIPIENT(), address(this));
vm.expectEmit(true, true, true, true, address(Predeploys.SEQUENCER_FEE_WALLET));
emit Withdrawal(address(vault).balance, vault.RECIPIENT(), address(this), FeeVault.WithdrawalNetwork.L2);
emit Withdrawal(
address(sequencerFeeVault).balance,
sequencerFeeVault.RECIPIENT(),
address(this),
FeeVault.WithdrawalNetwork.L2
);
// The entire vault's balance is withdrawn
vm.expectCall(recipient, address(vault).balance, bytes(""));
vm.expectCall(recipient, address(sequencerFeeVault).balance, bytes(""));
vault.withdraw();
sequencerFeeVault.withdraw();
// The withdrawal was successful
assertEq(vault.totalProcessed(), amount);
assertEq(address(vault).balance, ZERO_VALUE);
assertEq(sequencerFeeVault.totalProcessed(), amount);
assertEq(address(sequencerFeeVault).balance, 0);
assertEq(recipient.balance, amount);
}
/// @dev Tests that `withdraw` fails if the Recipient reverts. This also serves to simulate
/// a situation where insufficient gas is provided to the RECIPIENT.
function test_withdraw_toL2recipientReverts_fails() external {
uint256 amount = vault.MIN_WITHDRAWAL_AMOUNT();
uint256 amount = sequencerFeeVault.MIN_WITHDRAWAL_AMOUNT();
vm.deal(address(vault), amount);
vm.deal(address(sequencerFeeVault), amount);
// No ether has been withdrawn yet
assertEq(vault.totalProcessed(), 0);
assertEq(sequencerFeeVault.totalProcessed(), 0);
// Ensure the RECIPIENT reverts
vm.etch(vault.RECIPIENT(), type(Reverter).runtimeCode);
vm.etch(sequencerFeeVault.RECIPIENT(), type(Reverter).runtimeCode);
// The entire vault's balance is withdrawn
vm.expectCall(recipient, address(vault).balance, bytes(""));
vm.expectCall(recipient, address(sequencerFeeVault).balance, bytes(""));
vm.expectRevert("FeeVault: failed to send ETH to L2 fee recipient");
vault.withdraw();
assertEq(vault.totalProcessed(), 0);
sequencerFeeVault.withdraw();
assertEq(sequencerFeeVault.totalProcessed(), 0);
}
}
......@@ -15,89 +15,59 @@ import { Proxy } from "src/universal/Proxy.sol";
import { SystemConfig } from "src/L1/SystemConfig.sol";
contract SystemConfig_Init is CommonTest {
SystemConfig sysConf;
SystemConfig systemConfigImpl;
event ConfigUpdate(uint256 indexed version, SystemConfig.UpdateType indexed updateType, bytes data);
}
// Dummy addresses used to test getters
address constant batchInbox = address(0x18);
address constant l1CrossDomainMessenger = address(0x20);
address constant l1ERC721Bridge = address(0x21);
address constant l1StandardBridge = address(0x22);
address constant l2OutputOracle = address(0x23);
address constant optimismPortal = address(0x24);
address constant optimismMintableERC20Factory = address(0x25);
uint256 constant overhead = 2100;
uint256 constant scalar = 1000000;
bytes32 constant batcherHash = bytes32(hex"abcd");
uint64 constant gasLimit = 30_000_000;
address constant unsafeBlockSigner = address(1);
contract SystemConfig_Initialize_Test is SystemConfig_Init {
address batchInbox;
address owner;
uint256 overhead;
uint256 scalar;
bytes32 batcherHash;
uint64 gasLimit;
address unsafeBlockSigner;
address systemConfigImpl;
address optimismMintableERC20Factory;
function setUp() public virtual override {
super.setUp();
Proxy proxy = new Proxy(multisig);
systemConfigImpl = new SystemConfig();
vm.prank(multisig);
proxy.upgradeToAndCall(
address(systemConfigImpl),
abi.encodeCall(
SystemConfig.initialize,
(
alice, // _owner,
overhead, // _overhead,
scalar, // _scalar,
batcherHash, // _batcherHash
gasLimit, // _gasLimit,
unsafeBlockSigner, // _unsafeBlockSigner,
Constants.DEFAULT_RESOURCE_CONFIG(), // _config,
0, // _startBlock
batchInbox, // _batchInbox
SystemConfig.Addresses({ // _addresses
l1CrossDomainMessenger: l1CrossDomainMessenger,
l1ERC721Bridge: l1ERC721Bridge,
l1StandardBridge: l1StandardBridge,
l2OutputOracle: l2OutputOracle,
optimismPortal: optimismPortal,
optimismMintableERC20Factory: optimismMintableERC20Factory
})
)
)
);
sysConf = SystemConfig(address(proxy));
batchInbox = cfg.batchInboxAddress();
owner = cfg.finalSystemOwner();
overhead = cfg.gasPriceOracleOverhead();
scalar = cfg.gasPriceOracleScalar();
batcherHash = bytes32(uint256(uint160(cfg.batchSenderAddress())));
gasLimit = uint64(cfg.l2GenesisBlockGasLimit());
unsafeBlockSigner = cfg.p2pSequencerAddress();
systemConfigImpl = mustGetAddress("SystemConfig");
optimismMintableERC20Factory = mustGetAddress("OptimismMintableERC20FactoryProxy");
}
}
contract SystemConfig_Initialize_Test is SystemConfig_Init {
/// @dev Tests that initailization sets the correct values.
function test_initialize_values_succeeds() external {
assertEq(sysConf.l1CrossDomainMessenger(), l1CrossDomainMessenger);
assertEq(sysConf.l1ERC721Bridge(), l1ERC721Bridge);
assertEq(sysConf.l1StandardBridge(), l1StandardBridge);
assertEq(sysConf.l2OutputOracle(), l2OutputOracle);
assertEq(sysConf.optimismPortal(), optimismPortal);
assertEq(sysConf.optimismMintableERC20Factory(), optimismMintableERC20Factory);
assertEq(sysConf.batchInbox(), batchInbox);
assertEq(sysConf.owner(), alice);
assertEq(sysConf.overhead(), overhead);
assertEq(sysConf.scalar(), scalar);
assertEq(sysConf.batcherHash(), batcherHash);
assertEq(sysConf.gasLimit(), gasLimit);
assertEq(sysConf.unsafeBlockSigner(), unsafeBlockSigner);
assertEq(systemConfig.l1CrossDomainMessenger(), address(l1CrossDomainMessenger));
assertEq(systemConfig.l1ERC721Bridge(), address(l1ERC721Bridge));
assertEq(systemConfig.l1StandardBridge(), address(l1StandardBridge));
assertEq(systemConfig.l2OutputOracle(), address(l2OutputOracle));
assertEq(systemConfig.optimismPortal(), address(optimismPortal));
assertEq(systemConfig.optimismMintableERC20Factory(), optimismMintableERC20Factory);
assertEq(systemConfig.batchInbox(), batchInbox);
assertEq(systemConfig.owner(), owner);
assertEq(systemConfig.overhead(), overhead);
assertEq(systemConfig.scalar(), scalar);
assertEq(systemConfig.batcherHash(), batcherHash);
assertEq(systemConfig.gasLimit(), gasLimit);
assertEq(systemConfig.unsafeBlockSigner(), unsafeBlockSigner);
// Depends on start block being set to 0 in `initialize`
assertEq(sysConf.startBlock(), block.number);
assertEq(systemConfig.startBlock(), block.number);
// Depends on `initialize` being called with defaults
ResourceMetering.ResourceConfig memory cfg = Constants.DEFAULT_RESOURCE_CONFIG();
ResourceMetering.ResourceConfig memory actual = sysConf.resourceConfig();
assertEq(actual.maxResourceLimit, cfg.maxResourceLimit);
assertEq(actual.elasticityMultiplier, cfg.elasticityMultiplier);
assertEq(actual.baseFeeMaxChangeDenominator, cfg.baseFeeMaxChangeDenominator);
assertEq(actual.minimumBaseFee, cfg.minimumBaseFee);
assertEq(actual.systemTxMaxGas, cfg.systemTxMaxGas);
assertEq(actual.maximumBaseFee, cfg.maximumBaseFee);
ResourceMetering.ResourceConfig memory rcfg = Constants.DEFAULT_RESOURCE_CONFIG();
ResourceMetering.ResourceConfig memory actual = systemConfig.resourceConfig();
assertEq(actual.maxResourceLimit, rcfg.maxResourceLimit);
assertEq(actual.elasticityMultiplier, rcfg.elasticityMultiplier);
assertEq(actual.baseFeeMaxChangeDenominator, rcfg.baseFeeMaxChangeDenominator);
assertEq(actual.minimumBaseFee, rcfg.minimumBaseFee);
assertEq(actual.systemTxMaxGas, rcfg.systemTxMaxGas);
assertEq(actual.maximumBaseFee, rcfg.maximumBaseFee);
}
/// @dev Ensures that the start block override can be used to set the start block.
......@@ -105,15 +75,17 @@ contract SystemConfig_Initialize_Test is SystemConfig_Init {
uint256 startBlock = 100;
// Wipe out the initialized slot so the proxy can be initialized again
vm.store(address(sysConf), bytes32(0), bytes32(0));
vm.store(address(systemConfig), bytes32(0), bytes32(0));
assertEq(sysConf.startBlock(), block.number);
assertEq(systemConfig.startBlock(), block.number);
// the startBlock slot is 106, wipe it out
vm.store(address(sysConf), bytes32(uint256(106)), bytes32(0));
assertEq(sysConf.startBlock(), 0);
vm.store(address(systemConfig), bytes32(uint256(106)), bytes32(0));
assertEq(systemConfig.startBlock(), 0);
address admin = address(uint160(uint256(vm.load(address(systemConfig), Constants.PROXY_OWNER_ADDRESS))));
vm.prank(admin);
vm.prank(multisig);
Proxy(payable(address(sysConf))).upgradeToAndCall(
Proxy(payable(address(systemConfig))).upgradeToAndCall(
address(systemConfigImpl),
abi.encodeCall(
SystemConfig.initialize,
......@@ -128,31 +100,32 @@ contract SystemConfig_Initialize_Test is SystemConfig_Init {
startBlock, // _startBlock
batchInbox, // _batchInbox
SystemConfig.Addresses({ // _addresses
l1CrossDomainMessenger: l1CrossDomainMessenger,
l1ERC721Bridge: l1ERC721Bridge,
l1StandardBridge: l1StandardBridge,
l2OutputOracle: l2OutputOracle,
optimismPortal: optimismPortal,
l1CrossDomainMessenger: address(l1CrossDomainMessenger),
l1ERC721Bridge: address(l1ERC721Bridge),
l1StandardBridge: address(l1StandardBridge),
l2OutputOracle: address(l2OutputOracle),
optimismPortal: address(optimismPortal),
optimismMintableERC20Factory: optimismMintableERC20Factory
})
)
)
);
assertEq(sysConf.startBlock(), startBlock);
assertEq(systemConfig.startBlock(), startBlock);
}
/// @dev Tests that initialization with start block already set is a noop.
function test_initialize_startBlockNoop_reverts() external {
// wipe out initialized slot so we can initialize again
vm.store(address(sysConf), bytes32(0), bytes32(0));
vm.store(address(systemConfig), bytes32(0), bytes32(0));
// the startBlock slot is 106, set it to something non zero
vm.store(address(sysConf), bytes32(uint256(106)), bytes32(uint256(0xff)));
vm.store(address(systemConfig), bytes32(uint256(106)), bytes32(uint256(0xff)));
// Initialize with a non zero start block, should see a revert
vm.prank(multisig);
address admin = address(uint160(uint256(vm.load(address(systemConfig), Constants.PROXY_OWNER_ADDRESS))));
vm.prank(admin);
// The call to initialize reverts due to: "SystemConfig: cannot override an already set start block"
// but the proxy revert message bubbles up.
Proxy(payable(address(sysConf))).upgradeToAndCall(
Proxy(payable(address(systemConfig))).upgradeToAndCall(
address(systemConfigImpl),
abi.encodeCall(
SystemConfig.initialize,
......@@ -167,11 +140,11 @@ contract SystemConfig_Initialize_Test is SystemConfig_Init {
1, // _startBlock
batchInbox, // _batchInbox
SystemConfig.Addresses({ // _addresses
l1CrossDomainMessenger: l1CrossDomainMessenger,
l1ERC721Bridge: l1ERC721Bridge,
l1StandardBridge: l1StandardBridge,
l2OutputOracle: l2OutputOracle,
optimismPortal: optimismPortal,
l1CrossDomainMessenger: address(l1CrossDomainMessenger),
l1ERC721Bridge: address(l1ERC721Bridge),
l1StandardBridge: address(l1StandardBridge),
l2OutputOracle: address(l2OutputOracle),
optimismPortal: address(optimismPortal),
optimismMintableERC20Factory: optimismMintableERC20Factory
})
)
......@@ -180,29 +153,31 @@ contract SystemConfig_Initialize_Test is SystemConfig_Init {
// It was initialized with 1 but it was already set so the override
// should be ignored.
uint256 startBlock = sysConf.startBlock();
uint256 startBlock = systemConfig.startBlock();
assertEq(startBlock, 0xff);
}
/// @dev Ensures that the events are emitted during initialization.
function test_initialize_events_succeeds() external {
// Wipe out the initialized slot so the proxy can be initialized again
vm.store(address(sysConf), bytes32(0), bytes32(0));
vm.store(address(sysConf), bytes32(uint256(106)), bytes32(0));
assertEq(sysConf.startBlock(), 0);
vm.store(address(systemConfig), bytes32(0), bytes32(0));
vm.store(address(systemConfig), bytes32(uint256(106)), bytes32(0));
assertEq(systemConfig.startBlock(), 0);
// The order depends here
vm.expectEmit(true, true, true, true, address(sysConf));
vm.expectEmit(true, true, true, true, address(systemConfig));
emit ConfigUpdate(0, SystemConfig.UpdateType.BATCHER, abi.encode(batcherHash));
vm.expectEmit(true, true, true, true, address(sysConf));
vm.expectEmit(true, true, true, true, address(systemConfig));
emit ConfigUpdate(0, SystemConfig.UpdateType.GAS_CONFIG, abi.encode(overhead, scalar));
vm.expectEmit(true, true, true, true, address(sysConf));
vm.expectEmit(true, true, true, true, address(systemConfig));
emit ConfigUpdate(0, SystemConfig.UpdateType.GAS_LIMIT, abi.encode(gasLimit));
vm.expectEmit(true, true, true, true, address(sysConf));
vm.expectEmit(true, true, true, true, address(systemConfig));
emit ConfigUpdate(0, SystemConfig.UpdateType.UNSAFE_BLOCK_SIGNER, abi.encode(unsafeBlockSigner));
vm.prank(multisig);
Proxy(payable(address(sysConf))).upgradeToAndCall(
address admin = address(uint160(uint256(vm.load(address(systemConfig), Constants.PROXY_OWNER_ADDRESS))));
vm.prank(admin);
Proxy(payable(address(systemConfig))).upgradeToAndCall(
address(systemConfigImpl),
abi.encodeCall(
SystemConfig.initialize,
......@@ -217,11 +192,11 @@ contract SystemConfig_Initialize_Test is SystemConfig_Init {
0, // _startBlock
batchInbox, // _batchInbox
SystemConfig.Addresses({ // _addresses
l1CrossDomainMessenger: l1CrossDomainMessenger,
l1ERC721Bridge: l1ERC721Bridge,
l1StandardBridge: l1StandardBridge,
l2OutputOracle: l2OutputOracle,
optimismPortal: optimismPortal,
l1CrossDomainMessenger: address(l1CrossDomainMessenger),
l1ERC721Bridge: address(l1ERC721Bridge),
l1StandardBridge: address(l1StandardBridge),
l2OutputOracle: address(l2OutputOracle),
optimismPortal: address(optimismPortal),
optimismMintableERC20Factory: optimismMintableERC20Factory
})
)
......@@ -233,15 +208,19 @@ contract SystemConfig_Initialize_Test is SystemConfig_Init {
contract SystemConfig_Initialize_TestFail is SystemConfig_Init {
/// @dev Tests that initialization reverts if the gas limit is too low.
function test_initialize_lowGasLimit_reverts() external {
uint64 minimumGasLimit = sysConf.minimumGasLimit();
address systemConfigImpl = mustGetAddress("SystemConfig");
uint64 minimumGasLimit = systemConfig.minimumGasLimit();
// Wipe out the initialized slot so the proxy can be initialized again
vm.store(address(sysConf), bytes32(0), bytes32(0));
vm.prank(multisig);
vm.store(address(systemConfig), bytes32(0), bytes32(0));
address admin = address(uint160(uint256(vm.load(address(systemConfig), Constants.PROXY_OWNER_ADDRESS))));
vm.prank(admin);
// The call to initialize reverts due to: "SystemConfig: gas limit too low"
// but the proxy revert message bubbles up.
vm.expectRevert("Proxy: delegatecall to new implementation contract failed");
Proxy(payable(address(sysConf))).upgradeToAndCall(
Proxy(payable(address(systemConfig))).upgradeToAndCall(
address(systemConfigImpl),
abi.encodeCall(
SystemConfig.initialize,
......@@ -273,32 +252,32 @@ contract SystemConfig_Setters_TestFail is SystemConfig_Init {
/// @dev Tests that `setBatcherHash` reverts if the caller is not the owner.
function test_setBatcherHash_notOwner_reverts() external {
vm.expectRevert("Ownable: caller is not the owner");
sysConf.setBatcherHash(bytes32(hex""));
systemConfig.setBatcherHash(bytes32(hex""));
}
/// @dev Tests that `setGasConfig` reverts if the caller is not the owner.
function test_setGasConfig_notOwner_reverts() external {
vm.expectRevert("Ownable: caller is not the owner");
sysConf.setGasConfig(0, 0);
systemConfig.setGasConfig(0, 0);
}
/// @dev Tests that `setGasLimit` reverts if the caller is not the owner.
function test_setGasLimit_notOwner_reverts() external {
vm.expectRevert("Ownable: caller is not the owner");
sysConf.setGasLimit(0);
systemConfig.setGasLimit(0);
}
/// @dev Tests that `setUnsafeBlockSigner` reverts if the caller is not the owner.
function test_setUnsafeBlockSigner_notOwner_reverts() external {
vm.expectRevert("Ownable: caller is not the owner");
sysConf.setUnsafeBlockSigner(address(0x20));
systemConfig.setUnsafeBlockSigner(address(0x20));
}
/// @dev Tests that `setResourceConfig` reverts if the caller is not the owner.
function test_setResourceConfig_notOwner_reverts() external {
ResourceMetering.ResourceConfig memory config = Constants.DEFAULT_RESOURCE_CONFIG();
vm.expectRevert("Ownable: caller is not the owner");
sysConf.setResourceConfig(config);
systemConfig.setResourceConfig(config);
}
/// @dev Tests that `setResourceConfig` reverts if the min base fee
......@@ -312,9 +291,9 @@ contract SystemConfig_Setters_TestFail is SystemConfig_Init {
minimumBaseFee: 2 gwei,
maximumBaseFee: 1 gwei
});
vm.prank(sysConf.owner());
vm.prank(systemConfig.owner());
vm.expectRevert("SystemConfig: min base fee must be less than max base");
sysConf.setResourceConfig(config);
systemConfig.setResourceConfig(config);
}
/// @dev Tests that `setResourceConfig` reverts if the baseFeeMaxChangeDenominator
......@@ -328,14 +307,14 @@ contract SystemConfig_Setters_TestFail is SystemConfig_Init {
minimumBaseFee: 1 gwei,
maximumBaseFee: 2 gwei
});
vm.prank(sysConf.owner());
vm.prank(systemConfig.owner());
vm.expectRevert("SystemConfig: denominator must be larger than 1");
sysConf.setResourceConfig(config);
systemConfig.setResourceConfig(config);
}
/// @dev Tests that `setResourceConfig` reverts if the gas limit is too low.
function test_setResourceConfig_lowGasLimit_reverts() external {
uint64 gasLimit = sysConf.gasLimit();
uint64 gasLimit = systemConfig.gasLimit();
ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({
maxResourceLimit: uint32(gasLimit),
......@@ -345,9 +324,9 @@ contract SystemConfig_Setters_TestFail is SystemConfig_Init {
minimumBaseFee: 1 gwei,
maximumBaseFee: 2 gwei
});
vm.prank(sysConf.owner());
vm.prank(systemConfig.owner());
vm.expectRevert("SystemConfig: gas limit too low");
sysConf.setResourceConfig(config);
systemConfig.setResourceConfig(config);
}
/// @dev Tests that `setResourceConfig` reverts if the elasticity multiplier
......@@ -361,9 +340,9 @@ contract SystemConfig_Setters_TestFail is SystemConfig_Init {
minimumBaseFee: 1 gwei,
maximumBaseFee: 2 gwei
});
vm.prank(sysConf.owner());
vm.prank(systemConfig.owner());
vm.expectRevert("SystemConfig: precision loss with target resource limit");
sysConf.setResourceConfig(config);
systemConfig.setResourceConfig(config);
}
}
......@@ -373,9 +352,9 @@ contract SystemConfig_Setters_Test is SystemConfig_Init {
vm.expectEmit(true, true, true, true);
emit ConfigUpdate(0, SystemConfig.UpdateType.BATCHER, abi.encode(newBatcherHash));
vm.prank(sysConf.owner());
sysConf.setBatcherHash(newBatcherHash);
assertEq(sysConf.batcherHash(), newBatcherHash);
vm.prank(systemConfig.owner());
systemConfig.setBatcherHash(newBatcherHash);
assertEq(systemConfig.batcherHash(), newBatcherHash);
}
/// @dev Tests that `setGasConfig` updates the overhead and scalar successfully.
......@@ -383,23 +362,23 @@ contract SystemConfig_Setters_Test is SystemConfig_Init {
vm.expectEmit(true, true, true, true);
emit ConfigUpdate(0, SystemConfig.UpdateType.GAS_CONFIG, abi.encode(newOverhead, newScalar));
vm.prank(sysConf.owner());
sysConf.setGasConfig(newOverhead, newScalar);
assertEq(sysConf.overhead(), newOverhead);
assertEq(sysConf.scalar(), newScalar);
vm.prank(systemConfig.owner());
systemConfig.setGasConfig(newOverhead, newScalar);
assertEq(systemConfig.overhead(), newOverhead);
assertEq(systemConfig.scalar(), newScalar);
}
/// @dev Tests that `setGasLimit` updates the gas limit successfully.
function testFuzz_setGasLimit_succeeds(uint64 newGasLimit) external {
uint64 minimumGasLimit = sysConf.minimumGasLimit();
uint64 minimumGasLimit = systemConfig.minimumGasLimit();
newGasLimit = uint64(bound(uint256(newGasLimit), uint256(minimumGasLimit), uint256(type(uint64).max)));
vm.expectEmit(true, true, true, true);
emit ConfigUpdate(0, SystemConfig.UpdateType.GAS_LIMIT, abi.encode(newGasLimit));
vm.prank(sysConf.owner());
sysConf.setGasLimit(newGasLimit);
assertEq(sysConf.gasLimit(), newGasLimit);
vm.prank(systemConfig.owner());
systemConfig.setGasLimit(newGasLimit);
assertEq(systemConfig.gasLimit(), newGasLimit);
}
/// @dev Tests that `setUnsafeBlockSigner` updates the block signer successfully.
......@@ -407,8 +386,8 @@ contract SystemConfig_Setters_Test is SystemConfig_Init {
vm.expectEmit(true, true, true, true);
emit ConfigUpdate(0, SystemConfig.UpdateType.UNSAFE_BLOCK_SIGNER, abi.encode(newUnsafeSigner));
vm.prank(sysConf.owner());
sysConf.setUnsafeBlockSigner(newUnsafeSigner);
assertEq(sysConf.unsafeBlockSigner(), newUnsafeSigner);
vm.prank(systemConfig.owner());
systemConfig.setUnsafeBlockSigner(newUnsafeSigner);
assertEq(systemConfig.unsafeBlockSigner(), newUnsafeSigner);
}
}
......@@ -96,10 +96,10 @@ contract XDM_MinGasLimits is Messenger_Initializer {
super.setUp();
// Deploy a relay actor
actor = new RelayActor(op, L1Messenger, vm, doFail);
actor = new RelayActor(optimismPortal, l1CrossDomainMessenger, vm, doFail);
// Give the portal some ether to send to `relayMessage`
vm.deal(address(op), type(uint128).max);
vm.deal(address(optimismPortal), type(uint128).max);
// Target the `RelayActor` contract
targetContract(address(actor));
......@@ -138,9 +138,9 @@ contract XDM_MinGasLimits_Succeeds is XDM_MinGasLimits {
for (uint256 i = 0; i < length; ++i) {
bytes32 hash = actor.hashes(i);
// The message hash is set in the successfulMessages mapping
assertTrue(L1Messenger.successfulMessages(hash));
assertTrue(l1CrossDomainMessenger.successfulMessages(hash));
// The message hash is not set in the failedMessages mapping
assertFalse(L1Messenger.failedMessages(hash));
assertFalse(l1CrossDomainMessenger.failedMessages(hash));
}
assertFalse(actor.reverted());
}
......@@ -171,9 +171,9 @@ contract XDM_MinGasLimits_Reverts is XDM_MinGasLimits {
for (uint256 i = 0; i < length; ++i) {
bytes32 hash = actor.hashes(i);
// The message hash is not set in the successfulMessages mapping
assertFalse(L1Messenger.successfulMessages(hash));
assertFalse(l1CrossDomainMessenger.successfulMessages(hash));
// The message hash is set in the failedMessages mapping
assertTrue(L1Messenger.failedMessages(hash));
assertTrue(l1CrossDomainMessenger.failedMessages(hash));
}
assertFalse(actor.reverted());
}
......
......@@ -36,7 +36,7 @@ contract L2OutputOracle_MonotonicBlockNumIncrease_Invariant is L2OutputOracle_In
super.setUp();
// Create a proposer actor.
actor = new L2OutputOracle_Proposer(oracle, vm);
actor = new L2OutputOracle_Proposer(l2OutputOracle, vm);
// Set the target contract to the proposer actor.
targetContract(address(actor));
......@@ -57,6 +57,6 @@ contract L2OutputOracle_MonotonicBlockNumIncrease_Invariant is L2OutputOracle_In
/// correspond to a block number that is less than the current output.
function invariant_monotonicBlockNumIncrease() external {
// Assert that the block number of proposals must monotonically increase.
assertTrue(oracle.nextBlockNumber() >= oracle.latestBlockNumber());
assertTrue(l2OutputOracle.nextBlockNumber() >= l2OutputOracle.latestBlockNumber());
}
}
......@@ -109,18 +109,21 @@ contract OptimismPortal_Invariant_Harness is Portal_Initializer {
messagePasserStorageRoot: _storageRoot,
latestBlockhash: bytes32(uint256(0))
});
_proposedBlockNumber = oracle.nextBlockNumber();
_proposedOutputIndex = oracle.nextOutputIndex();
_proposedBlockNumber = l2OutputOracle.nextBlockNumber();
_proposedOutputIndex = l2OutputOracle.nextOutputIndex();
// Configure the oracle to return the output root we've prepared.
vm.warp(oracle.computeL2Timestamp(_proposedBlockNumber) + 1);
vm.prank(oracle.PROPOSER());
oracle.proposeL2Output(_outputRoot, _proposedBlockNumber, 0, 0);
vm.warp(l2OutputOracle.computeL2Timestamp(_proposedBlockNumber) + 1);
vm.prank(l2OutputOracle.PROPOSER());
l2OutputOracle.proposeL2Output(_outputRoot, _proposedBlockNumber, 0, 0);
// Warp beyond the finalization period for the block we've proposed.
vm.warp(oracle.getL2Output(_proposedOutputIndex).timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);
vm.warp(
l2OutputOracle.getL2Output(_proposedOutputIndex).timestamp + l2OutputOracle.FINALIZATION_PERIOD_SECONDS()
+ 1
);
// Fund the portal so that we can withdraw ETH.
vm.deal(address(op), 0xFFFFFFFF);
vm.deal(address(optimismPortal), 0xFFFFFFFF);
}
}
......@@ -130,7 +133,7 @@ contract OptimismPortal_Deposit_Invariant is Portal_Initializer {
function setUp() public override {
super.setUp();
// Create a deposit actor.
actor = new OptimismPortal_Depositor(vm, op);
actor = new OptimismPortal_Depositor(vm, optimismPortal);
targetContract(address(actor));
......@@ -155,12 +158,12 @@ contract OptimismPortal_CannotTimeTravel is OptimismPortal_Invariant_Harness {
super.setUp();
// Prove the withdrawal transaction
op.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof);
optimismPortal.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof);
// Set the target contract to the portal proxy
targetContract(address(op));
targetContract(address(optimismPortal));
// Exclude the proxy admin from the senders so that the proxy cannot be upgraded
excludeSender(EIP1967Helper.getAdmin(address(op)));
excludeSender(EIP1967Helper.getAdmin(address(optimismPortal)));
}
/// @custom:invariant `finalizeWithdrawalTransaction` should revert if the finalization
......@@ -170,7 +173,7 @@ contract OptimismPortal_CannotTimeTravel is OptimismPortal_Invariant_Harness {
/// until after the finalization period has elapsed.
function invariant_cannotFinalizeBeforePeriodHasPassed() external {
vm.expectRevert("OptimismPortal: proven withdrawal finalization period has not elapsed");
op.finalizeWithdrawalTransaction(_defaultTx);
optimismPortal.finalizeWithdrawalTransaction(_defaultTx);
}
}
......@@ -179,18 +182,18 @@ contract OptimismPortal_CannotFinalizeTwice is OptimismPortal_Invariant_Harness
super.setUp();
// Prove the withdrawal transaction
op.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof);
optimismPortal.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof);
// Warp past the finalization period.
vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);
vm.warp(block.timestamp + l2OutputOracle.FINALIZATION_PERIOD_SECONDS() + 1);
// Finalize the withdrawal transaction.
op.finalizeWithdrawalTransaction(_defaultTx);
optimismPortal.finalizeWithdrawalTransaction(_defaultTx);
// Set the target contract to the portal proxy
targetContract(address(op));
targetContract(address(optimismPortal));
// Exclude the proxy admin from the senders so that the proxy cannot be upgraded
excludeSender(EIP1967Helper.getAdmin(address(op)));
excludeSender(EIP1967Helper.getAdmin(address(optimismPortal)));
}
/// @custom:invariant `finalizeWithdrawalTransaction` should revert if the withdrawal
......@@ -200,7 +203,7 @@ contract OptimismPortal_CannotFinalizeTwice is OptimismPortal_Invariant_Harness
/// allows a withdrawal to be finalized twice.
function invariant_cannotFinalizeTwice() external {
vm.expectRevert("OptimismPortal: withdrawal has already been finalized");
op.finalizeWithdrawalTransaction(_defaultTx);
optimismPortal.finalizeWithdrawalTransaction(_defaultTx);
}
}
......@@ -209,15 +212,15 @@ contract OptimismPortal_CanAlwaysFinalizeAfterWindow is OptimismPortal_Invariant
super.setUp();
// Prove the withdrawal transaction
op.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof);
optimismPortal.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof);
// Warp past the finalization period.
vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);
vm.warp(block.timestamp + l2OutputOracle.FINALIZATION_PERIOD_SECONDS() + 1);
// Set the target contract to the portal proxy
targetContract(address(op));
targetContract(address(optimismPortal));
// Exclude the proxy admin from the senders so that the proxy cannot be upgraded
excludeSender(EIP1967Helper.getAdmin(address(op)));
excludeSender(EIP1967Helper.getAdmin(address(optimismPortal)));
}
/// @custom:invariant A withdrawal should **always** be able to be finalized
......@@ -230,7 +233,7 @@ contract OptimismPortal_CanAlwaysFinalizeAfterWindow is OptimismPortal_Invariant
function invariant_canAlwaysFinalize() external {
uint256 bobBalanceBefore = address(bob).balance;
op.finalizeWithdrawalTransaction(_defaultTx);
optimismPortal.finalizeWithdrawalTransaction(_defaultTx);
assertEq(address(bob).balance, bobBalanceBefore + _defaultTx.value);
}
......
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