From b1a61f870807d26c6bdcb31e54301cac8e3da573 Mon Sep 17 00:00:00 2001 From: 0xHansLee Date: Thu, 21 Mar 2024 18:18:30 +0900 Subject: [PATCH] feat(contracts): add withdrawTo to ValidatorPool contract --- packages/contracts/.gas-snapshot | 142 +++++++++--------- .../contracts/contracts/L1/ValidatorPool.sol | 15 ++ .../contracts/test/ValidatorPool.t.sol | 27 ++++ 3 files changed, 114 insertions(+), 70 deletions(-) diff --git a/packages/contracts/.gas-snapshot b/packages/contracts/.gas-snapshot index fcf04bb94..add80203f 100644 --- a/packages/contracts/.gas-snapshot +++ b/packages/contracts/.gas-snapshot @@ -1,42 +1,42 @@ ColosseumTest:test_bisect_cancelChallenge_succeeds() (gas: 2687669) -ColosseumTest:test_bisect_finalizedOutput_reverts() (gas: 461794) -ColosseumTest:test_bisect_ifNotYourTurn_reverts() (gas: 458937) -ColosseumTest:test_bisect_succeeds() (gas: 435043) -ColosseumTest:test_bisect_whenAsserterTimedOut_reverts() (gas: 461404) -ColosseumTest:test_bisect_whenChallengerTimedOut_reverts() (gas: 457310) -ColosseumTest:test_bisect_withBadSegments_reverts() (gas: 483055) +ColosseumTest:test_bisect_finalizedOutput_reverts() (gas: 461816) +ColosseumTest:test_bisect_ifNotYourTurn_reverts() (gas: 458959) +ColosseumTest:test_bisect_succeeds() (gas: 435065) +ColosseumTest:test_bisect_whenAsserterTimedOut_reverts() (gas: 461426) +ColosseumTest:test_bisect_whenChallengerTimedOut_reverts() (gas: 457332) +ColosseumTest:test_bisect_withBadSegments_reverts() (gas: 483077) ColosseumTest:test_cancelChallenge_noChallenge_reverts() (gas: 15895) -ColosseumTest:test_cancelChallenge_outputNotDeleted_reverts() (gas: 444331) -ColosseumTest:test_cancelChallenge_senderNotChallenger_reverts() (gas: 2901973) +ColosseumTest:test_cancelChallenge_outputNotDeleted_reverts() (gas: 444353) +ColosseumTest:test_cancelChallenge_senderNotChallenger_reverts() (gas: 2902017) ColosseumTest:test_cancelChallenge_succeeds() (gas: 2647224) -ColosseumTest:test_cancelChallenge_whenChallengerTimedOut_reverts() (gas: 2899033) -ColosseumTest:test_challengerNotCloseWhenAsserterTimeout_succeeds() (gas: 452940) -ColosseumTest:test_challengerTimeout_succeeds() (gas: 431276) +ColosseumTest:test_cancelChallenge_whenChallengerTimedOut_reverts() (gas: 2899077) +ColosseumTest:test_challengerNotCloseWhenAsserterTimeout_succeeds() (gas: 452962) +ColosseumTest:test_challengerTimeout_succeeds() (gas: 431293) ColosseumTest:test_constructor() (gas: 22387) -ColosseumTest:test_createChallenge_afterChallengeProven_reverts() (gas: 2423164) -ColosseumTest:test_createChallenge_afterChallengerTimedOut_succeeds() (gas: 711740) +ColosseumTest:test_createChallenge_afterChallengeProven_reverts() (gas: 2423186) +ColosseumTest:test_createChallenge_afterChallengerTimedOut_succeeds() (gas: 711775) ColosseumTest:test_createChallenge_afterCreationPeriod_reverts() (gas: 46712) -ColosseumTest:test_createChallenge_afterDismissed_succeeds() (gas: 2777857) +ColosseumTest:test_createChallenge_afterDismissed_succeeds() (gas: 2777901) ColosseumTest:test_createChallenge_asAsserter_reverts() (gas: 47544) -ColosseumTest:test_createChallenge_existedChallenge_reverts() (gas: 450082) +ColosseumTest:test_createChallenge_existedChallenge_reverts() (gas: 450104) ColosseumTest:test_createChallenge_finalizedOutput_reverts() (gas: 46428) ColosseumTest:test_createChallenge_genesisOutput_reverts() (gas: 33901) ColosseumTest:test_createChallenge_notSubmittedOutput_reverts() (gas: 33407) -ColosseumTest:test_createChallenge_otherChallenger_succeeds() (gas: 855369) -ColosseumTest:test_createChallenge_succeeds() (gas: 437709) +ColosseumTest:test_createChallenge_otherChallenger_succeeds() (gas: 855413) +ColosseumTest:test_createChallenge_succeeds() (gas: 437731) ColosseumTest:test_createChallenge_withBadSegments_reverts() (gas: 112613) ColosseumTest:test_createChallenge_wrongFork_reverts() (gas: 45197) -ColosseumTest:test_dismissChallenge_notSecurityCouncil_reverts() (gas: 2415060) +ColosseumTest:test_dismissChallenge_notSecurityCouncil_reverts() (gas: 2415082) ColosseumTest:test_dismissChallenge_outputNotDeleted_reverts() (gas: 16395) -ColosseumTest:test_dismissChallenge_succeeds() (gas: 2429904) -ColosseumTest:test_forceDeleteOutput_alreadyDeletedOutput_reverts() (gas: 590401) -ColosseumTest:test_forceDeleteOutput_finalizedOutput_reverts() (gas: 579654) +ColosseumTest:test_dismissChallenge_succeeds() (gas: 2429926) +ColosseumTest:test_forceDeleteOutput_alreadyDeletedOutput_reverts() (gas: 590423) +ColosseumTest:test_forceDeleteOutput_finalizedOutput_reverts() (gas: 579676) ColosseumTest:test_forceDeleteOutput_notSecurityCouncil_reverts() (gas: 15991) -ColosseumTest:test_forceDeleteOutput_succeeds() (gas: 584014) +ColosseumTest:test_forceDeleteOutput_succeeds() (gas: 584036) ColosseumTest:test_isInCreationPeriod_succeeds() (gas: 43125) ColosseumTest:test_proveFault_cancelChallenge_succeeds() (gas: 2862418) -ColosseumTest:test_proveFault_finalizedOutput_reverts() (gas: 653263) -ColosseumTest:test_proveFault_succeeds() (gas: 2410912) +ColosseumTest:test_proveFault_finalizedOutput_reverts() (gas: 653285) +ColosseumTest:test_proveFault_succeeds() (gas: 2410934) CrossDomainMessenger_BaseGas_Test:test_baseGas_succeeds() (gas: 11763) CrossDomainOwnable2_Test:test_onlyOwner_notMessenger_reverts() (gas: 8451) CrossDomainOwnable2_Test:test_onlyOwner_notOwner2_reverts() (gas: 57515) @@ -72,7 +72,7 @@ GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_1() (gas: 4031 GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_0() (gas: 421662) GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_1() (gas: 3467561) GasBenchMark_L1StandardBridge_Finalize:test_finalizeBridgeETH_benchmark() (gas: 32274) -GasBenchMark_L2OutputOracle:test_submitL2Output_benchmark() (gas: 155604) +GasBenchMark_L2OutputOracle:test_submitL2Output_benchmark() (gas: 155626) GasPriceOracle_Test:test_baseFee_succeeds() (gas: 8325) GasPriceOracle_Test:test_decimals_succeeds() (gas: 5419) GasPriceOracle_Test:test_gasPrice_succeeds() (gas: 8294) @@ -130,7 +130,7 @@ KromaPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_timestamp KromaPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_onInvalidOutputRootProof_reverts() (gas: 101136) KromaPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_onSelfCall_reverts() (gas: 66247) KromaPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_paused_reverts() (gas: 87066) -KromaPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_replayProveChangedOutputRootAndOutputIndex_succeeds() (gas: 647451) +KromaPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_replayProveChangedOutputRootAndOutputIndex_succeeds() (gas: 647473) KromaPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_replayProveChangedOutputRoot_succeeds() (gas: 449354) KromaPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_replayProve_reverts() (gas: 288788) KromaPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_validWithdrawalProof_succeeds() (gas: 274724) @@ -145,7 +145,7 @@ KromaPortal_Test:test_depositTransaction_withEthValueAndContractContractCreation KromaPortal_Test:test_depositTransaction_withEthValueAndEOAContractCreation_succeeds() (gas: 75981) KromaPortal_Test:test_depositTransaction_withEthValueFromContract_succeeds() (gas: 83505) KromaPortal_Test:test_depositTransaction_withEthValueFromEOA_succeeds() (gas: 84111) -KromaPortal_Test:test_isOutputFinalized_succeeds() (gas: 194612) +KromaPortal_Test:test_isOutputFinalized_succeeds() (gas: 194634) KromaPortal_Test:test_pause_onlyGuardian_reverts() (gas: 22340) KromaPortal_Test:test_pause_succeeds() (gas: 42359) KromaPortal_Test:test_receive_succeeds() (gas: 127638) @@ -230,26 +230,26 @@ L2OutputOracleTest:test_constructor_badTimestamp_reverts() (gas: 71011) L2OutputOracleTest:test_constructor_l2BlockTimeZero_reverts() (gas: 45978) L2OutputOracleTest:test_constructor_submissionInterval_reverts() (gas: 46013) L2OutputOracleTest:test_constructor_succeeds() (gas: 34075) -L2OutputOracleTest:test_getL2OutputIndexAfter_multipleOutputsExist_succeeds() (gas: 496345) +L2OutputOracleTest:test_getL2OutputIndexAfter_multipleOutputsExist_succeeds() (gas: 496433) L2OutputOracleTest:test_getL2OutputIndexAfter_noOutputsExist_reverts() (gas: 17939) -L2OutputOracleTest:test_getL2OutputIndexAfter_previousBlock_succeeds() (gas: 166640) -L2OutputOracleTest:test_getL2OutputIndexAfter_sameBlock_succeeds() (gas: 166548) -L2OutputOracleTest:test_getL2Output_succeeds() (gas: 173572) -L2OutputOracleTest:test_latestBlockNumber_succeeds() (gas: 167546) -L2OutputOracleTest:test_nextBlockNumber_succeeds() (gas: 185158) -L2OutputOracleTest:test_replaceL2Output_finalized_reverts() (gas: 187325) +L2OutputOracleTest:test_getL2OutputIndexAfter_previousBlock_succeeds() (gas: 166662) +L2OutputOracleTest:test_getL2OutputIndexAfter_sameBlock_succeeds() (gas: 166570) +L2OutputOracleTest:test_getL2Output_succeeds() (gas: 173594) +L2OutputOracleTest:test_latestBlockNumber_succeeds() (gas: 167568) +L2OutputOracleTest:test_nextBlockNumber_succeeds() (gas: 185180) +L2OutputOracleTest:test_replaceL2Output_finalized_reverts() (gas: 187347) L2OutputOracleTest:test_replaceL2Output_ifNotChallenger_reverts() (gas: 19404) -L2OutputOracleTest:test_replaceL2Output_nonExistent_reverts() (gas: 185608) -L2OutputOracleTest:test_replaceL2Output_succeeds() (gas: 430979) +L2OutputOracleTest:test_replaceL2Output_nonExistent_reverts() (gas: 185630) +L2OutputOracleTest:test_replaceL2Output_succeeds() (gas: 431045) L2OutputOracleTest:test_replaceL2Output_zeroAddress_reverts() (gas: 21823) -L2OutputOracleTest:test_submitL2Output_emptyOutput_reverts() (gas: 37178) -L2OutputOracleTest:test_submitL2Output_futureTimetamp_reverts() (gas: 39165) -L2OutputOracleTest:test_submitL2Output_notValidator_reverts() (gas: 36208) -L2OutputOracleTest:test_submitL2Output_submitAnotherOutput_succeeds() (gas: 176782) -L2OutputOracleTest:test_submitL2Output_unexpectedBlockNumber_reverts() (gas: 38875) -L2OutputOracleTest:test_submitL2Output_unmatchedBlockhash_reverts() (gas: 39974) -L2OutputOracleTest:test_submitL2Output_wrongFork_reverts() (gas: 39513) -L2OutputOracleTest:test_submitWithBlockhashAndHeight_succeeds() (gas: 165845) +L2OutputOracleTest:test_submitL2Output_emptyOutput_reverts() (gas: 37200) +L2OutputOracleTest:test_submitL2Output_futureTimetamp_reverts() (gas: 39187) +L2OutputOracleTest:test_submitL2Output_notValidator_reverts() (gas: 36230) +L2OutputOracleTest:test_submitL2Output_submitAnotherOutput_succeeds() (gas: 176804) +L2OutputOracleTest:test_submitL2Output_unexpectedBlockNumber_reverts() (gas: 38897) +L2OutputOracleTest:test_submitL2Output_unmatchedBlockhash_reverts() (gas: 39996) +L2OutputOracleTest:test_submitL2Output_wrongFork_reverts() (gas: 39535) +L2OutputOracleTest:test_submitWithBlockhashAndHeight_succeeds() (gas: 165867) L2OutputOracleUpgradeable_Test:test_initValuesOnProxy_succeeds() (gas: 33444) L2OutputOracleUpgradeable_Test:test_initializeImpl_alreadyInitialized_reverts() (gas: 15167) L2OutputOracleUpgradeable_Test:test_initializeProxy_alreadyInitialized_reverts() (gas: 20105) @@ -347,38 +347,40 @@ UpgradeGovernorTest:test_initialize_succeeds() (gas: 85053) UpgradeGovernorTest:test_queueProposal_succeeds() (gas: 280037) UpgradeGovernorTest:test_voteProposal_overPeriod_reverts() (gas: 152674) UpgradeGovernorTest:test_voteProposal_succeeds() (gas: 198054) -ValidatorPoolTest:test_addPendingBond_insufficientBalances_reverts() (gas: 298263) -ValidatorPoolTest:test_addPendingBond_noBond_reverts() (gas: 29891) -ValidatorPoolTest:test_addPendingBond_succeeds() (gas: 367828) +ValidatorPoolTest:test_addPendingBond_insufficientBalances_reverts() (gas: 298307) +ValidatorPoolTest:test_addPendingBond_noBond_reverts() (gas: 29935) +ValidatorPoolTest:test_addPendingBond_succeeds() (gas: 367864) ValidatorPoolTest:test_balanceOf_succeeds() (gas: 57635) -ValidatorPoolTest:test_constructor_succeeds() (gas: 26374) +ValidatorPoolTest:test_constructor_succeeds() (gas: 26460) ValidatorPoolTest:test_createBond_existsBond_reverts() (gas: 366588) -ValidatorPoolTest:test_createBond_insufficientBalances_reverts() (gas: 138970) -ValidatorPoolTest:test_createBond_senderNotL2OO_reverts() (gas: 190089) -ValidatorPoolTest:test_createBond_succeeds() (gas: 287483) -ValidatorPoolTest:test_createBond_unbondBefore_succeeds() (gas: 512103) -ValidatorPoolTest:test_deposit_alreadyValidator_succeeds() (gas: 207074) +ValidatorPoolTest:test_createBond_insufficientBalances_reverts() (gas: 138992) +ValidatorPoolTest:test_createBond_senderNotL2OO_reverts() (gas: 190067) +ValidatorPoolTest:test_createBond_succeeds() (gas: 287505) +ValidatorPoolTest:test_createBond_unbondBefore_succeeds() (gas: 512147) +ValidatorPoolTest:test_deposit_alreadyValidator_succeeds() (gas: 207096) ValidatorPoolTest:test_deposit_insufficientBalances_reverts() (gas: 19815) ValidatorPoolTest:test_deposit_succeeds() (gas: 185466) -ValidatorPoolTest:test_getBond_noBond_reverts() (gas: 16887) -ValidatorPoolTest:test_getBond_succeeds() (gas: 291249) +ValidatorPoolTest:test_getBond_noBond_reverts() (gas: 16932) +ValidatorPoolTest:test_getBond_succeeds() (gas: 291271) ValidatorPoolTest:test_increaseBond_noBond_reverts() (gas: 29978) -ValidatorPoolTest:test_increaseBond_noPendingBond_reverts() (gas: 296996) -ValidatorPoolTest:test_increaseBond_succeeds() (gas: 406081) -ValidatorPoolTest:test_isValidator_succeeds() (gas: 139365) -ValidatorPoolTest:test_nextValidator_succeeds() (gas: 1429408) -ValidatorPoolTest:test_releasePendingBond_noPendingBond_succeeds() (gas: 30126) -ValidatorPoolTest:test_releasePendingBond_succeeds() (gas: 431240) -ValidatorPoolTest:test_securityCouncilCannotBeValidator_succeeds() (gas: 51167) -ValidatorPoolTest:test_unbond_maxUnbond_succeeds() (gas: 483446) -ValidatorPoolTest:test_unbond_multipleBonds_succeeds() (gas: 394014) -ValidatorPoolTest:test_unbond_noBond_reverts() (gas: 18106) -ValidatorPoolTest:test_unbond_notExpired_reverts() (gas: 289813) -ValidatorPoolTest:test_unbond_succeeds() (gas: 383051) +ValidatorPoolTest:test_increaseBond_noPendingBond_reverts() (gas: 297018) +ValidatorPoolTest:test_increaseBond_succeeds() (gas: 406152) +ValidatorPoolTest:test_isValidator_succeeds() (gas: 139343) +ValidatorPoolTest:test_nextValidator_succeeds() (gas: 1429716) +ValidatorPoolTest:test_releasePendingBond_noPendingBond_succeeds() (gas: 30060) +ValidatorPoolTest:test_releasePendingBond_succeeds() (gas: 431258) +ValidatorPoolTest:test_securityCouncilCannotBeValidator_succeeds() (gas: 51211) +ValidatorPoolTest:test_unbond_maxUnbond_succeeds() (gas: 483534) +ValidatorPoolTest:test_unbond_multipleBonds_succeeds() (gas: 394058) +ValidatorPoolTest:test_unbond_noBond_reverts() (gas: 18083) +ValidatorPoolTest:test_unbond_notExpired_reverts() (gas: 289902) +ValidatorPoolTest:test_unbond_succeeds() (gas: 383073) ValidatorPoolTest:test_validatorCount_succeeds() (gas: 208556) -ValidatorPoolTest:test_withdraw_all_succeeds() (gas: 167278) -ValidatorPoolTest:test_withdraw_loseValidatorEligibility_succeeds() (gas: 171832) -ValidatorPoolTest:test_withdraw_maintainValidatorEligibility_succeeds() (gas: 119400) +ValidatorPoolTest:test_withdraw_all_succeeds() (gas: 167313) +ValidatorPoolTest:test_withdraw_loseValidatorEligibility_succeeds() (gas: 171876) +ValidatorPoolTest:test_withdraw_maintainValidatorEligibility_succeeds() (gas: 119422) +ValidatorPoolTest:test_withdraw_to_succeeds() (gas: 167576) +ValidatorPoolTest:test_withdraw_to_zero_address_reverts() (gas: 197802) ValidatorRewardVault_Test:test_balanceOf_succeeds() (gas: 42735) ValidatorRewardVault_Test:test_constructor_succeeds() (gas: 11335) ValidatorRewardVault_Test:test_minWithdrawalAmount_succeeds() (gas: 5498) diff --git a/packages/contracts/contracts/L1/ValidatorPool.sol b/packages/contracts/contracts/L1/ValidatorPool.sol index e4e1d0a3f..afe034017 100644 --- a/packages/contracts/contracts/L1/ValidatorPool.sol +++ b/packages/contracts/contracts/L1/ValidatorPool.sol @@ -237,6 +237,21 @@ contract ValidatorPool is ReentrancyGuardUpgradeable, ISemver { require(success, "ValidatorPool: ETH transfer failed"); } + /** + * @notice Withdraw a given amount. + * + * @param _to Address to withdraw asset to. + * @param _amount Amount to withdraw. + */ + function withdrawTo(address _to, uint256 _amount) external nonReentrant { + require(_to != address(0), "ValidatorPool: cannot withdraw to the zero address"); + + _decreaseBalance(msg.sender, _amount); + + bool success = SafeCall.call(_to, gasleft(), _amount, ""); + require(success, "ValidatorPool: ETH transfer failed"); + } + /** * @notice Bond asset corresponding to the given output index. * This function is called when submitting output. diff --git a/packages/contracts/contracts/test/ValidatorPool.t.sol b/packages/contracts/contracts/test/ValidatorPool.t.sol index 22a4dcfc6..219aced33 100644 --- a/packages/contracts/contracts/test/ValidatorPool.t.sol +++ b/packages/contracts/contracts/test/ValidatorPool.t.sol @@ -161,6 +161,33 @@ contract ValidatorPoolTest is L2OutputOracle_Initializer { assertEq(pool.validatorCount(), count - 1); } + function test_withdraw_to_succeeds() external { + test_deposit_succeeds(); + + address nextValidator = pool.nextValidator(); + uint256 deposits = pool.balanceOf(nextValidator); + + uint256 prevNextValidatorBalance = nextValidator.balance; + uint256 prevChallengerBalance = challenger.balance; + + vm.prank(nextValidator); + pool.withdrawTo(challenger, deposits); + assertEq(pool.balanceOf(nextValidator), 0); + assertEq(nextValidator.balance, prevNextValidatorBalance); + assertEq(challenger.balance, prevChallengerBalance + deposits); + } + + function test_withdraw_to_zero_address_reverts() external { + test_deposit_succeeds(); + + address nextValidator = pool.nextValidator(); + uint256 deposits = pool.balanceOf(nextValidator); + + vm.prank(nextValidator); + vm.expectRevert("ValidatorPool: cannot withdraw to the zero address"); + pool.withdrawTo(address(0), deposits); + } + function test_withdraw_maintainValidatorEligibility_succeeds() external { uint256 trustedBalance = trusted.balance; uint256 depositAmount = requiredBondAmount * 2;