From 6752b45c9ac8addb0419453a9bdbb1d6edadb6ff Mon Sep 17 00:00:00 2001 From: Nikita P Date: Thu, 7 Aug 2025 10:20:13 +0300 Subject: [PATCH 01/28] Revert "Revert "HOODI - CSM v2 + Triggerable Withdrawals"" --- .../scripts/vote_dg_easy_track_tw_holesky.py | 105 + archive/scripts/vote_tw_csm2_holesky.py | 722 ++++ archive/scripts/vote_tw_csm2_hoodi.py | 901 +++++ .../vote_update_sandbox_impl_holesky.py | 102 + .../scripts/vote_update_sandbox_impl_hoodi.py | 105 + .../test_vote_dg_easy_track_tw_holesky.py | 78 + archive/tests/test_vote_tw_csm2_holesky.py | 938 ++++++ archive/tests/test_vote_tw_csm2_hoodi.py | 1062 ++++++ .../test_vote_update_sandbox_impl_holesky.py | 137 + .../test_vote_update_sandbox_impl_hoodi.py | 179 + configs/config_holesky.py | 25 +- configs/config_hoodi.py | 84 +- interfaces/AccountingOracle.json | 28 +- interfaces/CSAccounting.json | 1 + interfaces/{csm => }/CSEarlyAdoption.json | 0 interfaces/CSEjector.json | 1 + interfaces/CSExitPenalties.json | 1 + interfaces/CSFeeDistributor.json | 1 + interfaces/CSFeeOracle.json | 1 + interfaces/CSHashConsensus.json | 1 + interfaces/CSModule.json | 1 + interfaces/CSPermissionlessGate.json | 1 + interfaces/CSStrikes.json | 1 + interfaces/{csm => }/CSVerifier.json | 0 interfaces/CSVerifierV2.json | 1 + interfaces/CSVettedGate.json | 1 + interfaces/NodeOperatorsRegistry.json | 322 +- interfaces/Sandbox.json | 1735 +++++++++- interfaces/SimpleDVT.json | 322 +- interfaces/StakingRouter.json | 129 +- interfaces/TriggerableWithdrawalsGateway.json | 703 ++++ interfaces/ValidatorExitVerifier.json | 1 + interfaces/ValidatorsExitBusOracle.json | 1642 ++++++++- interfaces/WithdrawalVault.json | 372 +- interfaces/WithdrawalsManagerProxy.json | 81 + interfaces/csm/CSAccounting.json | 2299 ------------- interfaces/csm/CSFeeDistributor.json | 849 ----- interfaces/csm/CSFeeOracle.json | 1381 -------- interfaces/csm/CSHashConsensus.json | 1141 ------- interfaces/csm/CSModule.json | 2986 ----------------- utils/agent.py | 13 +- utils/config.py | 35 +- .../test/event_validators/dual_governance.py | 21 +- 43 files changed, 9538 insertions(+), 8971 deletions(-) create mode 100644 archive/scripts/vote_dg_easy_track_tw_holesky.py create mode 100644 archive/scripts/vote_tw_csm2_holesky.py create mode 100644 archive/scripts/vote_tw_csm2_hoodi.py create mode 100644 archive/scripts/vote_update_sandbox_impl_holesky.py create mode 100644 archive/scripts/vote_update_sandbox_impl_hoodi.py create mode 100644 archive/tests/test_vote_dg_easy_track_tw_holesky.py create mode 100644 archive/tests/test_vote_tw_csm2_holesky.py create mode 100644 archive/tests/test_vote_tw_csm2_hoodi.py create mode 100644 archive/tests/test_vote_update_sandbox_impl_holesky.py create mode 100644 archive/tests/test_vote_update_sandbox_impl_hoodi.py create mode 100644 interfaces/CSAccounting.json rename interfaces/{csm => }/CSEarlyAdoption.json (100%) create mode 100644 interfaces/CSEjector.json create mode 100644 interfaces/CSExitPenalties.json create mode 100644 interfaces/CSFeeDistributor.json create mode 100644 interfaces/CSFeeOracle.json create mode 100644 interfaces/CSHashConsensus.json create mode 100644 interfaces/CSModule.json create mode 100644 interfaces/CSPermissionlessGate.json create mode 100644 interfaces/CSStrikes.json rename interfaces/{csm => }/CSVerifier.json (100%) create mode 100644 interfaces/CSVerifierV2.json create mode 100644 interfaces/CSVettedGate.json create mode 100644 interfaces/TriggerableWithdrawalsGateway.json create mode 100644 interfaces/ValidatorExitVerifier.json create mode 100644 interfaces/WithdrawalsManagerProxy.json delete mode 100644 interfaces/csm/CSAccounting.json delete mode 100644 interfaces/csm/CSFeeDistributor.json delete mode 100644 interfaces/csm/CSFeeOracle.json delete mode 100644 interfaces/csm/CSHashConsensus.json delete mode 100644 interfaces/csm/CSModule.json diff --git a/archive/scripts/vote_dg_easy_track_tw_holesky.py b/archive/scripts/vote_dg_easy_track_tw_holesky.py new file mode 100644 index 000000000..bf54075b3 --- /dev/null +++ b/archive/scripts/vote_dg_easy_track_tw_holesky.py @@ -0,0 +1,105 @@ +""" +Vote XX/06/2025 [HOLESKY] + +1. Grant SUBMIT_REPORT_HASH_ROLE role to the EasyTrack EVM Script Executor +2. Connect TRIGGERABLE_WITHDRAWALS_GATEWAY to Dual Governance tiebreaker +3. Add `SubmitValidatorsExitRequestHashes` (SDVT) EVM script factory to Easy Track +4. Add `SubmitValidatorsExitRequestHashes` (Curated Module) EVM script factory to Easy Track +""" +import time + +from typing import Any, Dict +from typing import Tuple, Optional +from utils.config import ( + AGENT, + contracts, + get_deployer_account, + get_priority_fee, + get_is_live +) +from utils.dg_decorators import forward_agent, forward_dg_admin, forward_voting, process_voting_items +from utils.ipfs import upload_vote_ipfs_description, calculate_vote_ipfs_description +from utils.voting import confirm_vote_script, create_vote, bake_vote_items +from utils.permissions import encode_oz_grant_role +from utils.easy_track import ( + add_evmscript_factory, + create_permissions, +) +from typing import Optional, Tuple, Dict +from utils.config import contracts + + + +TRIGGERABLE_WITHDRAWALS_GATEWAY = "0x4FD4113f2B92856B59BC3be77f2943B7F4eaa9a5" + +EASYTRACK_EVMSCRIPT_EXECUTOR = "0x2819B65021E13CEEB9AC33E77DB32c7e64e7520D" + +EASYTRACK_SDVT_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY = "0x4aB23f409F8F6EdeF321C735e941E4670804a1B4" +EASYTRACK_CURATED_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY = "0x7A1c5af4625dc1160a7c67d00335B6Ad492bE53f" + +DESCRIPTION = "Add Triggerable Withdrawals Gateway to Dual Governance and new Easy Tracks (HOLESKY)" + +def start_vote(tx_params: Dict[str, str], silent: bool) -> Tuple[int, Optional[Any]]: + voting_unprepared_items = [ + ( + f"Grant SUBMIT_REPORT_HASH_ROLE on Validator Exit Bus Oracle to the EasyTrack EVM Script Executor", + forward_agent( + *encode_oz_grant_role( + contract=contracts.validators_exit_bus_oracle, + role_name="SUBMIT_REPORT_HASH_ROLE", + grant_to=EASYTRACK_EVMSCRIPT_EXECUTOR, + ), + ), + ), + ( + "Connect TRIGGERABLE_WITHDRAWALS_GATEWAY to Dual Governance tiebreaker", + forward_dg_admin( + contracts.dual_governance.address, + contracts.dual_governance.addTiebreakerSealableWithdrawalBlocker.encode_input( + TRIGGERABLE_WITHDRAWALS_GATEWAY + ), + ) + ), + ( + f"Add `SubmitValidatorsExitRequestHashes` (SDVT) EVM script factory with address `{EASYTRACK_SDVT_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY}` to Easy Track `{contracts.easy_track.address}`", + forward_voting( + *add_evmscript_factory( + factory=EASYTRACK_SDVT_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY, + permissions=(create_permissions(contracts.validators_exit_bus_oracle, "submitExitRequestsHash")), + ) + ) + ), + ( + f"Add `SubmitValidatorsExitRequestHashes` (Curated Module) EVM script factory with address `{EASYTRACK_CURATED_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY}` to Easy Track `{contracts.easy_track.address}`", + forward_voting( + *add_evmscript_factory( + factory=EASYTRACK_CURATED_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY, + permissions=(create_permissions(contracts.validators_exit_bus_oracle, "submitExitRequestsHash")), + ) + ) + ) + ] + + if silent: + desc_ipfs = calculate_vote_ipfs_description(DESCRIPTION) + else: + desc_ipfs = upload_vote_ipfs_description(DESCRIPTION) + + + vote_items = process_voting_items(voting_unprepared_items) + assert confirm_vote_script(vote_items, silent, desc_ipfs) + + return create_vote(vote_items, tx_params, desc_ipfs=desc_ipfs) + + + +def main(): + tx_params = {"from": get_deployer_account()} + if get_is_live(): + tx_params["priority_fee"] = get_priority_fee() + + vote_id, _ = start_vote(tx_params=tx_params, silent=False) + + vote_id >= 0 and print(f"Vote created: {vote_id}.") + + time.sleep(5) # hack for waiting thread #2. diff --git a/archive/scripts/vote_tw_csm2_holesky.py b/archive/scripts/vote_tw_csm2_holesky.py new file mode 100644 index 000000000..d05351b79 --- /dev/null +++ b/archive/scripts/vote_tw_csm2_holesky.py @@ -0,0 +1,722 @@ +""" +Vote XX/06/2025 [HOLESKY] + +--- Locator +1. Update locator implementation +--- VEB +2. Update VEBO implementation +3. Call finalizeUpgrade_v2(maxValidatorsPerReport, maxExitRequestsLimit, exitsPerFrame, frameDurationInSec) on VEBO +4. Grant VEBO role MANAGE_CONSENSUS_VERSION_ROLE to the AGENT +5. Bump VEBO consensus version to `4` +6. Revoke VEBO role MANAGE_CONSENSUS_VERSION_ROLE from the AGENT +--- Triggerable Withdrawals Gateway (TWG) +7. Grant TWG role ADD_FULL_WITHDRAWAL_REQUEST_ROLE to the CS Ejector +8. Grant TWG role ADD_FULL_WITHDRAWAL_REQUEST_ROLE to the VEB +--- WV +9. Update WithdrawalVault implementation +10. Call finalizeUpgrade_v2() on WithdrawalVault +--- AO +11. Update Accounting Oracle implementation +12. Grant AO MANAGE_CONSENSUS_VERSION_ROLE to the AGENT +13. Bump AO consensus version to `4` +14. Revoke AO MANAGE_CONSENSUS_VERSION_ROLE from the AGENT +--- SR +15. Update SR implementation +16. Grant SR role REPORT_VALIDATOR_EXITING_STATUS_ROLE to ValidatorExitVerifier +17. Grant SR role REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE to TWG +--- NOR +18. Grant APP_MANAGER_ROLE role to the AGENT on Kernel +19. Update `NodeOperatorsRegistry` implementation +20. Call finalizeUpgrade_v4 on NOR +--- sDVT +21. Update `SimpleDVT` implementation +22. Call finalizeUpgrade_v4 on sDVT +23. Revoke APP_MANAGER_ROLE role from the AGENT on Kernel +--- Oracle configs --- +24. Grant CONFIG_MANAGER_ROLE role to the AGENT +25. Remove NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP variable from OracleDaemonConfig +26. Remove VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS variable from OracleDaemonConfig +27. Remove VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS variable from OracleDaemonConfig +28. Add EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS variable to OracleDaemonConfig +--- CSM --- +29. Upgrade CSM implementation on proxy +30. Call `finalizeUpgradeV2()` on CSM contract +31. Upgrade CSAccounting implementation on proxy +32. Call `finalizeUpgradeV2(bondCurves)` on CSAccounting contract +33. Upgrade CSFeeOracle implementation on proxy +34. Call `finalizeUpgradeV2(consensusVersion)` on CSFeeOracle contract +35. Upgrade CSFeeDistributor implementation on proxy +36. Call `finalizeUpgradeV2(admin)` on CSFeeDistributor contract +37. Revoke CSAccounting role SET_BOND_CURVE_ROLE from the CSM contract +38. Revoke CSAccounting role RESET_BOND_CURVE_ROLE from the CSM contract +39. Revoke CSAccounting role RESET_BOND_CURVE_ROLE from the CSM committee +40. Grant CSM role CREATE_NODE_OPERATOR_ROLE for the permissionless gate +41. Grant CSM role CREATE_NODE_OPERATOR_ROLE for the vetted gate +42. Grant CSAccounting role SET_BOND_CURVE_ROLE for the vetted gate +43. Revoke role VERIFIER_ROLE from the previous instance of the Verifier contract +44. Grant role VERIFIER_ROLE to the new instance of the Verifier contract +45. Revoke CSM role PAUSE_ROLE from the previous GateSeal instance +46. Revoke CSAccounting role PAUSE_ROLE from the previous GateSeal instance +47. Revoke CSFeeOracle role PAUSE_ROLE from the previous GateSeal instance +48. Grant CSM role PAUSE_ROLE for the new GateSeal instance +49. Grant CSAccounting role PAUSE_ROLE for the new GateSeal instance +50. Grant CSFeeOracle role PAUSE_ROLE for the new GateSeal instance +51. Grant MANAGE_BOND_CURVES_ROLE to the AGENT +52. Add Identified Community Stakers Gate Bond Curve +53. Revoke MANAGE_BOND_CURVES_ROLE from the AGENT +54. Increase CSM share in Staking Router from 15% to 20% +--- Gate Seals --- +55. Revoke PAUSE_ROLE on WithdrawalQueue from the old GateSeal +56. Revoke PAUSE_ROLE on ValidatorsExitBusOracle from the old GateSeal +57. Grant PAUSE_ROLE on WithdrawalQueue to the new WithdrawalQueue GateSeal +58. Grant PAUSE_ROLE on ValidatorsExitBusOracle to the new Triggerable Withdrawals GateSeal +59. Grant PAUSE_ROLE on TriggerableWithdrawalsGateway to the new Triggerable Withdrawals GateSeal +--- ResealManager --- +60. Grant PAUSE_ROLE on TriggerableWithdrawalsGateway to ResealManager +61. Grant RESUME_ROLE on TriggerableWithdrawalsGateway to ResealManager +62. Call finalizeUpgrade_v3 on AO contract (TODO: move to beginning of the vote in Hoodi script) +63. Add CSSetVettedGateTree factory to EasyTrack with permissions +""" +import time + +from typing import TYPE_CHECKING, Any, Dict +from typing import Tuple, Optional, Sequence +from brownie import interface, web3, convert, ZERO_ADDRESS # type: ignore +from utils.config import ( + CSM_COMMITTEE_MS, + CS_MODULE_ID, + CS_MODULE_MODULE_FEE_BP, + CS_MODULE_TREASURY_FEE_BP, + CS_MODULE_MAX_DEPOSITS_PER_BLOCK, + CS_MODULE_MIN_DEPOSIT_BLOCK_DISTANCE, + CS_GATE_SEAL_ADDRESS, + NODE_OPERATORS_REGISTRY_ARAGON_APP_ID, + SIMPLE_DVT_ARAGON_APP_ID, + ARAGON_KERNEL, + AGENT, + contracts, +) +from utils.ipfs import upload_vote_ipfs_description, calculate_vote_ipfs_description +from utils.permissions import encode_oz_grant_role, encode_oz_revoke_role +from utils.easy_track import ( + add_evmscript_factory, + create_permissions, +) +from utils.agent import dual_governance_agent_forward +from utils.voting import confirm_vote_script, create_vote +from utils.config import get_deployer_account, get_priority_fee, get_is_live + +DESCRIPTION = "Triggerable withdrawals and CSM v2 upgrade voting (HOLESKY)" + +# New core contracts implementations +LIDO_LOCATOR_IMPL = "0xa437ab5614033d071493C88Fd351aFEbc802521f" +ACCOUNTING_ORACLE_IMPL = "0xE63267AAaC507A329213593e8A9bCa37e2994F1C" +VALIDATORS_EXIT_BUS_ORACLE_IMPL = "0xeCE105ABd3F2653398BE75e680dB033A238E2aD6" +WITHDRAWAL_VAULT_IMPL = "0x6aAA28C515E02ED0fe1B51e74323e14E910eA7d7" +STAKING_ROUTER_IMPL = "0xE6E775C6AdF8753588237b1De32f61937bC54341" +NODE_OPERATORS_REGISTRY_IMPL = "0x834aa47DCd21A32845099a78B4aBb17A7f0bD503" + +TRIGGERABLE_WITHDRAWALS_GATEWAY = "0x4FD4113f2B92856B59BC3be77f2943B7F4eaa9a5" +VALIDATOR_EXIT_VERIFIER = "0x9c5da60e54fcae8592132Fc9a67511e686b52BE8" + +# Oracle consensus versions +AO_CONSENSUS_VERSION = 4 +VEBO_CONSENSUS_VERSION = 4 +CSM_CONSENSUS_VERSION = 3 + +EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS = 7 * 7200 + +NOR_EXIT_DEADLINE_IN_SEC = 172800 + +MAX_VALIDATORS_PER_REPORT = 600 +MAX_EXIT_REQUESTS_LIMIT = 13000 +EXITS_PER_FRAME = 1 +FRAME_DURATION_IN_SEC = 48 + +# CSM +CS_MODULE_NEW_TARGET_SHARE_BP = 2000 # 20% +CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP = 2500 # 25% + +CS_ACCOUNTING_IMPL_V2_ADDRESS = "0xbd78207826CfdBE125cFf0a7075EaB90F5f9FCbb" +CS_FEE_DISTRIBUTOR_IMPL_V2_ADDRESS = "0x6e00A87690A1CAF4abb135B549408cEfca2fd6f5" +CS_FEE_ORACLE_IMPL_V2_ADDRESS = "0xD6F44e196A5b4A1C3863Bdd87233465ef42aBB40" +CSM_IMPL_V2_ADDRESS = "0xaF370636f618bC97c8Af2aBC33aAD426b1f4164A" + +CS_GATE_SEAL_V2_ADDRESS = "0x86E4aFE068f30A41f650601Df9A097bc7CddFb76" +CS_SET_VETTED_GATE_TREE_FACTORY = "0x26CDa8f9D84956efC743c8432658Ae9a5B7939da" +CS_EJECTOR_ADDRESS = "0x477589D5A8cB67Bd6682AF3612f99ADB72d09582" +CS_PERMISSIONLESS_GATE_ADDRESS = "0x676626c3940ae32eF1e4F609938F785fF064ee22" +CS_VETTED_GATE_ADDRESS = "0x92A5aB5e4f98e67Fb7295fe439A652d0E51033bf" +CS_VERIFIER_V2_ADDRESS = "0xBC88b4b56A58b33716C3C2e879b4B1F964152AD4" + +CS_DEFAULT_BOND_CURVE = ( + [1, 2 * 10**18], [2, 1.9 * 10**18], [3, 1.8 * 10**18], [4, 1.7 * 10**18], [5, 1.6 * 10**18], [6, 1.5 * 10**18] +) +CS_LEGACY_EA_BOND_CURVE = ( + ([1, 1.5 * 10**18], [2, 1.9 * 10**18], [3, 1.8 * 10**18], [4, 1.7 * 10**18], [5, 1.6 * 10**18], [6, 1.5 * 10**18]) +) +CS_EXTRA_CURVES = [ + ([1, 3 * 10**18], [2, 1.9 * 10**18], [3, 1.8 * 10**18], [4, 1.7 * 10**18], [5, 1.6 * 10**18], [6, 1.5 * 10**18]), + ([1, 4 * 10**18], [2, 1 * 10**18]) +] +CS_CURVES = [CS_DEFAULT_BOND_CURVE, CS_LEGACY_EA_BOND_CURVE, *CS_EXTRA_CURVES] +CS_ICS_GATE_BOND_CURVE = ([1, 1.5 * 10**18], [2, 1.3 * 10**18]) # Identified Community Stakers Gate Bond Curve + +OLD_GATE_SEAL_ADDRESS = "0xAE6eCd77DCC656c5533c4209454Fd56fB46e1778" + +NEW_WQ_GATE_SEAL = "0xE900BC859EB750562E1009e912B63743BC877662" +NEW_TW_GATE_SEAL = "0xaEEF47C61f2A9CCe4C4D0363911C5d49e2cFb6f1" + +RESEAL_MANAGER = "0x9dE2273f9f1e81145171CcA927EFeE7aCC64c9fb" + +def encode_staking_router_proxy_update(implementation: str) -> Tuple[str, str]: + proxy = interface.OssifiableProxy(contracts.staking_router) + return proxy.address, proxy.proxy__upgradeTo.encode_input(implementation) + + +def encode_proxy_upgrade_to(proxy: Any, implementation: str) -> Tuple[str, str]: + proxy = interface.OssifiableProxy(proxy) + return proxy.address, proxy.proxy__upgradeTo.encode_input(implementation) + + +def encode_wv_proxy_upgrade_to(proxy: Any, implementation: str) -> Tuple[str, str]: + proxy = interface.WithdrawalContractProxy(proxy) + + return proxy.address, proxy.proxy_upgradeTo.encode_input(implementation, b'') + + +def encode_oracle_upgrade_consensus(proxy: Any, consensus_version: int) -> Tuple[str, str]: + oracle = interface.BaseOracle(proxy) + return oracle.address, oracle.setConsensusVersion.encode_input(consensus_version) + + +def encode_staking_router_update_csm_module_share() -> Tuple[str, str]: + """Encode call to update CSM share limit""" + return ( + contracts.staking_router.address, + contracts.staking_router.updateStakingModule.encode_input( + CS_MODULE_ID, + CS_MODULE_NEW_TARGET_SHARE_BP, + CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP, + CS_MODULE_MODULE_FEE_BP, + CS_MODULE_TREASURY_FEE_BP, + CS_MODULE_MAX_DEPOSITS_PER_BLOCK, + CS_MODULE_MIN_DEPOSIT_BLOCK_DISTANCE, + ) + ) + + +def start_vote(tx_params: Dict[str, str], silent: bool) -> Tuple[int, Optional[Any]]: + vote_desc_items, call_script_items = zip( + # --- locator + ( + f"1. Update locator implementation", + encode_proxy_upgrade_to(contracts.lido_locator, LIDO_LOCATOR_IMPL) + ), + # --- VEB + ( + f"2. Update VEBO implementation", + encode_proxy_upgrade_to(contracts.validators_exit_bus_oracle, VALIDATORS_EXIT_BUS_ORACLE_IMPL) + ), + ( + f"3. Call finalizeUpgrade_v2 on VEBO", + ( + contracts.validators_exit_bus_oracle.address, + contracts.validators_exit_bus_oracle.finalizeUpgrade_v2.encode_input(MAX_VALIDATORS_PER_REPORT, MAX_EXIT_REQUESTS_LIMIT, EXITS_PER_FRAME, FRAME_DURATION_IN_SEC), + ) + ), + ( + f"4. Grant VEBO role MANAGE_CONSENSUS_VERSION_ROLE to the AGENT", + encode_oz_grant_role( + contract=contracts.validators_exit_bus_oracle, + role_name="MANAGE_CONSENSUS_VERSION_ROLE", + grant_to=contracts.agent, + ) + ), + ( + f"5. Bump VEBO consensus version to `{VEBO_CONSENSUS_VERSION}`", + encode_oracle_upgrade_consensus(contracts.validators_exit_bus_oracle, VEBO_CONSENSUS_VERSION) + ), + ( + f"6. Revoke VEBO role MANAGE_CONSENSUS_VERSION_ROLE from the AGENT", + encode_oz_revoke_role( + contract=contracts.validators_exit_bus_oracle, + role_name="MANAGE_CONSENSUS_VERSION_ROLE", + revoke_from=contracts.agent, + ) + ), + # --- Triggerable Withdrawals Gateway (TWG) + ( + f"7. Grant TWG role ADD_FULL_WITHDRAWAL_REQUEST_ROLE to the CS Ejector", + encode_oz_grant_role( + contract=interface.TriggerableWithdrawalsGateway(TRIGGERABLE_WITHDRAWALS_GATEWAY), + role_name="ADD_FULL_WITHDRAWAL_REQUEST_ROLE", + grant_to=CS_EJECTOR_ADDRESS, + ) + ), + ( + f"8. Grant TWG role ADD_FULL_WITHDRAWAL_REQUEST_ROLE to the VEB", + encode_oz_grant_role( + contract=interface.TriggerableWithdrawalsGateway(TRIGGERABLE_WITHDRAWALS_GATEWAY), + role_name="ADD_FULL_WITHDRAWAL_REQUEST_ROLE", + grant_to=contracts.validators_exit_bus_oracle, + ) + ), + # --- WV + ( + f"9. Update WithdrawalVault implementation", + encode_wv_proxy_upgrade_to(contracts.withdrawal_vault, WITHDRAWAL_VAULT_IMPL) + ), + ( + f"10. Call finalizeUpgrade_v2 on WithdrawalVault", + ( + contracts.withdrawal_vault.address, + contracts.withdrawal_vault.finalizeUpgrade_v2.encode_input(), + ) + ), + # --- AO + ( + f"11. Update Accounting Oracle implementation", + encode_proxy_upgrade_to(contracts.accounting_oracle, ACCOUNTING_ORACLE_IMPL), + ), + ( + f"12. Grant AO MANAGE_CONSENSUS_VERSION_ROLE to the AGENT", + encode_oz_grant_role( + contract=contracts.accounting_oracle, + role_name="MANAGE_CONSENSUS_VERSION_ROLE", + grant_to=contracts.agent, + ) + ), + ( + f"13. Bump AO consensus version to `{AO_CONSENSUS_VERSION}`", + encode_oracle_upgrade_consensus(contracts.accounting_oracle, AO_CONSENSUS_VERSION) + ), + ( + f"14. Revoke AO MANAGE_CONSENSUS_VERSION_ROLE from the AGENT", + encode_oz_revoke_role( + contract=contracts.accounting_oracle, + role_name="MANAGE_CONSENSUS_VERSION_ROLE", + revoke_from=contracts.agent, + ) + ), + # --- SR + ( + f"15. Update SR implementation", + encode_staking_router_proxy_update(STAKING_ROUTER_IMPL) + ), + ( + f"16. Grant SR role REPORT_VALIDATOR_EXITING_STATUS_ROLE to ValidatorExitDelayVerifier", + encode_oz_grant_role( + contract=contracts.staking_router, + role_name="REPORT_VALIDATOR_EXITING_STATUS_ROLE", + grant_to=VALIDATOR_EXIT_VERIFIER, + ) + ), + ( + f"17. Grant SR role REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE to TWG", + encode_oz_grant_role( + contract=contracts.staking_router, + role_name="REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE", + grant_to=interface.TriggerableWithdrawalsGateway(TRIGGERABLE_WITHDRAWALS_GATEWAY), + ) + ), + # --- NOR and sDVT + ( + f"18. Grant APP_MANAGER_ROLE role to the AGENT", + ( + contracts.acl.address, + contracts.acl.grantPermission.encode_input( + AGENT, + ARAGON_KERNEL, + convert.to_uint(web3.keccak(text="APP_MANAGER_ROLE")) + ) + ) + ), + ( + f"19. Update `NodeOperatorsRegistry` implementation", + ( + contracts.kernel.address, + contracts.kernel.setApp.encode_input( + contracts.kernel.APP_BASES_NAMESPACE(), + NODE_OPERATORS_REGISTRY_ARAGON_APP_ID, + NODE_OPERATORS_REGISTRY_IMPL + ) + ) + ), + ( + f"20. Call finalizeUpgrade_v4 on NOR", + ( + interface.NodeOperatorsRegistry(contracts.node_operators_registry).address, + interface.NodeOperatorsRegistry(contracts.node_operators_registry).finalizeUpgrade_v4.encode_input( + NOR_EXIT_DEADLINE_IN_SEC + ) + ) + ), + ( + f"21. Update `SDVT` implementation", + ( + contracts.kernel.address, + contracts.kernel.setApp.encode_input( + contracts.kernel.APP_BASES_NAMESPACE(), + SIMPLE_DVT_ARAGON_APP_ID, + NODE_OPERATORS_REGISTRY_IMPL + ) + ) + ), + ( + f"22. Call finalizeUpgrade_v4 on SDVT", + ( + interface.NodeOperatorsRegistry(contracts.simple_dvt).address, + interface.NodeOperatorsRegistry(contracts.simple_dvt).finalizeUpgrade_v4.encode_input( + NOR_EXIT_DEADLINE_IN_SEC + ) + ) + ), + ( + f"23. Revoke APP_MANAGER_ROLE role from the AGENT", + ( + contracts.acl.address, + contracts.acl.revokePermission.encode_input( + AGENT, + ARAGON_KERNEL, + convert.to_uint(web3.keccak(text="APP_MANAGER_ROLE")) + ) + ) + ), + # --- Oracle configs --- + ( + f"24. Grant CONFIG_MANAGER_ROLE role to the AGENT", + encode_oz_grant_role( + contract=contracts.oracle_daemon_config, + role_name="CONFIG_MANAGER_ROLE", + grant_to=contracts.agent, + ) + ), + ( + f"25. Remove NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP variable from OracleDaemonConfig", + ( + contracts.oracle_daemon_config.address, + contracts.oracle_daemon_config.unset.encode_input('NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP'), + ), + ), + ( + f"26. Remove VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS variable from OracleDaemonConfig", + ( + contracts.oracle_daemon_config.address, + contracts.oracle_daemon_config.unset.encode_input('VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS'), + ), + ), + ( + f"27. Remove VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS variable from OracleDaemonConfig", + ( + contracts.oracle_daemon_config.address, + contracts.oracle_daemon_config.unset.encode_input('VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS'), + ), + ), + ( + f"28. Add EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS variable to OracleDaemonConfig", + ( + contracts.oracle_daemon_config.address, + contracts.oracle_daemon_config.set.encode_input('EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS', EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS), + ), + ), + # --- CSM + ( + f"29. Upgrade CSM implementation on proxy", + encode_proxy_upgrade_to( + contracts.csm, + CSM_IMPL_V2_ADDRESS, + ) + ), + ( + f"30. Call `finalizeUpgradeV2()` on CSM contract", + ( + contracts.csm.address, + contracts.csm.finalizeUpgradeV2.encode_input(), + ), + ), + ( + f"31. Upgrade CSAccounting implementation on proxy", + encode_proxy_upgrade_to( + contracts.cs_accounting, + CS_ACCOUNTING_IMPL_V2_ADDRESS, + ) + ), + ( + f"32. Call `finalizeUpgradeV2(bondCurves)` on CSAccounting contract", + ( + contracts.cs_accounting.address, + contracts.cs_accounting.finalizeUpgradeV2.encode_input(CS_CURVES), + ), + ), + ( + f"33. Upgrade CSFeeOracle implementation on proxy", + encode_proxy_upgrade_to( + contracts.cs_fee_oracle, + CS_FEE_ORACLE_IMPL_V2_ADDRESS, + ) + ), + ( + f"34. Call `finalizeUpgradeV2(consensusVersion)` on CSFeeOracle contract", + ( + contracts.cs_fee_oracle.address, + contracts.cs_fee_oracle.finalizeUpgradeV2.encode_input(CSM_CONSENSUS_VERSION), + ) + ), + ( + f"35. Upgrade CSFeeDistributor implementation on proxy", + encode_proxy_upgrade_to( + contracts.cs_fee_distributor, + CS_FEE_DISTRIBUTOR_IMPL_V2_ADDRESS, + ) + ), + ( + f"36. Call `finalizeUpgradeV2(admin)` on CSFeeDistributor contract", + ( + contracts.cs_fee_distributor.address, + contracts.cs_fee_distributor.finalizeUpgradeV2.encode_input(contracts.agent), + ) + ), + ( + f"37. Revoke CSAccounting role SET_BOND_CURVE_ROLE from the CSM contract", + encode_oz_revoke_role( + contract=contracts.cs_accounting, + role_name="SET_BOND_CURVE_ROLE", + revoke_from=contracts.csm, + ) + ), + ( + f"38. Revoke CSAccounting role RESET_BOND_CURVE_ROLE from the CSM contract", + encode_oz_revoke_role( + contract=contracts.cs_accounting, + role_name="RESET_BOND_CURVE_ROLE", + revoke_from=contracts.csm, + ) + ), + ( + f"39. Revoke CSAccounting role RESET_BOND_CURVE_ROLE from the CSM committee", + encode_oz_revoke_role( + contract=contracts.cs_accounting, + role_name="RESET_BOND_CURVE_ROLE", + revoke_from=CSM_COMMITTEE_MS, + ) + ), + ( + f"40. Grant CSM role CREATE_NODE_OPERATOR_ROLE for the permissionless gate", + encode_oz_grant_role( + contract=contracts.csm, + role_name="CREATE_NODE_OPERATOR_ROLE", + grant_to=CS_PERMISSIONLESS_GATE_ADDRESS, + ) + ), + ( + f"41. Grant CSM role CREATE_NODE_OPERATOR_ROLE for the vetted gate", + encode_oz_grant_role( + contract=contracts.csm, + role_name="CREATE_NODE_OPERATOR_ROLE", + grant_to=CS_VETTED_GATE_ADDRESS, + ) + ), + ( + f"42. Grant CSAccounting role SET_BOND_CURVE_ROLE for the vetted gate", + encode_oz_grant_role( + contract=contracts.cs_accounting, + role_name="SET_BOND_CURVE_ROLE", + grant_to=CS_VETTED_GATE_ADDRESS, + ) + ), + ( + f"43. Revoke role VERIFIER_ROLE from the previous instance of the Verifier contract", + encode_oz_revoke_role( + contract=contracts.csm, + role_name="VERIFIER_ROLE", + revoke_from=contracts.cs_verifier, + ) + ), + ( + f"44. Grant role VERIFIER_ROLE to the new instance of the Verifier contract", + encode_oz_grant_role( + contract=contracts.csm, + role_name="VERIFIER_ROLE", + grant_to=CS_VERIFIER_V2_ADDRESS, + ) + ), + ( + f"45. Revoke CSM role PAUSE_ROLE from the previous GateSeal instance", + encode_oz_revoke_role( + contract=contracts.csm, + role_name="PAUSE_ROLE", + revoke_from=CS_GATE_SEAL_ADDRESS, + ) + ), + ( + f"46. Revoke CSAccounting role PAUSE_ROLE from the previous GateSeal instance", + encode_oz_revoke_role( + contract=contracts.cs_accounting, + role_name="PAUSE_ROLE", + revoke_from=CS_GATE_SEAL_ADDRESS, + ) + ), + ( + f"47. Revoke CSFeeOracle role PAUSE_ROLE from the previous GateSeal instance", + encode_oz_revoke_role( + contract=contracts.cs_fee_oracle, + role_name="PAUSE_ROLE", + revoke_from=CS_GATE_SEAL_ADDRESS, + ) + ), + ( + f"48. Grant CSM role PAUSE_ROLE for the new GateSeal instance", + encode_oz_grant_role( + contract=contracts.csm, + role_name="PAUSE_ROLE", + grant_to=CS_GATE_SEAL_V2_ADDRESS, + ) + ), + ( + f"49. Grant CSAccounting role PAUSE_ROLE for the new GateSeal instance", + encode_oz_grant_role( + contract=contracts.cs_accounting, + role_name="PAUSE_ROLE", + grant_to=CS_GATE_SEAL_V2_ADDRESS, + ) + ), + ( + f"50. Grant CSFeeOracle role PAUSE_ROLE for the new GateSeal instance", + encode_oz_grant_role( + contract=contracts.cs_fee_oracle, + role_name="PAUSE_ROLE", + grant_to=CS_GATE_SEAL_V2_ADDRESS, + ) + ), + ( + "51. Grant MANAGE_BOND_CURVES_ROLE to the AGENT", + encode_oz_grant_role( + contract=contracts.cs_accounting, + role_name="MANAGE_BOND_CURVES_ROLE", + grant_to=contracts.agent, + ) + ), + ( + "52. Add Identified Community Stakers Gate Bond Curve", + ( + contracts.cs_accounting.address, + contracts.cs_accounting.addBondCurve.encode_input(CS_ICS_GATE_BOND_CURVE), + ), + ), + ( + "53. Revoke MANAGE_BOND_CURVES_ROLE from the AGENT", + encode_oz_revoke_role( + contract=contracts.cs_accounting, + role_name="MANAGE_BOND_CURVES_ROLE", + revoke_from=contracts.agent, + ) + ), + ( + "54. Increase CSM share in Staking Router from 3% to 5%", + encode_staking_router_update_csm_module_share() + ), + # --- Core Gate seals --- + # Revoke old GateSeal + ( + "55. Revoke PAUSE_ROLE on WithdrawalQueue 0xc7cc160b58F8Bb0baC94b80847E2CF2800565C50 from the old GateSeal 0xA34d620EA9F3e86bf8B8a7699B4dE44CD9D3202d", + encode_oz_revoke_role( + contract=contracts.withdrawal_queue, + role_name="PAUSE_ROLE", + revoke_from=OLD_GATE_SEAL_ADDRESS, + ), + ), + ( + "56. Revoke PAUSE_ROLE on ValidatorsExitBusOracle 0xffDDF7025410412deaa05E3E1cE68FE53208afcb from the old GateSeal 0xA34d620EA9F3e86bf8B8a7699B4dE44CD9D3202d", + encode_oz_revoke_role( + contract=contracts.validators_exit_bus_oracle, + role_name="PAUSE_ROLE", + revoke_from=OLD_GATE_SEAL_ADDRESS, + ) + ), + # Add new GateSeal + # Now we have two GateSeals: one for WithdrawalQueue and one for ValidatorsExitBusOracle and TriggerableWithdrawalsGateway. + ( + "57. Grant PAUSE_ROLE on WithdrawalQueue to the new GateSeal", + encode_oz_grant_role( + contract=contracts.withdrawal_queue, + role_name="PAUSE_ROLE", + grant_to=NEW_WQ_GATE_SEAL, + ) + ), + ( + "58. Grant PAUSE_ROLE on ValidatorsExitBusOracle to the new GateSeal", + encode_oz_grant_role( + contract=contracts.validators_exit_bus_oracle, + role_name="PAUSE_ROLE", + grant_to=NEW_TW_GATE_SEAL, + ) + ), + ( + "59. Grant PAUSE_ROLE on TWG to the new GateSeal", + encode_oz_grant_role( + contract=interface.TriggerableWithdrawalsGateway(TRIGGERABLE_WITHDRAWALS_GATEWAY), + role_name="PAUSE_ROLE", + grant_to=NEW_TW_GATE_SEAL, + ) + ), + # --- ResealManager --- + # Grant ResealManager PAUSE_ROLE on WithdrawalQueue, ValidatorsExitBusOracle and TWG + ( + "60. Grant PAUSE_ROLE on TWG to the new GateSeal", + encode_oz_grant_role( + contract=interface.TriggerableWithdrawalsGateway(TRIGGERABLE_WITHDRAWALS_GATEWAY), + role_name="PAUSE_ROLE", + grant_to=RESEAL_MANAGER, + ) + ), + # Grant ResealManager RESUME_ROLE on WithdrawalQueue, ValidatorsExitBusOracle and TWG + ( + "61. Grant PAUSE_ROLE on TWG to the new GateSeal", + encode_oz_grant_role( + contract=interface.TriggerableWithdrawalsGateway(TRIGGERABLE_WITHDRAWALS_GATEWAY), + role_name="RESUME_ROLE", + grant_to=RESEAL_MANAGER, + ) + ), + ( + "62. Call finalizeUpgrade_v3 on AO contract", + ( + contracts.accounting_oracle.address, + contracts.accounting_oracle.finalizeUpgrade_v3.encode_input(), + ) + ) + ) + + + dg_bypass_item = { + "63. Add CSSetVettedGateTree factory to EasyTrack with permissions": add_evmscript_factory( + factory=CS_SET_VETTED_GATE_TREE_FACTORY, + permissions=(create_permissions(interface.CSVettedGate(CS_VETTED_GATE_ADDRESS), "setTreeParams")), + ) + } + + if silent: + desc_ipfs = calculate_vote_ipfs_description(DESCRIPTION) + else: + desc_ipfs = upload_vote_ipfs_description(DESCRIPTION) + + dg_desc = "\n".join(vote_desc_items) + dg_vote = dual_governance_agent_forward(call_script_items, dg_desc) + vote_items = {dg_desc: dg_vote, **dg_bypass_item} + + assert confirm_vote_script(vote_items, silent, desc_ipfs) + + return create_vote(vote_items, tx_params, desc_ipfs=desc_ipfs) + + +def main(): + tx_params = {"from": get_deployer_account()} + if get_is_live(): + tx_params["priority_fee"] = get_priority_fee() + + vote_id, _ = start_vote(tx_params=tx_params, silent=False) + + vote_id >= 0 and print(f"Vote created: {vote_id}.") + + time.sleep(5) # hack for waiting thread #2. diff --git a/archive/scripts/vote_tw_csm2_hoodi.py b/archive/scripts/vote_tw_csm2_hoodi.py new file mode 100644 index 000000000..da0f3bd32 --- /dev/null +++ b/archive/scripts/vote_tw_csm2_hoodi.py @@ -0,0 +1,901 @@ +""" +Vote 23/07/2025 [HOODI] + +--- Locator +1. Update locator implementation +--- VEB +2. Update VEBO implementation +3. Call finalizeUpgrade_v2(maxValidatorsPerReport, maxExitRequestsLimit, exitsPerFrame, frameDurationInSec) on VEBO +4. Grant VEBO role MANAGE_CONSENSUS_VERSION_ROLE to the AGENT +5. Bump VEBO consensus version to `4` +6. Revoke VEBO role MANAGE_CONSENSUS_VERSION_ROLE from the AGENT +7. Grant SUBMIT_REPORT_HASH_ROLE on Validator Exit Bus Oracle to the EasyTrack EVM Script Executor +--- Triggerable Withdrawals Gateway (TWG) +8. Grant TWG role ADD_FULL_WITHDRAWAL_REQUEST_ROLE to the CS Ejector +9. Grant TWG role ADD_FULL_WITHDRAWAL_REQUEST_ROLE to the VEB +10. Connect TRIGGERABLE_WITHDRAWALS_GATEWAY to Dual Governance tiebreaker +--- WV +11. Update WithdrawalVault implementation +12. Call finalizeUpgrade_v2() on WithdrawalVault +--- AO +13. Update Accounting Oracle implementation +14. Grant AO MANAGE_CONSENSUS_VERSION_ROLE to the AGENT +15. Bump AO consensus version to `4` +16. Revoke AO MANAGE_CONSENSUS_VERSION_ROLE from the AGENT +17. Call finalizeUpgrade_v3() on AO +--- SR +18. Update SR implementation +19. Call finalizeUpgrade_v3() on SR +20. Grant SR role REPORT_VALIDATOR_EXITING_STATUS_ROLE to ValidatorExitVerifier +21. Grant SR role REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE to TWG +--- Curated Staking Module +22. Grant APP_MANAGER_ROLE role to the AGENT on Kernel +23. Update `NodeOperatorsRegistry` implementation +24. Call finalizeUpgrade_v4 on Curated Staking Module +--- sDVT +25. Update `SimpleDVT` implementation +26. Call finalizeUpgrade_v4 on sDVT +27. Revoke APP_MANAGER_ROLE role from the AGENT on Kernel +--- Oracle configs --- +28. Grant CONFIG_MANAGER_ROLE role to the AGENT +29. Remove NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP variable from OracleDaemonConfig +30. Remove VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS variable from OracleDaemonConfig +31. Remove VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS variable from OracleDaemonConfig +32. Add EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS variable to OracleDaemonConfig +33. Revoke CONFIG_MANAGER_ROLE role from the AGENT +--- CSM --- +34. Upgrade CSM implementation on proxy +35. Call `finalizeUpgradeV2()` on CSM contract +36. Upgrade CSAccounting implementation on proxy +37. Call `finalizeUpgradeV2(bondCurves)` on CSAccounting contract +38. Upgrade CSFeeOracle implementation on proxy +39. Call `finalizeUpgradeV2(consensusVersion)` on CSFeeOracle contract +40. Upgrade CSFeeDistributor implementation on proxy +41. Call `finalizeUpgradeV2(admin)` on CSFeeDistributor contract +42. Revoke CSAccounting role SET_BOND_CURVE_ROLE from the CSM contract +43. Revoke CSAccounting role RESET_BOND_CURVE_ROLE from the CSM contract +44. Revoke CSAccounting role RESET_BOND_CURVE_ROLE from the CSM committee +45. Grant CSM role CREATE_NODE_OPERATOR_ROLE for the permissionless gate +46. Grant CSM role CREATE_NODE_OPERATOR_ROLE for the vetted gate +47. Grant CSAccounting role SET_BOND_CURVE_ROLE for the vetted gate +48. Revoke role VERIFIER_ROLE from the previous instance of the Verifier contract +49. Grant role VERIFIER_ROLE to the new instance of the Verifier contract +50. Revoke CSM role PAUSE_ROLE from the previous GateSeal instance +51. Revoke CSAccounting role PAUSE_ROLE from the previous GateSeal instance +52. Revoke CSFeeOracle role PAUSE_ROLE from the previous GateSeal instance +53. Grant CSM role PAUSE_ROLE for the new GateSeal instance +54. Grant CSAccounting role PAUSE_ROLE for the new GateSeal instance +55. Grant CSFeeOracle role PAUSE_ROLE for the new GateSeal instance +56. Grant MANAGE_BOND_CURVES_ROLE to the AGENT +57. Add Identified Community Stakers Gate Bond Curve +58. Revoke MANAGE_BOND_CURVES_ROLE from the AGENT +59. Increase CSM share in Staking Router from 15% to 16% +--- Gate Seals --- +60. Revoke PAUSE_ROLE on WithdrawalQueue from the old GateSeal +61. Revoke PAUSE_ROLE on ValidatorsExitBusOracle from the old GateSeal +62. Grant PAUSE_ROLE on WithdrawalQueue to the new WithdrawalQueue GateSeal +63. Grant PAUSE_ROLE on ValidatorsExitBusOracle to the new Triggerable Withdrawals GateSeal +64. Grant PAUSE_ROLE on TriggerableWithdrawalsGateway to the new Triggerable Withdrawals GateSeal +--- ResealManager --- +65. Grant PAUSE_ROLE on TriggerableWithdrawalsGateway to ResealManager +66. Grant RESUME_ROLE on TriggerableWithdrawalsGateway to ResealManager +--- EasyTrack --- +67. Add CSSetVettedGateTree factory to EasyTrack with permissions +68. Add `SubmitValidatorsExitRequestHashes` (SDVT) EVM script factory to Easy Track +69. Add `SubmitValidatorsExitRequestHashes` (Curated Module) EVM script factory to Easy Track + +Vote passed & executed on Jul-23-2025 12:54:36 PM UTC, block 862608 +""" +import time + +from typing import TYPE_CHECKING, Any, Dict +from typing import Tuple, Optional, Sequence +from brownie import interface, web3, convert, ZERO_ADDRESS # type: ignore +from utils.agent import agent_forward +from utils.config import ( + CSM_COMMITTEE_MS, + CS_MODULE_ID, + CS_MODULE_MODULE_FEE_BP, + CS_MODULE_TREASURY_FEE_BP, + CS_MODULE_MAX_DEPOSITS_PER_BLOCK, + CS_MODULE_MIN_DEPOSIT_BLOCK_DISTANCE, + CS_MODULE_TARGET_SHARE_BP, + CS_GATE_SEAL_ADDRESS, + NODE_OPERATORS_REGISTRY_ARAGON_APP_ID, + SIMPLE_DVT_ARAGON_APP_ID, + ARAGON_KERNEL, + AGENT, + contracts, +) +from utils.ipfs import upload_vote_ipfs_description, calculate_vote_ipfs_description +from utils.permissions import encode_oz_grant_role, encode_oz_revoke_role +from utils.easy_track import ( + add_evmscript_factory, + create_permissions, +) +from utils.voting import confirm_vote_script, create_vote +from utils.config import get_deployer_account, get_priority_fee, get_is_live + +DESCRIPTION = "Triggerable withdrawals and CSM v2 upgrade voting (HOODI)" + +# New core contracts implementations +LIDO_LOCATOR_IMPL = "0x003f20CD17e7683A7F88A7AfF004f0C44F0cfB31" +ACCOUNTING_ORACLE_IMPL = "0x2341c9BE0E639f262f8170f9ef1efeCC92cCF617" +VALIDATORS_EXIT_BUS_ORACLE_IMPL = "0x7E6d9C9C44417bf2EaF69685981646e9752D623A" +WITHDRAWAL_VAULT_IMPL = "0xfe7A58960Af333eAdeAeC39149F9d6A71dc3E668" +STAKING_ROUTER_IMPL = "0xd5F04A81ac472B2cB32073CE9dDABa6FaF022827" +NODE_OPERATORS_REGISTRY_IMPL = "0x95F00b016bB31b7182D96D25074684518246E42a" + +TRIGGERABLE_WITHDRAWALS_GATEWAY = "0x6679090D92b08a2a686eF8614feECD8cDFE209db" +VALIDATOR_EXIT_VERIFIER = "0xFd4386A8795956f4B6D01cbb6dB116749731D7bD" + +# Oracle consensus versions +AO_CONSENSUS_VERSION = 4 +VEBO_CONSENSUS_VERSION = 4 +CSM_CONSENSUS_VERSION = 3 + +# Fixed constants from Holesky version +EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS = 14 * 7200 # 14 days in slots (assuming 12 seconds per slot) +NOR_EXIT_DEADLINE_IN_SEC = 172800 # 172800 + +# VEB parameters from Holesky +MAX_VALIDATORS_PER_REPORT = 600 +MAX_EXIT_REQUESTS_LIMIT = 11200 +EXITS_PER_FRAME = 1 +FRAME_DURATION_IN_SEC = 48 + +# CSM +CS_MODULE_NEW_TARGET_SHARE_BP = 1600 # 16% +CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP = 2100 # 21% + +CS_ACCOUNTING_IMPL_V2_ADDRESS = "0x9483b34504292a0E4f6509e5887D2c68f7129638" +CS_FEE_DISTRIBUTOR_IMPL_V2_ADDRESS = "0xe05F7Aab7177D73f26e62a5296120583F5F18031" +CS_FEE_ORACLE_IMPL_V2_ADDRESS = "0x752fF00fcacdB66Bc512a067F15A5E0B0b50EADB" +CSM_IMPL_V2_ADDRESS = "0x9aE387EB2abA80B9B1ebc145597D593EFAE61f31" + +CS_GATE_SEAL_V2_ADDRESS = "0x94a3aEB0E9148F64CB453Be2BDe2Bc0148f6AC24" +CS_EJECTOR_ADDRESS = "0x21e271cBa32672B106737AbeB3a45E53Fe9a0df4" +CS_PERMISSIONLESS_GATE_ADDRESS = "0x5553077102322689876A6AdFd48D75014c28acfb" +CS_VETTED_GATE_ADDRESS = "0x10a254E724fe2b7f305F76f3F116a3969c53845f" +CS_VERIFIER_V2_ADDRESS = "0xf805b3711cBB48F15Ae2bb27095ddC38c5339968" + +CS_CURVES = [ + ([1, 2.4 * 10**18], [2, 1.3 * 10**18]), # Default Curve + ([1, 1.5 * 10**18], [2, 1.3 * 10**18]), # Legacy EA Curve +] +CS_ICS_GATE_BOND_CURVE = ([1, 1.5 * 10**18], [2, 1.3 * 10**18]) # Identified Community Stakers Gate Bond Curve + +# Add missing constants +OLD_GATE_SEAL_ADDRESS = "0x2168Ea6D948Ab49c3D34c667A7e02F92369F3A9C" +NEW_WQ_GATE_SEAL = "0x73d76Bd3D589B2b2185c402da82cdAfbc18b958D" +NEW_TW_GATE_SEAL = "0x368f2fcb593170823cc844F1B29e75E3d26879A1" +RESEAL_MANAGER = "0x05172CbCDb7307228F781436b327679e4DAE166B" + +# Add EasyTrack constants +EASYTRACK_EVMSCRIPT_EXECUTOR = "0x79a20FD0FA36453B2F45eAbab19bfef43575Ba9E" +EASYTRACK_SDVT_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY = "0xAa3D6A8B52447F272c1E8FAaA06EA06658bd95E2" +EASYTRACK_CURATED_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY = "0x397206ecdbdcb1A55A75e60Fc4D054feC72E5f63" +EASYTRACK_CS_SET_VETTED_GATE_TREE_FACTORY = "0xa890fc73e1b771Ee6073e2402E631c312FF92Cd9" + + +def encode_staking_router_proxy_update(implementation: str) -> Tuple[str, str]: + proxy = interface.OssifiableProxy(contracts.staking_router) + return proxy.address, proxy.proxy__upgradeTo.encode_input(implementation) + + +def encode_proxy_upgrade_to(proxy: Any, implementation: str) -> Tuple[str, str]: + proxy = interface.OssifiableProxy(proxy) + return proxy.address, proxy.proxy__upgradeTo.encode_input(implementation) + + +def encode_wv_proxy_upgrade_to(proxy: Any, implementation: str) -> Tuple[str, str]: + proxy = interface.WithdrawalContractProxy(proxy) + + return proxy.address, proxy.proxy_upgradeTo.encode_input(implementation, b'') + + +def encode_oracle_upgrade_consensus(proxy: Any, consensus_version: int) -> Tuple[str, str]: + oracle = interface.BaseOracle(proxy) + return oracle.address, oracle.setConsensusVersion.encode_input(consensus_version) + + +def encode_staking_router_update_csm_module_share() -> Tuple[str, str]: + """Encode call to update CSM share limit""" + return ( + contracts.staking_router.address, + contracts.staking_router.updateStakingModule.encode_input( + CS_MODULE_ID, + CS_MODULE_NEW_TARGET_SHARE_BP, + CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP, + CS_MODULE_MODULE_FEE_BP, + CS_MODULE_TREASURY_FEE_BP, + CS_MODULE_MAX_DEPOSITS_PER_BLOCK, + CS_MODULE_MIN_DEPOSIT_BLOCK_DISTANCE, + ) + ) + + +def to_percent(bp: int) -> float: + """ + Convert basis points to percentage. + """ + return bp / 10000 * 100 + + +def start_vote(tx_params: Dict[str, str], silent: bool) -> Tuple[int, Optional[Any]]: + vote_desc_items, call_script_items = zip( + # --- locator + ( + "1. Update locator implementation", + agent_forward([encode_proxy_upgrade_to(contracts.lido_locator, LIDO_LOCATOR_IMPL)]) + ), + # --- VEB + ( + "2. Update VEBO implementation", + agent_forward([encode_proxy_upgrade_to(contracts.validators_exit_bus_oracle, VALIDATORS_EXIT_BUS_ORACLE_IMPL)]) + ), + ( + "3. Call finalizeUpgrade_v2 on VEBO", + agent_forward([ + ( + contracts.validators_exit_bus_oracle.address, + contracts.validators_exit_bus_oracle.finalizeUpgrade_v2.encode_input( + MAX_VALIDATORS_PER_REPORT, MAX_EXIT_REQUESTS_LIMIT, EXITS_PER_FRAME, FRAME_DURATION_IN_SEC + ), + ) + ]) + ), + ( + "4. Grant VEBO role MANAGE_CONSENSUS_VERSION_ROLE to the AGENT", + agent_forward([ + encode_oz_grant_role( + contract=contracts.validators_exit_bus_oracle, + role_name="MANAGE_CONSENSUS_VERSION_ROLE", + grant_to=contracts.agent, + ) + ]) + ), + ( + "5. Bump VEBO consensus version to `4`", + agent_forward([encode_oracle_upgrade_consensus(contracts.validators_exit_bus_oracle, VEBO_CONSENSUS_VERSION)]) + ), + ( + "6. Revoke VEBO role MANAGE_CONSENSUS_VERSION_ROLE from the AGENT", + agent_forward([ + encode_oz_revoke_role( + contract=contracts.validators_exit_bus_oracle, + role_name="MANAGE_CONSENSUS_VERSION_ROLE", + revoke_from=contracts.agent, + ) + ]) + ), + ( + "7. Grant SUBMIT_REPORT_HASH_ROLE on Validator Exit Bus Oracle to the EasyTrack EVM Script Executor", + agent_forward([ + encode_oz_grant_role( + contract=contracts.validators_exit_bus_oracle, + role_name="SUBMIT_REPORT_HASH_ROLE", + grant_to=EASYTRACK_EVMSCRIPT_EXECUTOR, + ) + ]) + ), + # --- Triggerable Withdrawals Gateway (TWG) + ( + "8. Grant TWG role ADD_FULL_WITHDRAWAL_REQUEST_ROLE to the CS Ejector", + agent_forward([ + encode_oz_grant_role( + contract=interface.TriggerableWithdrawalsGateway(TRIGGERABLE_WITHDRAWALS_GATEWAY), + role_name="ADD_FULL_WITHDRAWAL_REQUEST_ROLE", + grant_to=CS_EJECTOR_ADDRESS, + ) + ]) + ), + ( + "9. Grant TWG role ADD_FULL_WITHDRAWAL_REQUEST_ROLE to the VEB", + agent_forward([ + encode_oz_grant_role( + contract=interface.TriggerableWithdrawalsGateway(TRIGGERABLE_WITHDRAWALS_GATEWAY), + role_name="ADD_FULL_WITHDRAWAL_REQUEST_ROLE", + grant_to=contracts.validators_exit_bus_oracle, + ) + ]) + ), + ( + "10. Connect TRIGGERABLE_WITHDRAWALS_GATEWAY to Dual Governance tiebreaker", + ( + contracts.dual_governance.address, + contracts.dual_governance.addTiebreakerSealableWithdrawalBlocker.encode_input( + TRIGGERABLE_WITHDRAWALS_GATEWAY + ), + ) + ), + # --- WV + ( + "11. Update WithdrawalVault implementation", + agent_forward([encode_wv_proxy_upgrade_to(contracts.withdrawal_vault, WITHDRAWAL_VAULT_IMPL)]) + ), + ( + "12. Call finalizeUpgrade_v2 on WithdrawalVault", + agent_forward([ + ( + contracts.withdrawal_vault.address, + contracts.withdrawal_vault.finalizeUpgrade_v2.encode_input(), + ) + ]) + ), + # --- AO + ( + "13. Update Accounting Oracle implementation", + agent_forward([encode_proxy_upgrade_to(contracts.accounting_oracle, ACCOUNTING_ORACLE_IMPL)]) + ), + ( + "14. Grant AO MANAGE_CONSENSUS_VERSION_ROLE to the AGENT", + agent_forward([ + encode_oz_grant_role( + contract=contracts.accounting_oracle, + role_name="MANAGE_CONSENSUS_VERSION_ROLE", + grant_to=contracts.agent, + ) + ]) + ), + ( + "15. Bump AO consensus version to `4`", + agent_forward([encode_oracle_upgrade_consensus(contracts.accounting_oracle, AO_CONSENSUS_VERSION)]) + ), + ( + "16. Revoke AO MANAGE_CONSENSUS_VERSION_ROLE from the AGENT", + agent_forward([ + encode_oz_revoke_role( + contract=contracts.accounting_oracle, + role_name="MANAGE_CONSENSUS_VERSION_ROLE", + revoke_from=contracts.agent, + ) + ]) + ), + ( + "17. Call finalizeUpgrade_v3() on AO", + agent_forward([ + ( + contracts.accounting_oracle.address, + contracts.accounting_oracle.finalizeUpgrade_v3.encode_input(), + ) + ]) + ), + # --- SR + ( + "18. Update SR implementation", + agent_forward([encode_staking_router_proxy_update(STAKING_ROUTER_IMPL)]) + ), + ( + "19. Call finalizeUpgrade_v3() on SR", + agent_forward([( + contracts.staking_router.address, + contracts.staking_router.finalizeUpgrade_v3.encode_input(), + )]) + ), + ( + "20. Grant SR role REPORT_VALIDATOR_EXITING_STATUS_ROLE to ValidatorExitDelayVerifier", + agent_forward([ + encode_oz_grant_role( + contract=contracts.staking_router, + role_name="REPORT_VALIDATOR_EXITING_STATUS_ROLE", + grant_to=VALIDATOR_EXIT_VERIFIER, + ) + ]) + ), + ( + "21. Grant SR role REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE to TWG", + agent_forward([ + encode_oz_grant_role( + contract=contracts.staking_router, + role_name="REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE", + grant_to=interface.TriggerableWithdrawalsGateway(TRIGGERABLE_WITHDRAWALS_GATEWAY), + ) + ]) + ), + # --- Curated Staking Module and sDVT + ( + "22. Grant APP_MANAGER_ROLE role to the AGENT", + agent_forward([ + ( + contracts.acl.address, + contracts.acl.grantPermission.encode_input( + AGENT, + ARAGON_KERNEL, + convert.to_uint(web3.keccak(text="APP_MANAGER_ROLE")) + ) + ) + ]) + ), + ( + "23. Update `NodeOperatorsRegistry` implementation", + agent_forward([ + ( + contracts.kernel.address, + contracts.kernel.setApp.encode_input( + contracts.kernel.APP_BASES_NAMESPACE(), + NODE_OPERATORS_REGISTRY_ARAGON_APP_ID, + NODE_OPERATORS_REGISTRY_IMPL + ) + ) + ]) + ), + ( + "24. Call finalizeUpgrade_v4 on Curated Staking Module", + agent_forward([ + ( + interface.NodeOperatorsRegistry(contracts.node_operators_registry).address, + interface.NodeOperatorsRegistry(contracts.node_operators_registry).finalizeUpgrade_v4.encode_input( + NOR_EXIT_DEADLINE_IN_SEC + ) + ) + ]) + ), + ( + "25. Update `SDVT` implementation", + agent_forward([ + ( + contracts.kernel.address, + contracts.kernel.setApp.encode_input( + contracts.kernel.APP_BASES_NAMESPACE(), + SIMPLE_DVT_ARAGON_APP_ID, + NODE_OPERATORS_REGISTRY_IMPL + ) + ) + ]) + ), + ( + "26. Call finalizeUpgrade_v4 on SDVT", + agent_forward([ + ( + interface.NodeOperatorsRegistry(contracts.simple_dvt).address, + interface.NodeOperatorsRegistry(contracts.simple_dvt).finalizeUpgrade_v4.encode_input( + NOR_EXIT_DEADLINE_IN_SEC + ) + ) + ]) + ), + ( + "27. Revoke APP_MANAGER_ROLE role from the AGENT", + agent_forward([ + ( + contracts.acl.address, + contracts.acl.revokePermission.encode_input( + AGENT, + ARAGON_KERNEL, + convert.to_uint(web3.keccak(text="APP_MANAGER_ROLE")) + ) + ) + ]) + ), + # --- Oracle configs + ( + "28. Grant CONFIG_MANAGER_ROLE role to the AGENT", + agent_forward([ + encode_oz_grant_role( + contract=contracts.oracle_daemon_config, + role_name="CONFIG_MANAGER_ROLE", + grant_to=contracts.agent, + ) + ]) + ), + ( + "29. Remove NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP variable from OracleDaemonConfig", + agent_forward([ + ( + contracts.oracle_daemon_config.address, + contracts.oracle_daemon_config.unset.encode_input('NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP'), + ) + ]) + ), + ( + "30. Remove VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS variable from OracleDaemonConfig", + agent_forward([ + ( + contracts.oracle_daemon_config.address, + contracts.oracle_daemon_config.unset.encode_input('VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS'), + ) + ]) + ), + ( + "31. Remove VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS variable from OracleDaemonConfig", + agent_forward([ + ( + contracts.oracle_daemon_config.address, + contracts.oracle_daemon_config.unset.encode_input('VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS'), + ) + ]) + ), + ( + "32. Add EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS variable to OracleDaemonConfig", + agent_forward([ + ( + contracts.oracle_daemon_config.address, + contracts.oracle_daemon_config.set.encode_input('EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS', EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS), + ) + ]) + ), + ( + "33. Revoke CONFIG_MANAGER_ROLE role from the AGENT", + agent_forward([ + encode_oz_revoke_role( + contract=contracts.oracle_daemon_config, + role_name="CONFIG_MANAGER_ROLE", + revoke_from=contracts.agent, + ) + ]) + ), + # --- CSM + ( + "34. Upgrade CSM implementation on proxy", + agent_forward([ + encode_proxy_upgrade_to( + contracts.csm, + CSM_IMPL_V2_ADDRESS, + ) + ]) + ), + ( + "35. Call `finalizeUpgradeV2()` on CSM contract", + agent_forward([ + ( + contracts.csm.address, + contracts.csm.finalizeUpgradeV2.encode_input(), + ) + ]) + ), + ( + "36. Upgrade CSAccounting implementation on proxy", + agent_forward([ + encode_proxy_upgrade_to( + contracts.cs_accounting, + CS_ACCOUNTING_IMPL_V2_ADDRESS, + ) + ]) + ), + ( + "37. Call `finalizeUpgradeV2(bondCurves)` on CSAccounting contract", + agent_forward([ + ( + contracts.cs_accounting.address, + contracts.cs_accounting.finalizeUpgradeV2.encode_input(CS_CURVES), + ) + ]) + ), + ( + "38. Upgrade CSFeeOracle implementation on proxy", + agent_forward([ + encode_proxy_upgrade_to( + contracts.cs_fee_oracle, + CS_FEE_ORACLE_IMPL_V2_ADDRESS, + ) + ]) + ), + ( + "39. Call `finalizeUpgradeV2(consensusVersion)` on CSFeeOracle contract", + agent_forward([ + ( + contracts.cs_fee_oracle.address, + contracts.cs_fee_oracle.finalizeUpgradeV2.encode_input(CSM_CONSENSUS_VERSION), + ) + ]) + ), + ( + "40. Upgrade CSFeeDistributor implementation on proxy", + agent_forward([ + encode_proxy_upgrade_to( + contracts.cs_fee_distributor, + CS_FEE_DISTRIBUTOR_IMPL_V2_ADDRESS, + ) + ]) + ), + ( + "41. Call `finalizeUpgradeV2(admin)` on CSFeeDistributor contract", + agent_forward([ + ( + contracts.cs_fee_distributor.address, + contracts.cs_fee_distributor.finalizeUpgradeV2.encode_input(contracts.agent), + ) + ]) + ), + ( + "42. Revoke CSAccounting role SET_BOND_CURVE_ROLE from the CSM contract", + agent_forward([ + encode_oz_revoke_role( + contract=contracts.cs_accounting, + role_name="SET_BOND_CURVE_ROLE", + revoke_from=contracts.csm, + ) + ]) + ), + ( + "43. Revoke CSAccounting role RESET_BOND_CURVE_ROLE from the CSM contract", + agent_forward([ + encode_oz_revoke_role( + contract=contracts.cs_accounting, + role_name="RESET_BOND_CURVE_ROLE", + revoke_from=contracts.csm, + ) + ]) + ), + ( + "44. Revoke CSAccounting role RESET_BOND_CURVE_ROLE from the CSM committee", + agent_forward([ + encode_oz_revoke_role( + contract=contracts.cs_accounting, + role_name="RESET_BOND_CURVE_ROLE", + revoke_from=CSM_COMMITTEE_MS, + ) + ]) + ), + ( + "45. Grant CSM role CREATE_NODE_OPERATOR_ROLE for the permissionless gate", + agent_forward([ + encode_oz_grant_role( + contract=contracts.csm, + role_name="CREATE_NODE_OPERATOR_ROLE", + grant_to=CS_PERMISSIONLESS_GATE_ADDRESS, + ) + ]) + ), + ( + "46. Grant CSM role CREATE_NODE_OPERATOR_ROLE for the vetted gate", + agent_forward([ + encode_oz_grant_role( + contract=contracts.csm, + role_name="CREATE_NODE_OPERATOR_ROLE", + grant_to=CS_VETTED_GATE_ADDRESS, + ) + ]) + ), + ( + "47. Grant CSAccounting role SET_BOND_CURVE_ROLE for the vetted gate", + agent_forward([ + encode_oz_grant_role( + contract=contracts.cs_accounting, + role_name="SET_BOND_CURVE_ROLE", + grant_to=CS_VETTED_GATE_ADDRESS, + ) + ]) + ), + ( + "48. Revoke role VERIFIER_ROLE from the previous instance of the Verifier contract", + agent_forward([ + encode_oz_revoke_role( + contract=contracts.csm, + role_name="VERIFIER_ROLE", + revoke_from=contracts.cs_verifier, + ) + ]) + ), + ( + "49. Grant role VERIFIER_ROLE to the new instance of the Verifier contract", + agent_forward([ + encode_oz_grant_role( + contract=contracts.csm, + role_name="VERIFIER_ROLE", + grant_to=CS_VERIFIER_V2_ADDRESS, + ) + ]) + ), + ( + "50. Revoke CSM role PAUSE_ROLE from the previous GateSeal instance", + agent_forward([ + encode_oz_revoke_role( + contract=contracts.csm, + role_name="PAUSE_ROLE", + revoke_from=CS_GATE_SEAL_ADDRESS, + ) + ]) + ), + ( + "51. Revoke CSAccounting role PAUSE_ROLE from the previous GateSeal instance", + agent_forward([ + encode_oz_revoke_role( + contract=contracts.cs_accounting, + role_name="PAUSE_ROLE", + revoke_from=CS_GATE_SEAL_ADDRESS, + ) + ]) + ), + ( + "52. Revoke CSFeeOracle role PAUSE_ROLE from the previous GateSeal instance", + agent_forward([ + encode_oz_revoke_role( + contract=contracts.cs_fee_oracle, + role_name="PAUSE_ROLE", + revoke_from=CS_GATE_SEAL_ADDRESS, + ) + ]) + ), + ( + "53. Grant CSM role PAUSE_ROLE for the new GateSeal instance", + agent_forward([ + encode_oz_grant_role( + contract=contracts.csm, + role_name="PAUSE_ROLE", + grant_to=CS_GATE_SEAL_V2_ADDRESS, + ) + ]) + ), + ( + "54. Grant CSAccounting role PAUSE_ROLE for the new GateSeal instance", + agent_forward([ + encode_oz_grant_role( + contract=contracts.cs_accounting, + role_name="PAUSE_ROLE", + grant_to=CS_GATE_SEAL_V2_ADDRESS, + ) + ]) + ), + ( + "55. Grant CSFeeOracle role PAUSE_ROLE for the new GateSeal instance", + agent_forward([ + encode_oz_grant_role( + contract=contracts.cs_fee_oracle, + role_name="PAUSE_ROLE", + grant_to=CS_GATE_SEAL_V2_ADDRESS, + ) + ]) + ), + ( + "56. Grant MANAGE_BOND_CURVES_ROLE to the AGENT", + agent_forward([ + encode_oz_grant_role( + contract=contracts.cs_accounting, + role_name="MANAGE_BOND_CURVES_ROLE", + grant_to=contracts.agent, + ) + ]) + ), + ( + "57. Add Identified Community Stakers Gate Bond Curve", + agent_forward([ + ( + contracts.cs_accounting.address, + contracts.cs_accounting.addBondCurve.encode_input(CS_ICS_GATE_BOND_CURVE), + ) + ]) + ), + ( + "58. Revoke MANAGE_BOND_CURVES_ROLE from the AGENT", + agent_forward([ + encode_oz_revoke_role( + contract=contracts.cs_accounting, + role_name="MANAGE_BOND_CURVES_ROLE", + revoke_from=contracts.agent, + ) + ]) + ), + ( + "59. Increase CSM share in Staking Router from 15% to 16%", + agent_forward([encode_staking_router_update_csm_module_share()]) + ), + # --- Gate Seals + ( + "60. Revoke PAUSE_ROLE on WithdrawalQueue from the old GateSeal", + agent_forward([ + encode_oz_revoke_role( + contract=contracts.withdrawal_queue, + role_name="PAUSE_ROLE", + revoke_from=OLD_GATE_SEAL_ADDRESS, + ) + ]) + ), + ( + "61. Revoke PAUSE_ROLE on ValidatorsExitBusOracle from the old GateSeal", + agent_forward([ + encode_oz_revoke_role( + contract=contracts.validators_exit_bus_oracle, + role_name="PAUSE_ROLE", + revoke_from=OLD_GATE_SEAL_ADDRESS, + ) + ]) + ), + ( + "62. Grant PAUSE_ROLE on WithdrawalQueue to the new WithdrawalQueue GateSeal", + agent_forward([ + encode_oz_grant_role( + contract=contracts.withdrawal_queue, + role_name="PAUSE_ROLE", + grant_to=NEW_WQ_GATE_SEAL, + ) + ]) + ), + ( + "63. Grant PAUSE_ROLE on ValidatorsExitBusOracle to the new Triggerable Withdrawals GateSeal", + agent_forward([ + encode_oz_grant_role( + contract=contracts.validators_exit_bus_oracle, + role_name="PAUSE_ROLE", + grant_to=NEW_TW_GATE_SEAL, + ) + ]) + ), + ( + "64. Grant PAUSE_ROLE on TriggerableWithdrawalsGateway to the new Triggerable Withdrawals GateSeal", + agent_forward([ + encode_oz_grant_role( + contract=interface.TriggerableWithdrawalsGateway(TRIGGERABLE_WITHDRAWALS_GATEWAY), + role_name="PAUSE_ROLE", + grant_to=NEW_TW_GATE_SEAL, + ) + ]) + ), + ( + "65. Grant PAUSE_ROLE on TriggerableWithdrawalsGateway to ResealManager", + agent_forward([ + encode_oz_grant_role( + contract=interface.TriggerableWithdrawalsGateway(TRIGGERABLE_WITHDRAWALS_GATEWAY), + role_name="PAUSE_ROLE", + grant_to=RESEAL_MANAGER, + ) + ]) + ), + ( + "66. Grant RESUME_ROLE on TriggerableWithdrawalsGateway to ResealManager", + agent_forward([ + encode_oz_grant_role( + contract=interface.TriggerableWithdrawalsGateway(TRIGGERABLE_WITHDRAWALS_GATEWAY), + role_name="RESUME_ROLE", + grant_to=RESEAL_MANAGER, + ) + ]) + ), + ) + + dg_bypass_item = { + "67. Add CSSetVettedGateTree factory to EasyTrack with permissions": add_evmscript_factory( + factory=EASYTRACK_CS_SET_VETTED_GATE_TREE_FACTORY, + permissions=(create_permissions(interface.CSVettedGate(CS_VETTED_GATE_ADDRESS), "setTreeParams")), + ), + "68. Add `SubmitValidatorsExitRequestHashes` (SDVT) EVM script factory to Easy Track": add_evmscript_factory( + factory=EASYTRACK_SDVT_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY, + permissions=(create_permissions(contracts.validators_exit_bus_oracle, "submitExitRequestsHash")), + ), + "69. Add `SubmitValidatorsExitRequestHashes` (Curated Module) EVM script factory to Easy Track": add_evmscript_factory( + factory=EASYTRACK_CURATED_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY, + permissions=(create_permissions(contracts.validators_exit_bus_oracle, "submitExitRequestsHash")), + ) + } + + if silent: + desc_ipfs = calculate_vote_ipfs_description(DESCRIPTION) + else: + desc_ipfs = upload_vote_ipfs_description(DESCRIPTION) + + dg_desc = "\n".join(vote_desc_items) + + dg_vote = prepare_proposal(call_script_items, dg_desc) + vote_items = {dg_desc: dg_vote, **dg_bypass_item} + + assert confirm_vote_script(vote_items, silent, desc_ipfs) + + return create_vote(vote_items, tx_params, desc_ipfs=desc_ipfs) + +def prepare_proposal( + call_script: Sequence[Tuple], + description: Optional[str] = "", +) -> Tuple[str, str]: + dual_governance = contracts.dual_governance + forwarded = [] + + for _call in call_script: + forwarded.append((_call[0], _call[1])) + + print(f"Forwarding call script to dual governance: {forwarded}") + return ( + contracts.dual_governance.address, + dual_governance.submitProposal.encode_input([(_call[0], 0, _call[1]) for _call in forwarded], description), + ) + +def main(): + tx_params = {"from": get_deployer_account()} + if get_is_live(): + tx_params["priority_fee"] = get_priority_fee() + + vote_id, _ = start_vote(tx_params=tx_params, silent=False) + + vote_id >= 0 and print(f"Vote created: {vote_id}.") + + time.sleep(5) # hack for waiting thread #2. diff --git a/archive/scripts/vote_update_sandbox_impl_holesky.py b/archive/scripts/vote_update_sandbox_impl_holesky.py new file mode 100644 index 000000000..00d0bbf34 --- /dev/null +++ b/archive/scripts/vote_update_sandbox_impl_holesky.py @@ -0,0 +1,102 @@ +""" +Vote XX/06/2025 [HOLESKY] + +1. Grant APP_MANAGER_ROLE role to the AGENT +2. Update `Sandbox Module` implementation +3. Call finalizeUpgrade_v4 on `Sandbox Module` +4. Revoke APP_MANAGER_ROLE role from the AGENT +""" +import time + +from typing import Any, Dict +from typing import Tuple, Optional +from brownie import interface, web3, convert # type: ignore +from utils.config import ( + ARAGON_KERNEL, + AGENT, + contracts, + get_deployer_account, + get_priority_fee, + get_is_live +) +from utils.ipfs import upload_vote_ipfs_description, calculate_vote_ipfs_description +from utils.agent import dual_governance_agent_forward +from utils.voting import confirm_vote_script, create_vote + +SANDBOX_APP_ID = "0x85d2fceef13a6c14c43527594f79fb91a8ef8f15024a43486efac8df2b11e632" +NODE_OPERATORS_REGISTRY_IMPL = "0x834aa47DCd21A32845099a78B4aBb17A7f0bD503" +NOR_EXIT_DEADLINE_IN_SEC = 172800 + +DESCRIPTION = "Update Sanbox Module Implementation (HOLESKY)" + +def start_vote(tx_params: Dict[str, str], silent: bool) -> Tuple[int, Optional[Any]]: + vote_desc_items, call_script_items = zip( + # --- Update Sanbox Module implementation [TESTNET ONLY] --- + ( + f"1. Grant APP_MANAGER_ROLE role to the AGENT", + ( + contracts.acl.address, + contracts.acl.grantPermission.encode_input( + AGENT, + ARAGON_KERNEL, + convert.to_uint(web3.keccak(text="APP_MANAGER_ROLE")) + ) + ) + ), + ( + f"2. Update `Sandbox Module` implementation", + ( + contracts.kernel.address, + contracts.kernel.setApp.encode_input( + contracts.kernel.APP_BASES_NAMESPACE(), + SANDBOX_APP_ID, + NODE_OPERATORS_REGISTRY_IMPL + ) + ) + ), + ( + f"3. Call finalizeUpgrade_v4 on `Sandbox Module`", + ( + interface.NodeOperatorsRegistry(contracts.sandbox).address, + interface.NodeOperatorsRegistry(contracts.sandbox).finalizeUpgrade_v4.encode_input( + NOR_EXIT_DEADLINE_IN_SEC + ) + ) + ), + ( + f"4. Revoke APP_MANAGER_ROLE role from the AGENT", + ( + contracts.acl.address, + contracts.acl.revokePermission.encode_input( + AGENT, + ARAGON_KERNEL, + convert.to_uint(web3.keccak(text="APP_MANAGER_ROLE")) + ) + ) + ), + ) + + if silent: + desc_ipfs = calculate_vote_ipfs_description(DESCRIPTION) + else: + desc_ipfs = upload_vote_ipfs_description(DESCRIPTION) + + dg_desc = "\n".join(vote_desc_items) + dg_vote = dual_governance_agent_forward(call_script_items, dg_desc) + vote_items = {dg_desc: dg_vote} + + assert confirm_vote_script(vote_items, silent, desc_ipfs) + + return create_vote(vote_items, tx_params, desc_ipfs=desc_ipfs) + + +def main(): + tx_params = {"from": get_deployer_account()} + if get_is_live(): + tx_params["priority_fee"] = get_priority_fee() + + vote_id, _ = start_vote(tx_params=tx_params, silent=False) + + vote_id >= 0 and print(f"Vote created: {vote_id}.") + + time.sleep(5) # hack for waiting thread #2. diff --git a/archive/scripts/vote_update_sandbox_impl_hoodi.py b/archive/scripts/vote_update_sandbox_impl_hoodi.py new file mode 100644 index 000000000..7489916d0 --- /dev/null +++ b/archive/scripts/vote_update_sandbox_impl_hoodi.py @@ -0,0 +1,105 @@ +""" +Vote 23/07/2025 [HOODI] + +1. Grant APP_MANAGER_ROLE role to the AGENT +2. Update `Sandbox Module` implementation +3. Call finalizeUpgrade_v4 on `Sandbox Module` +4. Revoke APP_MANAGER_ROLE role from the AGENT + +Vote passed & executed on Jul-23-2025 01:29:48 PM UTC, block 862773 +""" +import time + +from typing import Any, Dict +from typing import Tuple, Optional +from brownie import interface, web3, convert # type: ignore +from scripts.vote_tw_csm2_hoodi import prepare_proposal +from utils.agent import agent_forward +from utils.config import ( + ARAGON_KERNEL, + AGENT, + contracts, + get_deployer_account, + get_priority_fee, + get_is_live +) +from utils.ipfs import upload_vote_ipfs_description, calculate_vote_ipfs_description +from utils.voting import confirm_vote_script, create_vote + +SANDBOX_APP_ID = "0x85d2fceef13a6c14c43527594f79fb91a8ef8f15024a43486efac8df2b11e632" +NODE_OPERATORS_REGISTRY_IMPL = "0x95F00b016bB31b7182D96D25074684518246E42a" # Updated for Hoodi +NOR_EXIT_DEADLINE_IN_SEC = 172800 # 48 hours in seconds + +DESCRIPTION = "Update Sandbox Module Implementation (HOODI)" + +def start_vote(tx_params: Dict[str, str], silent: bool) -> Tuple[int, Optional[Any]]: + vote_desc_items, call_script_items = zip( + # --- Update Sandbox Module implementation [TESTNET ONLY] --- + ( + f"1. Grant APP_MANAGER_ROLE role to the AGENT", + agent_forward([( + contracts.acl.address, + contracts.acl.grantPermission.encode_input( + AGENT, + ARAGON_KERNEL, + convert.to_uint(web3.keccak(text="APP_MANAGER_ROLE")) + ) + )]) + ), + ( + f"2. Update `Sandbox Module` implementation", + agent_forward([( + contracts.kernel.address, + contracts.kernel.setApp.encode_input( + contracts.kernel.APP_BASES_NAMESPACE(), + SANDBOX_APP_ID, + NODE_OPERATORS_REGISTRY_IMPL + ) + )]) + ), + ( + f"3. Call finalizeUpgrade_v4 on `Sandbox Module`", + agent_forward([( + interface.NodeOperatorsRegistry(contracts.sandbox).address, + interface.NodeOperatorsRegistry(contracts.sandbox).finalizeUpgrade_v4.encode_input( + NOR_EXIT_DEADLINE_IN_SEC + ) + )]), + ), + ( + f"4. Revoke APP_MANAGER_ROLE role from the AGENT", + agent_forward([( + contracts.acl.address, + contracts.acl.revokePermission.encode_input( + AGENT, + ARAGON_KERNEL, + convert.to_uint(web3.keccak(text="APP_MANAGER_ROLE")) + ) + )]), + ), + ) + + if silent: + desc_ipfs = calculate_vote_ipfs_description(DESCRIPTION) + else: + desc_ipfs = upload_vote_ipfs_description(DESCRIPTION) + + dg_desc = "\n".join(vote_desc_items) + dg_vote = prepare_proposal(call_script_items, dg_desc) + vote_items = {dg_desc: dg_vote} + + assert confirm_vote_script(vote_items, silent, desc_ipfs) + + return create_vote(vote_items, tx_params, desc_ipfs=desc_ipfs) + + +def main(): + tx_params = {"from": get_deployer_account()} + if get_is_live(): + tx_params["priority_fee"] = get_priority_fee() + + vote_id, _ = start_vote(tx_params=tx_params, silent=False) + + vote_id >= 0 and print(f"Vote created: {vote_id}.") + + time.sleep(5) # hack for waiting thread #2. diff --git a/archive/tests/test_vote_dg_easy_track_tw_holesky.py b/archive/tests/test_vote_dg_easy_track_tw_holesky.py new file mode 100644 index 000000000..1e04cdfa7 --- /dev/null +++ b/archive/tests/test_vote_dg_easy_track_tw_holesky.py @@ -0,0 +1,78 @@ +from typing import Optional +from scripts.vote_dg_easy_track_tw_holesky import start_vote +from brownie import interface, chain, web3 # type: ignore +from utils.dual_governance import wait_for_noon_utc_to_satisfy_time_constrains +from utils.config import ( + DUAL_GOVERNANCE, + TIMELOCK, + LDO_HOLDER_ADDRESS_FOR_TESTS, + contracts, +) + +# Implementation address from vote script +TRIGGERABLE_WITHDRAWALS_GATEWAY = "0x4FD4113f2B92856B59BC3be77f2943B7F4eaa9a5" + +EASYTRACK_EVMSCRIPT_EXECUTOR = "0x2819B65021E13CEEB9AC33E77DB32c7e64e7520D" + +EASYTRACK_SDVT_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY = "0x4aB23f409F8F6EdeF321C735e941E4670804a1B4" +EASYTRACK_CURATED_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY = "0x7A1c5af4625dc1160a7c67d00335B6Ad492bE53f" + + +def test_vote(helpers, accounts, vote_ids_from_env, stranger): + triggerable_withdrawals_gateway = interface.TriggerableWithdrawalsGateway(TRIGGERABLE_WITHDRAWALS_GATEWAY) + + timelock = interface.EmergencyProtectedTimelock(TIMELOCK) + dual_governance = interface.DualGovernance(DUAL_GOVERNANCE) + submit_exit_hashes_role = web3.keccak(text="SUBMIT_REPORT_HASH_ROLE") + initial_factories = contracts.easy_track.getEVMScriptFactories() + DG_OLD_WITHDRAWAL_BLOCKERS = ( + contracts.withdrawal_queue.address, + contracts.validators_exit_bus_oracle.address, + ) + + DG_NEW_WITHDRAWAL_BLOCKERS = ( + contracts.withdrawal_queue.address, + contracts.validators_exit_bus_oracle.address, + triggerable_withdrawals_gateway.address, + ) + + tiebreaker_details = contracts.dual_governance.getTiebreakerDetails() + assert tiebreaker_details[3] == DG_OLD_WITHDRAWAL_BLOCKERS, "Old withdrawal blockers should be set in Dual Governance before vote" + + + assert not contracts.validators_exit_bus_oracle.hasRole(submit_exit_hashes_role, EASYTRACK_EVMSCRIPT_EXECUTOR) + # SDVT EVM script factory is not in Easy Track + assert EASYTRACK_SDVT_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY not in initial_factories, "EasyTrack should not have SDVT Submit Validator Exit Request Hashes factory before vote" + # Curated EVM script factory is not in Easy Track + assert EASYTRACK_CURATED_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY not in initial_factories, "EasyTrack should not have Curated Submit Validator Exit Request Hashes factory before vote" + # START VOTE + if len(vote_ids_from_env) > 0: + (vote_id,) = vote_ids_from_env + else: + tx_params = {"from": LDO_HOLDER_ADDRESS_FOR_TESTS} + vote_id, _ = start_vote(tx_params, silent=True) + + vote_tx = helpers.execute_vote(accounts, vote_id, contracts.voting) + print(f"voteId = {vote_id}") + + proposal_id = vote_tx.events["ProposalSubmitted"][1]["proposalId"] + print(f"proposalId = {proposal_id}") + + chain.sleep(timelock.getAfterSubmitDelay() + 1) + dual_governance.scheduleProposal(proposal_id, {"from": stranger}) + + chain.sleep(timelock.getAfterScheduleDelay() + 1) + wait_for_noon_utc_to_satisfy_time_constrains() + + dg_tx = timelock.execute(proposal_id, {"from": stranger}) + # Check DG WITHDRAWAL_BLOCKERS + tiebreaker_details = contracts.dual_governance.getTiebreakerDetails() + print(f"tiebreaker_details = {tiebreaker_details[3]}") + assert tiebreaker_details[3] == DG_NEW_WITHDRAWAL_BLOCKERS, "New withdrawal blockers should be set in Dual Governance after vote" + + assert contracts.validators_exit_bus_oracle.hasRole(submit_exit_hashes_role, EASYTRACK_EVMSCRIPT_EXECUTOR) + new_factories = contracts.easy_track.getEVMScriptFactories() + # SDVT EVM script factory is added to Easy Track + assert EASYTRACK_SDVT_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY in new_factories, "EasyTrack should have SDVT Submit Validator Exit Request Hashes factory after vote" + # Curated EVM script factory is added to Easy Track + assert EASYTRACK_CURATED_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY in new_factories, "EasyTrack should have Curated Submit Validator Exit Request Hashes factory after vote" diff --git a/archive/tests/test_vote_tw_csm2_holesky.py b/archive/tests/test_vote_tw_csm2_holesky.py new file mode 100644 index 000000000..70275d18a --- /dev/null +++ b/archive/tests/test_vote_tw_csm2_holesky.py @@ -0,0 +1,938 @@ +from typing import Optional +from scripts.vote_tw_csm2_holesky import start_vote +from brownie import interface, reverts, chain, convert, web3, ZERO_ADDRESS # type: ignore +from brownie.network.event import EventDict +from utils.easy_track import create_permissions +from utils.test.tx_tracing_helpers import group_voting_events_from_receipt, group_dg_events_from_receipt +from utils.test.event_validators.easy_track import validate_evmscript_factory_added_event, EVMScriptFactoryAdded +from utils.test.event_validators.dual_governance import validate_dual_governance_submit_event +from utils.dual_governance import wait_for_noon_utc_to_satisfy_time_constrains +from utils.config import ( + DUAL_GOVERNANCE, + TIMELOCK, + DUAL_GOVERNANCE_EXECUTORS, + LDO_HOLDER_ADDRESS_FOR_TESTS, + CS_MODULE_ID, + CS_MODULE_MODULE_FEE_BP, + CS_MODULE_MAX_DEPOSITS_PER_BLOCK, + CS_MODULE_MIN_DEPOSIT_BLOCK_DISTANCE, + CS_MODULE_TREASURY_FEE_BP, + CS_GATE_SEAL_ADDRESS, + CSM_COMMITTEE_MS, + ARAGON_KERNEL, + AGENT, + VOTING, + contracts, +) + + +def validate_proxy_upgrade_event(event: EventDict, implementation: str, emitted_by: Optional[str] = None): + assert "Upgraded" in event, "No Upgraded event found" + + assert event["Upgraded"][0]["implementation"] == implementation, "Wrong implementation address" + + if emitted_by is not None: + assert convert.to_address(event["Upgraded"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + + +def validate_consensus_version_set_event(event: EventDict, new_version: int, prev_version: int, emitted_by: Optional[str] = None): + assert "ConsensusVersionSet" in event, "No ConsensusVersionSet event found" + + assert event["ConsensusVersionSet"][0]["version"] == new_version, "Wrong new version" + + assert event["ConsensusVersionSet"][0]["prevVersion"] == prev_version, "Wrong previous version" + + if emitted_by is not None: + assert convert.to_address(event["ConsensusVersionSet"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + + +def validate_role_grant_event(event: EventDict, role_hash: str, account: str, emitted_by: Optional[str] = None): + assert "RoleGranted" in event, "No RoleGranted event found" + + # Strip 0x prefix for consistent comparison + expected_role_hash = role_hash.replace('0x', '') + actual_role_hash = event["RoleGranted"][0]["role"].hex().replace('0x', '') + + assert actual_role_hash == expected_role_hash, "Wrong role hash" + + assert convert.to_address(event["RoleGranted"][0]["account"]) == convert.to_address(account), "Wrong account" + + if emitted_by is not None: + assert convert.to_address(event["RoleGranted"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + + +def validate_role_revoke_event(event: EventDict, role_hash: str, account: str, emitted_by: Optional[str] = None): + assert "RoleRevoked" in event, "No RoleRevoked event found" + + # Strip 0x prefix for consistent comparison + expected_role_hash = role_hash.replace('0x', '') + actual_role_hash = event["RoleRevoked"][0]["role"].hex().replace('0x', '') + + assert actual_role_hash == expected_role_hash, "Wrong role hash" + + assert convert.to_address(event["RoleRevoked"][0]["account"]) == convert.to_address(account), "Wrong account" + + if emitted_by is not None: + assert convert.to_address(event["RoleRevoked"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + + +def validate_contract_version_set_event(event: EventDict, version: int, emitted_by: Optional[str] = None): + assert "ContractVersionSet" in event, "No ContractVersionSet event found" + + assert event["ContractVersionSet"][0]["version"] == version, "Wrong version" + + if emitted_by is not None: + assert convert.to_address(event["ContractVersionSet"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + + +def validate_bond_curve_added_event(event: EventDict, curve_id: int, emitted_by: Optional[str] = None): + assert "BondCurveAdded" in event, "No BondCurveAdded event found" + + assert event["BondCurveAdded"][0]["curveId"] == curve_id, "Wrong curve ID" + + if emitted_by is not None: + assert convert.to_address(event["BondCurveAdded"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + + +def validate_staking_module_update_event( + event: EventDict, + module_id: int, + share_limit: int, + priority_share_threshold: int, + module_fee_points_bp: int, + treasury_fee_points_bp: int, + max_deposits_per_block: int, + min_deposit_block_distance: int, + emitted_by: Optional[str] = None +): + assert "StakingModuleShareLimitSet" in event, "No StakingModuleShareLimitSet event found" + assert "StakingModuleFeesSet" in event, "No StakingModuleFeesSet event found" + assert "StakingModuleMaxDepositsPerBlockSet" in event, "No StakingModuleMaxDepositsPerBlockSet event found" + assert "StakingModuleMinDepositBlockDistanceSet" in event, "No StakingModuleMinDepositBlockDistanceSet event found" + + assert len(event["StakingModuleShareLimitSet"]) == 1, "Multiple StakingModuleShareLimitSet events found" + assert len(event["StakingModuleFeesSet"]) == 1, "Multiple StakingModuleFeesSet events found" + assert len(event["StakingModuleMaxDepositsPerBlockSet"]) == 1, "Multiple StakingModuleMaxDepositsPerBlockSet events found" + assert len(event["StakingModuleMinDepositBlockDistanceSet"]) == 1, "Multiple StakingModuleMinDepositBlockDistanceSet events found" + + assert event["StakingModuleShareLimitSet"][0]["stakingModuleId"] == module_id, "Wrong module ID" + assert event["StakingModuleShareLimitSet"][0]["stakeShareLimit"] == share_limit, "Wrong share limit" + assert event["StakingModuleShareLimitSet"][0]["priorityExitShareThreshold"] == priority_share_threshold, "Wrong priority threshold" + + assert event["StakingModuleFeesSet"][0]["stakingModuleFee"] == module_fee_points_bp, "Wrong fee points" + assert event["StakingModuleFeesSet"][0]["treasuryFee"] == treasury_fee_points_bp, "Wrong treasury fee points" + + assert event["StakingModuleMaxDepositsPerBlockSet"][0]["maxDepositsPerBlock"] == max_deposits_per_block, "Wrong max deposits" + + assert event["StakingModuleMinDepositBlockDistanceSet"][0]["minDepositBlockDistance"] == min_deposit_block_distance, "Wrong min distance" + + if emitted_by is not None: + assert convert.to_address(event["StakingModuleShareLimitSet"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + assert convert.to_address(event["StakingModuleFeesSet"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + assert convert.to_address(event["StakingModuleMaxDepositsPerBlockSet"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + assert convert.to_address(event["StakingModuleMinDepositBlockDistanceSet"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + + +def get_ossifiable_proxy_impl(proxy_address): + """Get implementation address from an OssifiableProxy""" + proxy = interface.OssifiableProxy(proxy_address) + return proxy.proxy__getImplementation() + + +def get_wv_contract_proxy_impl(proxy_address): + """Get implementation address from an WithdrawalContractProxy""" + proxy = interface.WithdrawalContractProxy(proxy_address) + return proxy.implementation() + + +def check_proxy_implementation(proxy_address, expected_impl): + """Check that proxy has expected implementation""" + actual_impl = get_ossifiable_proxy_impl(proxy_address) + assert actual_impl == expected_impl, f"Expected impl {expected_impl}, got {actual_impl}" + + +# New core contracts implementations +LIDO_LOCATOR_IMPL = "0xa437ab5614033d071493C88Fd351aFEbc802521f" +ACCOUNTING_ORACLE_IMPL = "0xE63267AAaC507A329213593e8A9bCa37e2994F1C" +VALIDATORS_EXIT_BUS_ORACLE_IMPL = "0xeCE105ABd3F2653398BE75e680dB033A238E2aD6" +WITHDRAWAL_VAULT_IMPL = "0x6aAA28C515E02ED0fe1B51e74323e14E910eA7d7" +STAKING_ROUTER_IMPL = "0xE6E775C6AdF8753588237b1De32f61937bC54341" +NODE_OPERATORS_REGISTRY_IMPL = "0x834aa47DCd21A32845099a78B4aBb17A7f0bD503" + +TRIGGERABLE_WITHDRAWALS_GATEWAY = "0x4FD4113f2B92856B59BC3be77f2943B7F4eaa9a5" +VALIDATOR_EXIT_VERIFIER = "0x9c5da60e54fcae8592132Fc9a67511e686b52BE8" + +# Oracle consensus versions +AO_CONSENSUS_VERSION = 4 +VEBO_CONSENSUS_VERSION = 4 +CSM_CONSENSUS_VERSION = 3 + +EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS = 7 * 7200 + +NOR_EXIT_DEADLINE_IN_SEC = 172800 + +# CSM +CS_MODULE_NEW_TARGET_SHARE_BP = 2000 # 20% +CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP = 2500 # 25% + +CS_ACCOUNTING_IMPL_V2_ADDRESS = "0xbd78207826CfdBE125cFf0a7075EaB90F5f9FCbb" +CS_FEE_DISTRIBUTOR_IMPL_V2_ADDRESS = "0x6e00A87690A1CAF4abb135B549408cEfca2fd6f5" +CS_FEE_ORACLE_IMPL_V2_ADDRESS = "0xD6F44e196A5b4A1C3863Bdd87233465ef42aBB40" +CSM_IMPL_V2_ADDRESS = "0xaF370636f618bC97c8Af2aBC33aAD426b1f4164A" + +CS_GATE_SEAL_V2_ADDRESS = "0x86E4aFE068f30A41f650601Df9A097bc7CddFb76" +CS_SET_VETTED_GATE_TREE_FACTORY = "0x26CDa8f9D84956efC743c8432658Ae9a5B7939da" +CS_EJECTOR_ADDRESS = "0x477589D5A8cB67Bd6682AF3612f99ADB72d09582" +CS_PERMISSIONLESS_GATE_ADDRESS = "0x676626c3940ae32eF1e4F609938F785fF064ee22" +CS_VETTED_GATE_ADDRESS = "0x92A5aB5e4f98e67Fb7295fe439A652d0E51033bf" +CS_VERIFIER_V2_ADDRESS = "0xBC88b4b56A58b33716C3C2e879b4B1F964152AD4" + +CS_DEFAULT_BOND_CURVE = ( + [1, 2 * 10**18], [2, 1.9 * 10**18], [3, 1.8 * 10**18], [4, 1.7 * 10**18], [5, 1.6 * 10**18], [6, 1.5 * 10**18] +) +CS_LEGACY_EA_BOND_CURVE = ( + ([1, 1.5 * 10**18], [2, 1.9 * 10**18], [3, 1.8 * 10**18], [4, 1.7 * 10**18], [5, 1.6 * 10**18], [6, 1.5 * 10**18]) +) +CS_EXTRA_CURVES = [ + ([1, 3 * 10**18], [2, 1.9 * 10**18], [3, 1.8 * 10**18], [4, 1.7 * 10**18], [5, 1.6 * 10**18], [6, 1.5 * 10**18]), + ([1, 4 * 10**18], [2, 1 * 10**18]) +] +CS_CURVES = [CS_DEFAULT_BOND_CURVE, CS_LEGACY_EA_BOND_CURVE, *CS_EXTRA_CURVES] +CS_ICS_GATE_BOND_CURVE = ([1, 1.5 * 10**18], [2, 1.3 * 10**18]) # Identified Community Stakers Gate Bond Curve + +# Contract versions expected after upgrade +CSM_V2_VERSION = 2 +CS_ACCOUNTING_V2_VERSION = 2 +CS_FEE_ORACLE_V2_VERSION = 2 +CS_FEE_DISTRIBUTOR_V2_VERSION = 2 + + +# Add imports for Gate Seal and ResealManager constants +OLD_GATE_SEAL_ADDRESS = "0xAE6eCd77DCC656c5533c4209454Fd56fB46e1778" +NEW_WQ_GATE_SEAL = "0xE900BC859EB750562E1009e912B63743BC877662" +NEW_TW_GATE_SEAL = "0xaEEF47C61f2A9CCe4C4D0363911C5d49e2cFb6f1" +RESEAL_MANAGER = "0x9dE2273f9f1e81145171CcA927EFeE7aCC64c9fb" + +def test_tw_vote(helpers, accounts, vote_ids_from_env, stranger): + # Save original implementations for comparison + locator_impl_before = get_ossifiable_proxy_impl(contracts.lido_locator) + accounting_oracle_impl_before = get_ossifiable_proxy_impl(contracts.accounting_oracle) + vebo_impl_before = get_ossifiable_proxy_impl(contracts.validators_exit_bus_oracle) + withdrawal_vault_impl_before = get_wv_contract_proxy_impl(contracts.withdrawal_vault) + staking_router_impl_before = get_ossifiable_proxy_impl(contracts.staking_router) + + csm_impl_before = get_ossifiable_proxy_impl(contracts.csm.address) + cs_accounting_impl_before = get_ossifiable_proxy_impl(contracts.cs_accounting.address) + cs_fee_oracle_impl_before = get_ossifiable_proxy_impl(contracts.cs_fee_oracle.address) + cs_fee_distributor_impl_before = get_ossifiable_proxy_impl(contracts.cs_fee_distributor.address) + + timelock = interface.EmergencyProtectedTimelock(TIMELOCK) + dual_governance = interface.DualGovernance(DUAL_GOVERNANCE) + + # Not yet used by the protocol, but needed for the test + triggerable_withdrawals_gateway = interface.TriggerableWithdrawalsGateway(TRIGGERABLE_WITHDRAWALS_GATEWAY) + cs_ejector = interface.CSEjector(CS_EJECTOR_ADDRESS) + cs_permissionless_gate = interface.CSPermissionlessGate(CS_PERMISSIONLESS_GATE_ADDRESS) + cs_vetted_gate = interface.CSVettedGate(CS_VETTED_GATE_ADDRESS) + cs_verifier_v2 = interface.CSVerifierV2(CS_VERIFIER_V2_ADDRESS) + + # --- Initial state checks --- + + # Step 1: Check Lido Locator implementation initial state + assert locator_impl_before != LIDO_LOCATOR_IMPL, "Locator implementation should be different before upgrade" + + # Step 2: Check VEBO implementation initial state + assert vebo_impl_before != VALIDATORS_EXIT_BUS_ORACLE_IMPL, "VEBO implementation should be different before upgrade" + + # Step 3: Check VEBO finalizeUpgrade_v2 state + try: + assert contracts.validators_exit_bus_oracle.getMaxValidatorsPerReport() != 600, "VEBO max validators per report should not be 600 before upgrade" + except Exception: + pass # Function might not exist yet + + # Steps 4-6: Check VEBO consensus version management + initial_vebo_consensus_version = contracts.validators_exit_bus_oracle.getConsensusVersion() + assert initial_vebo_consensus_version < VEBO_CONSENSUS_VERSION, f"VEBO consensus version should be less than {VEBO_CONSENSUS_VERSION}" + assert not contracts.validators_exit_bus_oracle.hasRole(contracts.validators_exit_bus_oracle.MANAGE_CONSENSUS_VERSION_ROLE(), contracts.validators_exit_bus_oracle), "Agent should not have MANAGE_CONSENSUS_VERSION_ROLE on VEBO before upgrade" + + # Step 7: Check TWG role for CS Ejector initial state + add_full_withdrawal_request_role = triggerable_withdrawals_gateway.ADD_FULL_WITHDRAWAL_REQUEST_ROLE() + assert not triggerable_withdrawals_gateway.hasRole(add_full_withdrawal_request_role, cs_ejector), "CS Ejector should not have ADD_FULL_WITHDRAWAL_REQUEST_ROLE before upgrade" + + # Step 8: Check TWG role for VEB initial state + assert not triggerable_withdrawals_gateway.hasRole(add_full_withdrawal_request_role, contracts.validators_exit_bus_oracle), "VEBO should not have ADD_FULL_WITHDRAWAL_REQUEST_ROLE before upgrade" + + # Step 9: Check Withdrawal Vault implementation initial state + assert withdrawal_vault_impl_before != WITHDRAWAL_VAULT_IMPL, "Withdrawal Vault implementation should be different before upgrade" + + # Step 10: Withdrawal Vault finalizeUpgrade_v2 check is done post-execution + assert contracts.withdrawal_vault.getContractVersion() == 1, "Withdrawal Vault version should be 1 before upgrade" + + # Step 11: Check Accounting Oracle implementation initial state + assert accounting_oracle_impl_before != ACCOUNTING_ORACLE_IMPL, "Accounting Oracle implementation should be different before upgrade" + + # Steps 12-14: Check AO consensus version management + initial_ao_consensus_version = contracts.accounting_oracle.getConsensusVersion() + assert initial_ao_consensus_version < AO_CONSENSUS_VERSION, f"AO consensus version should be less than {AO_CONSENSUS_VERSION}" + assert not contracts.accounting_oracle.hasRole(contracts.accounting_oracle.MANAGE_CONSENSUS_VERSION_ROLE(), contracts.agent), "Agent should not have MANAGE_CONSENSUS_VERSION_ROLE on AO before upgrade" + assert contracts.accounting_oracle.getContractVersion() == 2, "Accounting Oracle version should be 2 before upgrade" + # Step 15: Check Staking Router implementation initial state + assert staking_router_impl_before != STAKING_ROUTER_IMPL, "Staking Router implementation should be different before upgrade" + + # Steps 16-17: Check SR roles initial state + try: + report_validator_exiting_status_role = contracts.staking_router.REPORT_VALIDATOR_EXITING_STATUS_ROLE() + report_validator_exit_triggered_role = contracts.staking_router.REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE() + except Exception as e: + assert "Unknown typed error: 0x" in str(e), f"Unexpected error: {e}" + report_validator_exiting_status_role = ZERO_ADDRESS + report_validator_exit_triggered_role = ZERO_ADDRESS + + assert report_validator_exiting_status_role == ZERO_ADDRESS, "REPORT_VALIDATOR_EXITING_STATUS_ROLE should not exist before upgrade" + assert report_validator_exit_triggered_role == ZERO_ADDRESS, "REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE should not exist before upgrade" + + # Step 18: Check APP_MANAGER_ROLE initial state + app_manager_role = web3.keccak(text="APP_MANAGER_ROLE") + assert contracts.acl.getPermissionManager(ARAGON_KERNEL, app_manager_role) == AGENT, "AGENT should be the permission manager for APP_MANAGER_ROLE" + assert contracts.node_operators_registry.kernel() == ARAGON_KERNEL, "Node Operators Registry must use the correct kernel" + assert not contracts.acl.hasPermission(VOTING, ARAGON_KERNEL, app_manager_role), "VOTING should not have APP_MANAGER_ROLE before the upgrade" + assert not contracts.acl.hasPermission(AGENT, ARAGON_KERNEL, app_manager_role), "AGENT should not have APP_MANAGER_ROLE before the upgrade" + + # Steps 19-23: Check NOR and sDVT initial state + assert not contracts.acl.hasPermission(contracts.agent, contracts.kernel, app_manager_role), "Agent should not have APP_MANAGER_ROLE before upgrade" + assert contracts.node_operators_registry.getContractVersion() == 3, "Node Operators Registry version should be 3 before upgrade" + assert contracts.simple_dvt.getContractVersion() == 3, "Simple DVT version should be 3 before upgrade" + + # Step 24: Check CONFIG_MANAGER_ROLE initial state + config_manager_role = contracts.oracle_daemon_config.CONFIG_MANAGER_ROLE() + assert not contracts.oracle_daemon_config.hasRole(config_manager_role, contracts.agent), "Agent should not have CONFIG_MANAGER_ROLE on Oracle Daemon Config before upgrade" + + # Steps 25-27: Check Oracle Daemon Config variables to be removed + try: + contracts.oracle_daemon_config.get('NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP') + contracts.oracle_daemon_config.get('VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS') + contracts.oracle_daemon_config.get('VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS') + except Exception as e: + assert False, f"Expected variables to exist before removal: {e}" + + # Step 28: Check that EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS doesn't exist yet + try: + contracts.oracle_daemon_config.get('EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS') + assert False, "EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS should not exist before vote" + except Exception: + pass # Expected to fail + + # Step 29: Check CSM implementation initial state + assert csm_impl_before != CSM_IMPL_V2_ADDRESS, "CSM implementation should be different before vote" + + # Step 30: Check CSM finalizeUpgradeV2 initial state + with reverts(): + # The function should not exist yet + contracts.csm.getInitializedVersion() + + # CSM Step 32: Check CSAccounting implementation (pre-vote state) + assert cs_accounting_impl_before != CS_ACCOUNTING_IMPL_V2_ADDRESS, "CSAccounting implementation should be different before vote" + + # CSM Step 33: Check CSAccounting finalizeUpgradeV2 was not called (pre-vote state) + with reverts(): + # The function should not exist yet + contracts.cs_accounting.getInitializedVersion() + + # CSM Step 34: Check CSFeeOracle implementation (pre-vote state) + assert cs_fee_oracle_impl_before != CS_FEE_ORACLE_IMPL_V2_ADDRESS, "CSFeeOracle implementation should be different before vote" + + # CSM Step 35: Check CSFeeOracle finalizeUpgradeV2 was not called (pre-vote state) + assert contracts.cs_fee_oracle.getContractVersion() < CS_FEE_ORACLE_V2_VERSION, f"CSFeeOracle version should be less than {CS_FEE_ORACLE_V2_VERSION} before vote" + assert contracts.cs_fee_oracle.getConsensusVersion() < 3, "CSFeeOracle consensus version should be less than 3 before vote" + + # CSM Step 36: Check CSFeeDistributor implementation (pre-vote state) + assert cs_fee_distributor_impl_before != CS_FEE_DISTRIBUTOR_IMPL_V2_ADDRESS, "CSFeeDistributor implementation should be different before vote" + + # CSM Step 37: Check CSFeeDistributor finalizeUpgradeV2 was not called (pre-vote state) + with reverts(): + # The function should not exist yet + contracts.cs_fee_distributor.getInitializedVersion() + + # CSM Steps 38-40: CSAccounting roles (pre-vote state) + assert contracts.cs_accounting.hasRole(contracts.cs_accounting.SET_BOND_CURVE_ROLE(), contracts.csm.address), "CSM should have SET_BOND_CURVE_ROLE on CSAccounting before vote" + assert contracts.cs_accounting.hasRole(web3.keccak(text="RESET_BOND_CURVE_ROLE"), contracts.csm.address), "CSM should have RESET_BOND_CURVE_ROLE on CSAccounting before vote" + assert contracts.cs_accounting.hasRole(web3.keccak(text="RESET_BOND_CURVE_ROLE"), CSM_COMMITTEE_MS), "CSM committee should have RESET_BOND_CURVE_ROLE on CSAccounting before vote" + + # CSM Steps 41-42: CSM roles (pre-vote state) + assert not contracts.csm.hasRole(web3.keccak(text="CREATE_NODE_OPERATOR_ROLE"), cs_permissionless_gate.address), "Permissionless gate should not have CREATE_NODE_OPERATOR_ROLE on CSM before vote" + assert not contracts.csm.hasRole(web3.keccak(text="CREATE_NODE_OPERATOR_ROLE"), cs_vetted_gate.address), "Vetted gate should not have CREATE_NODE_OPERATOR_ROLE on CSM before vote" + + # CSM Step 43: CSAccounting bond curve role for vetted gate (pre-vote state) + assert not contracts.cs_accounting.hasRole(contracts.cs_accounting.SET_BOND_CURVE_ROLE(), cs_vetted_gate.address), "Vetted gate should not have SET_BOND_CURVE_ROLE on CSAccounting before vote" + + # CSM Steps 44-45: Verifier roles (pre-vote state) + assert contracts.csm.hasRole(contracts.csm.VERIFIER_ROLE(), contracts.cs_verifier.address), "Old verifier should have VERIFIER_ROLE on CSM before vote" + assert not contracts.csm.hasRole(contracts.csm.VERIFIER_ROLE(), cs_verifier_v2.address), "New verifier should not have VERIFIER_ROLE on CSM before vote" + + # CSM Steps 46-51: GateSeal roles (pre-vote state) + assert contracts.csm.hasRole(contracts.csm.PAUSE_ROLE(), CS_GATE_SEAL_ADDRESS), "Old GateSeal should have PAUSE_ROLE on CSM before vote" + assert contracts.cs_accounting.hasRole(contracts.cs_accounting.PAUSE_ROLE(), CS_GATE_SEAL_ADDRESS), "Old GateSeal should have PAUSE_ROLE on CSAccounting before vote" + assert contracts.cs_fee_oracle.hasRole(contracts.cs_fee_oracle.PAUSE_ROLE(), CS_GATE_SEAL_ADDRESS), "Old GateSeal should have PAUSE_ROLE on CSFeeOracle before vote" + + assert not contracts.csm.hasRole(contracts.csm.PAUSE_ROLE(), CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should not have PAUSE_ROLE on CSM before vote" + assert not contracts.cs_accounting.hasRole(contracts.cs_accounting.PAUSE_ROLE(), CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should not have PAUSE_ROLE on CSAccounting before vote" + assert not contracts.cs_fee_oracle.hasRole(contracts.cs_fee_oracle.PAUSE_ROLE(), CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should not have PAUSE_ROLE on CSFeeOracle before vote" + + # CSM Step 52: Staking Router CSM module state before vote (pre-vote state) + csm_module_before = contracts.staking_router.getStakingModule(CS_MODULE_ID) + csm_share_before = csm_module_before['stakeShareLimit'] + csm_priority_exit_threshold_before = csm_module_before['priorityExitShareThreshold'] + assert csm_share_before != CS_MODULE_NEW_TARGET_SHARE_BP, f"CSM share should not be {CS_MODULE_NEW_TARGET_SHARE_BP} before vote, current: {csm_share_before}" + assert csm_priority_exit_threshold_before != CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP, f"CSM priority exit threshold should not be {CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP} before vote, current: {csm_priority_exit_threshold_before}" + + # CSM Step 53: EasyTrack factories before vote (pre-vote state) + initial_factories = contracts.easy_track.getEVMScriptFactories() + assert CS_SET_VETTED_GATE_TREE_FACTORY not in initial_factories, "EasyTrack should not have CSMSetVettedGateTree factory before vote" + + # Steps 55-56: Check that old GateSeal has PAUSE_ROLE initially + assert contracts.withdrawal_queue.hasRole(contracts.withdrawal_queue.PAUSE_ROLE(), OLD_GATE_SEAL_ADDRESS), "Old GateSeal should have PAUSE_ROLE on WithdrawalQueue before vote" + assert contracts.validators_exit_bus_oracle.hasRole(contracts.validators_exit_bus_oracle.PAUSE_ROLE(), OLD_GATE_SEAL_ADDRESS), "Old GateSeal should have PAUSE_ROLE on VEBO before vote" + + # Steps 57-59: Check new Gate Seals don't have roles yet + assert not contracts.withdrawal_queue.hasRole(contracts.withdrawal_queue.PAUSE_ROLE(), NEW_WQ_GATE_SEAL), "New WQ GateSeal should not have PAUSE_ROLE on WithdrawalQueue before vote" + assert not contracts.validators_exit_bus_oracle.hasRole(contracts.validators_exit_bus_oracle.PAUSE_ROLE(), NEW_TW_GATE_SEAL), "New TW GateSeal should not have PAUSE_ROLE on VEBO before vote" + assert not triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.PAUSE_ROLE(), NEW_TW_GATE_SEAL), "New TW GateSeal should not have PAUSE_ROLE on TWG before vote" + + # Steps 60-65: Check ResealManager doesn't have roles yet + # There should already be a role granted on the network for all contracts except TWG + assert contracts.withdrawal_queue.hasRole(contracts.withdrawal_queue.PAUSE_ROLE(), RESEAL_MANAGER), "ResealManager should have PAUSE_ROLE on WithdrawalQueue after vote" + assert contracts.validators_exit_bus_oracle.hasRole(contracts.validators_exit_bus_oracle.PAUSE_ROLE(), RESEAL_MANAGER), "ResealManager should have PAUSE_ROLE on VEBO after vote" + assert not triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.PAUSE_ROLE(), RESEAL_MANAGER), "ResealManager should have PAUSE_ROLE on TWG after vote" + assert contracts.withdrawal_queue.hasRole(contracts.withdrawal_queue.RESUME_ROLE(), RESEAL_MANAGER), "ResealManager should have RESUME_ROLE on WithdrawalQueue after vote" + assert contracts.validators_exit_bus_oracle.hasRole(contracts.validators_exit_bus_oracle.RESUME_ROLE(), RESEAL_MANAGER), "ResealManager should have RESUME_ROLE on VEBO after vote" + assert not triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.RESUME_ROLE(), RESEAL_MANAGER), "ResealManager should have RESUME_ROLE on TWG after vote" + + # START VOTE + if len(vote_ids_from_env) > 0: + (vote_id,) = vote_ids_from_env + else: + tx_params = {"from": LDO_HOLDER_ADDRESS_FOR_TESTS} + vote_id, _ = start_vote(tx_params, silent=True) + + vote_tx = helpers.execute_vote(accounts, vote_id, contracts.voting) + print(f"voteId = {vote_id}") + + proposal_id = vote_tx.events["ProposalSubmitted"][1]["proposalId"] + print(f"proposalId = {proposal_id}") + + chain.sleep(timelock.getAfterSubmitDelay() + 1) + dual_governance.scheduleProposal(proposal_id, {"from": stranger}) + + chain.sleep(timelock.getAfterScheduleDelay() + 1) + wait_for_noon_utc_to_satisfy_time_constrains() + + dg_tx = timelock.execute(proposal_id, {"from": stranger}) + + # --- VALIDATE EXECUTION RESULTS --- + + # Step 1: Validate Lido Locator implementation was updated + assert get_ossifiable_proxy_impl(contracts.lido_locator) == LIDO_LOCATOR_IMPL, "Locator implementation should be updated to the new value" + + # Step 2-3: Validate VEBO implementation was updated and configured + assert get_ossifiable_proxy_impl(contracts.validators_exit_bus_oracle) == VALIDATORS_EXIT_BUS_ORACLE_IMPL, "VEBO implementation should be updated" + assert contracts.validators_exit_bus_oracle.getMaxValidatorsPerReport() == 600, "VEBO max validators per report should be set to 600" + + # Validate exit request limit parameters from finalizeUpgrade_v2 call + exit_request_limits = contracts.validators_exit_bus_oracle.getExitRequestLimitFullInfo() + assert exit_request_limits[0] == 11200, "maxExitRequestsLimit should be 11200" + assert exit_request_limits[1] == 1, "exitsPerFrame should be 1" + assert exit_request_limits[2] == 48, "frameDurationInSec should be 48 hours in seconds" + + # Steps 4-6: Validate VEBO consensus version management + assert not contracts.validators_exit_bus_oracle.hasRole(contracts.validators_exit_bus_oracle.MANAGE_CONSENSUS_VERSION_ROLE(), contracts.agent), "Agent should not have MANAGE_CONSENSUS_VERSION_ROLE on VEBO" + assert contracts.validators_exit_bus_oracle.getConsensusVersion() == VEBO_CONSENSUS_VERSION, f"VEBO consensus version should be set to {VEBO_CONSENSUS_VERSION}" + + # Steps 7-8: Validate TWG roles + assert triggerable_withdrawals_gateway.hasRole(add_full_withdrawal_request_role, cs_ejector), "CS Ejector should have ADD_FULL_WITHDRAWAL_REQUEST_ROLE on TWG" + assert triggerable_withdrawals_gateway.hasRole(add_full_withdrawal_request_role, contracts.validators_exit_bus_oracle), "VEBO should have ADD_FULL_WITHDRAWAL_REQUEST_ROLE on TWG" + + # Steps 9-10: Validate Withdrawal Vault upgrade + assert get_wv_contract_proxy_impl(contracts.withdrawal_vault) == WITHDRAWAL_VAULT_IMPL, "Withdrawal Vault implementation should be updated" + assert contracts.withdrawal_vault.getContractVersion() == 2, "Withdrawal Vault version should be 2 after finalizeUpgrade_v2" + + # Steps 11-14: Validate Accounting Oracle upgrade + assert get_ossifiable_proxy_impl(contracts.accounting_oracle) == ACCOUNTING_ORACLE_IMPL, "Accounting Oracle implementation should be updated" + assert not contracts.accounting_oracle.hasRole(contracts.accounting_oracle.MANAGE_CONSENSUS_VERSION_ROLE(), contracts.agent), "Agent should not have MANAGE_CONSENSUS_VERSION_ROLE on AO" + assert contracts.accounting_oracle.getConsensusVersion() == AO_CONSENSUS_VERSION, f"AO consensus version should be set to {AO_CONSENSUS_VERSION}" + assert contracts.accounting_oracle.getContractVersion() == 3, "Accounting Oracle version should be updated to 3" + # Steps 15-17: Validate Staking Router upgrade + assert get_ossifiable_proxy_impl(contracts.staking_router) == STAKING_ROUTER_IMPL, "Staking Router implementation should be updated" + assert contracts.staking_router.hasRole(contracts.staking_router.REPORT_VALIDATOR_EXITING_STATUS_ROLE(), VALIDATOR_EXIT_VERIFIER), "ValidatorExitVerifier should have REPORT_VALIDATOR_EXITING_STATUS_ROLE on SR" + assert contracts.staking_router.hasRole(contracts.staking_router.REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE(), triggerable_withdrawals_gateway), "TWG should have REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE on SR" + + # Steps 18-23: Validate NOR and sDVT updates + assert not contracts.acl.hasPermission(contracts.agent, contracts.kernel, app_manager_role), "Agent should not have APP_MANAGER_ROLE after vote" + assert contracts.node_operators_registry.getContractVersion() == 4, "Node Operators Registry version should be updated to 4" + assert contracts.simple_dvt.getContractVersion() == 4, "Simple DVT version should be updated to 4" + assert contracts.node_operators_registry.exitDeadlineThreshold(0) == NOR_EXIT_DEADLINE_IN_SEC, "NOR exit deadline threshold should be set correctly" + assert contracts.simple_dvt.exitDeadlineThreshold(0) == NOR_EXIT_DEADLINE_IN_SEC, "sDVT exit deadline threshold should be set correctly" + + # Steps 24-28: Validate Oracle Daemon Config changes + assert contracts.oracle_daemon_config.hasRole(config_manager_role, contracts.agent), "Agent should have CONFIG_MANAGER_ROLE on Oracle Daemon Config" + for var_name in ['NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP', 'VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS', 'VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS']: + try: + contracts.oracle_daemon_config.get(var_name) + assert False, f"Variable {var_name} should have been removed" + except Exception: + pass # Expected to fail - variable should be removed + assert convert.to_uint(contracts.oracle_daemon_config.get('EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS')) == EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS, f"EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS should be set to {EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS}" + + # Step 29: Validate CSM implementation upgrade + check_proxy_implementation(contracts.csm.address, CSM_IMPL_V2_ADDRESS) + + # Step 30: Validate CSM finalizeUpgradeV2 was called + assert contracts.csm.getInitializedVersion() == CSM_V2_VERSION, f"CSM version should be {CSM_V2_VERSION} after vote" + + # Step 31: Validate CSAccounting implementation upgrade + check_proxy_implementation(contracts.cs_accounting.address, CS_ACCOUNTING_IMPL_V2_ADDRESS) + + # Step 32: Validate CSAccounting finalizeUpgradeV2 was called with bond curves + assert contracts.cs_accounting.getInitializedVersion() == CS_ACCOUNTING_V2_VERSION, f"CSAccounting version should be {CS_ACCOUNTING_V2_VERSION} after vote" + + # Step 33: Validate CSFeeOracle implementation upgrade + check_proxy_implementation(contracts.cs_fee_oracle.address, CS_FEE_ORACLE_IMPL_V2_ADDRESS) + + # Step 34: Validate CSFeeOracle finalizeUpgradeV2 was called with consensus version 3 + assert contracts.cs_fee_oracle.getContractVersion() == CS_FEE_ORACLE_V2_VERSION, f"CSFeeOracle version should be {CS_FEE_ORACLE_V2_VERSION} after vote" + assert contracts.cs_fee_oracle.getConsensusVersion() == CSM_CONSENSUS_VERSION, "CSFeeOracle consensus version should be 3 after vote" + + # Step 35: Validate CSFeeDistributor implementation upgrade + check_proxy_implementation(contracts.cs_fee_distributor.address, CS_FEE_DISTRIBUTOR_IMPL_V2_ADDRESS) + + # Step 36: Validate CSFeeDistributor finalizeUpgradeV2 was called + assert contracts.cs_fee_distributor.getInitializedVersion() == CS_FEE_DISTRIBUTOR_V2_VERSION, f"CSFeeDistributor version should be {CS_FEE_DISTRIBUTOR_V2_VERSION} after vote" + + # Step 37: Validate SET_BOND_CURVE_ROLE was revoked from CSM on CSAccounting + assert not contracts.cs_accounting.hasRole(contracts.cs_accounting.SET_BOND_CURVE_ROLE(), contracts.csm.address), "CSM should not have SET_BOND_CURVE_ROLE on CSAccounting after vote" + + # Step 38: Validate RESET_BOND_CURVE_ROLE was revoked from CSM on CSAccounting + assert not contracts.cs_accounting.hasRole(web3.keccak(text="RESET_BOND_CURVE_ROLE"), contracts.csm.address), "CSM should not have RESET_BOND_CURVE_ROLE on CSAccounting after vote" + + # Step 39: Validate RESET_BOND_CURVE_ROLE was revoked from CSM committee on CSAccounting + assert not contracts.cs_accounting.hasRole(web3.keccak(text="RESET_BOND_CURVE_ROLE"), CSM_COMMITTEE_MS), "CSM committee should not have RESET_BOND_CURVE_ROLE on CSAccounting after vote" + + # Step 40: Validate CREATE_NODE_OPERATOR_ROLE was granted to permissionless gate on CSM + assert contracts.csm.hasRole(contracts.csm.CREATE_NODE_OPERATOR_ROLE(), cs_permissionless_gate.address), "Permissionless gate should have CREATE_NODE_OPERATOR_ROLE on CSM after vote" + + # Step 41: Validate CREATE_NODE_OPERATOR_ROLE was granted to vetted gate on CSM + assert contracts.csm.hasRole(contracts.csm.CREATE_NODE_OPERATOR_ROLE(), cs_vetted_gate.address), "Vetted gate should have CREATE_NODE_OPERATOR_ROLE on CSM after vote" + + # Step 42: Validate SET_BOND_CURVE_ROLE was granted to vetted gate on CSAccounting + assert contracts.cs_accounting.hasRole(contracts.cs_accounting.SET_BOND_CURVE_ROLE(), cs_vetted_gate.address), "Vetted gate should have SET_BOND_CURVE_ROLE on CSAccounting after vote" + + # Step 43: Validate VERIFIER_ROLE was revoked from old verifier on CSM + assert not contracts.csm.hasRole(contracts.csm.VERIFIER_ROLE(), contracts.cs_verifier.address), "Old verifier should not have VERIFIER_ROLE on CSM after vote" + + # Step 44: Validate VERIFIER_ROLE was granted to new verifier on CSM + assert contracts.csm.hasRole(contracts.csm.VERIFIER_ROLE(), cs_verifier_v2.address), "New verifier should have VERIFIER_ROLE on CSM after vote" + + # Step 45: Validate PAUSE_ROLE was revoked from old GateSeal on CSM + assert not contracts.csm.hasRole(contracts.csm.PAUSE_ROLE(), CS_GATE_SEAL_ADDRESS), "Old GateSeal should not have PAUSE_ROLE on CSM after vote" + + # Step 46: Validate PAUSE_ROLE was revoked from old GateSeal on CSAccounting + assert not contracts.cs_accounting.hasRole(contracts.cs_accounting.PAUSE_ROLE(), CS_GATE_SEAL_ADDRESS), "Old GateSeal should not have PAUSE_ROLE on CSAccounting after vote" + + # Step 47: Validate PAUSE_ROLE was revoked from old GateSeal on CSFeeOracle + assert not contracts.cs_fee_oracle.hasRole(contracts.cs_fee_oracle.PAUSE_ROLE(), CS_GATE_SEAL_ADDRESS), "Old GateSeal should not have PAUSE_ROLE on CSFeeOracle after vote" + + # Step 48: Validate PAUSE_ROLE was granted to new GateSeal on CSM + assert contracts.csm.hasRole(contracts.csm.PAUSE_ROLE(), CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should have PAUSE_ROLE on CSM after vote" + + # Step 49: Validate PAUSE_ROLE was granted to new GateSeal on CSAccounting + assert contracts.cs_accounting.hasRole(contracts.cs_accounting.PAUSE_ROLE(), CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should have PAUSE_ROLE on CSAccounting after vote" + + # Step 50: Validate PAUSE_ROLE was granted to new GateSeal on CSFeeOracle + assert contracts.cs_fee_oracle.hasRole(contracts.cs_fee_oracle.PAUSE_ROLE(), CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should have PAUSE_ROLE on CSFeeOracle after vote" + + # Step 50-52: Check add ICS Bond Curve to CSAccounting + assert not contracts.cs_accounting.hasRole(contracts.cs_accounting.MANAGE_BOND_CURVES_ROLE(), contracts.agent), "Agent should not have MANAGE_BOND_CURVES_ROLE on CSAccounting after vote" + assert contracts.cs_accounting.getCurvesCount() == len(CS_CURVES) + 1, "CSAccounting should have legacy bond curves and ICS Bond Curve after vote" + + # Step 53: Increase CSM share in Staking Router + csm_module_after = contracts.staking_router.getStakingModule(CS_MODULE_ID) + csm_share_after = csm_module_after['stakeShareLimit'] + assert csm_share_after == CS_MODULE_NEW_TARGET_SHARE_BP, f"CSM share should be {CS_MODULE_NEW_TARGET_SHARE_BP} after vote, but got {csm_share_after}" + + csm_priority_exit_threshold_after = csm_module_after['priorityExitShareThreshold'] + assert csm_priority_exit_threshold_after == CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP, f"CSM priority exit threshold should be {CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP} after vote, but got {csm_priority_exit_threshold_after}" + + # Step 54: Add EasyTrack factory for CSSetVettedGateTree + new_factories = contracts.easy_track.getEVMScriptFactories() + assert CS_SET_VETTED_GATE_TREE_FACTORY in new_factories, "EasyTrack should have CSSetVettedGateTree factory after vote" + + # Steps 55-56: Validate old GateSeal no longer has PAUSE_ROLE + assert not contracts.withdrawal_queue.hasRole(contracts.withdrawal_queue.PAUSE_ROLE(), OLD_GATE_SEAL_ADDRESS), "Old GateSeal should not have PAUSE_ROLE on WithdrawalQueue after vote" + assert not contracts.validators_exit_bus_oracle.hasRole(contracts.validators_exit_bus_oracle.PAUSE_ROLE(), OLD_GATE_SEAL_ADDRESS), "Old GateSeal should not have PAUSE_ROLE on VEBO after vote" + + # Steps 57-59: Validate new Gate Seals have PAUSE_ROLE + assert contracts.withdrawal_queue.hasRole(contracts.withdrawal_queue.PAUSE_ROLE(), NEW_WQ_GATE_SEAL), "New WQ GateSeal should have PAUSE_ROLE on WithdrawalQueue after vote" + assert contracts.validators_exit_bus_oracle.hasRole(contracts.validators_exit_bus_oracle.PAUSE_ROLE(), NEW_TW_GATE_SEAL), "New TW GateSeal should have PAUSE_ROLE on VEBO after vote" + assert triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.PAUSE_ROLE(), NEW_TW_GATE_SEAL), "New TW GateSeal should have PAUSE_ROLE on TWG after vote" + + # Steps 60-65: Validate ResealManager has PAUSE_ROLE and RESUME_ROLE + assert contracts.withdrawal_queue.hasRole(contracts.withdrawal_queue.PAUSE_ROLE(), RESEAL_MANAGER), "ResealManager should have PAUSE_ROLE on WithdrawalQueue after vote" + assert contracts.validators_exit_bus_oracle.hasRole(contracts.validators_exit_bus_oracle.PAUSE_ROLE(), RESEAL_MANAGER), "ResealManager should have PAUSE_ROLE on VEBO after vote" + assert triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.PAUSE_ROLE(), RESEAL_MANAGER), "ResealManager should have PAUSE_ROLE on TWG after vote" + assert contracts.withdrawal_queue.hasRole(contracts.withdrawal_queue.RESUME_ROLE(), RESEAL_MANAGER), "ResealManager should have RESUME_ROLE on WithdrawalQueue after vote" + assert contracts.validators_exit_bus_oracle.hasRole(contracts.validators_exit_bus_oracle.RESUME_ROLE(), RESEAL_MANAGER), "ResealManager should have RESUME_ROLE on VEBO after vote" + assert triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.RESUME_ROLE(), RESEAL_MANAGER), "ResealManager should have RESUME_ROLE on TWG after vote" + + # --- VALIDATE EVENTS --- + + voting_events = group_voting_events_from_receipt(vote_tx) + assert len(voting_events) == 2, "Unexpected number of voting events" + dg_voting_event, dg_bypass_voting_event = voting_events + + validate_dual_governance_submit_event( + dg_voting_event, + proposal_id, + proposer=VOTING, + executor=DUAL_GOVERNANCE_EXECUTORS[0], + ) + dg_execution_events = group_dg_events_from_receipt(dg_tx, timelock=TIMELOCK, admin_executor=DUAL_GOVERNANCE_EXECUTORS[0]) + assert len(dg_execution_events) == 62, "Unexpected number of dual governance events" + + # 1. Lido Locator upgrade events + validate_proxy_upgrade_event(dg_execution_events[0], LIDO_LOCATOR_IMPL, emitted_by=contracts.lido_locator) + + # 2. VEBO upgrade events + validate_proxy_upgrade_event(dg_execution_events[1], VALIDATORS_EXIT_BUS_ORACLE_IMPL, emitted_by=contracts.validators_exit_bus_oracle) + + # 3. VEBO finalize upgrade events + validate_contract_version_set_event(dg_execution_events[2], version=2, emitted_by=contracts.validators_exit_bus_oracle) + assert 'ExitRequestsLimitSet' in dg_execution_events[2], "ExitRequestsLimitSet event not found" + assert dg_execution_events[2]['ExitRequestsLimitSet'][0]['maxExitRequestsLimit'] == 11200, "Wrong maxExitRequestsLimit" + assert dg_execution_events[2]['ExitRequestsLimitSet'][0]['exitsPerFrame'] == 1, "Wrong exitsPerFrame" + assert dg_execution_events[2]['ExitRequestsLimitSet'][0]['frameDurationInSec'] == 48, "Wrong frameDurationInSec" + + # 4. Grant VEBO MANAGE_CONSENSUS_VERSION_ROLE to Agent + validate_role_grant_event( + dg_execution_events[3], + role_hash=web3.keccak(text="MANAGE_CONSENSUS_VERSION_ROLE").hex(), + account=contracts.agent.address, + emitted_by=contracts.validators_exit_bus_oracle + ) + + # 5. Set VEBO consensus version to 4 + validate_consensus_version_set_event( + dg_execution_events[4], + new_version=4, + prev_version=3, + emitted_by=contracts.validators_exit_bus_oracle + ) + + # 6. Revoke VEBO MANAGE_CONSENSUS_VERSION_ROLE from Agent + validate_role_revoke_event( + dg_execution_events[5], + role_hash=web3.keccak(text="MANAGE_CONSENSUS_VERSION_ROLE").hex(), + account=contracts.agent.address, + emitted_by=contracts.validators_exit_bus_oracle + ) + + # 7. Grant TWG ADD_FULL_WITHDRAWAL_REQUEST_ROLE to CS Ejector + validate_role_grant_event( + dg_execution_events[6], + role_hash=web3.keccak(text="ADD_FULL_WITHDRAWAL_REQUEST_ROLE").hex(), + account=cs_ejector.address, + emitted_by=triggerable_withdrawals_gateway + ) + + # 8. Grant TWG ADD_FULL_WITHDRAWAL_REQUEST_ROLE to VEBO + validate_role_grant_event( + dg_execution_events[7], + role_hash=web3.keccak(text="ADD_FULL_WITHDRAWAL_REQUEST_ROLE").hex(), + account=contracts.validators_exit_bus_oracle.address, + emitted_by=triggerable_withdrawals_gateway + ) + + # 9. Update WithdrawalVault implementation + validate_proxy_upgrade_event(dg_execution_events[8], WITHDRAWAL_VAULT_IMPL, emitted_by=contracts.withdrawal_vault) + + # 10. Call finalizeUpgrade_v2 on WithdrawalVault + validate_contract_version_set_event(dg_execution_events[9], version=2, emitted_by=contracts.withdrawal_vault) + + # 11. Update AO implementation + validate_proxy_upgrade_event(dg_execution_events[10], ACCOUNTING_ORACLE_IMPL, emitted_by=contracts.accounting_oracle) + + # 12. Grant AO MANAGE_CONSENSUS_VERSION_ROLE to the AGENT + validate_role_grant_event( + dg_execution_events[11], + role_hash=web3.keccak(text="MANAGE_CONSENSUS_VERSION_ROLE").hex(), + account=contracts.agent.address, + emitted_by=contracts.accounting_oracle + ) + + # 13. Bump AO consensus version to 4 + validate_consensus_version_set_event( + dg_execution_events[12], + new_version=4, + prev_version=3, + emitted_by=contracts.accounting_oracle + ) + + # 14. Revoke AO MANAGE_CONSENSUS_VERSION_ROLE from the AGENT + validate_role_revoke_event( + dg_execution_events[13], + role_hash=web3.keccak(text="MANAGE_CONSENSUS_VERSION_ROLE").hex(), + account=contracts.agent.address, + emitted_by=contracts.accounting_oracle + ) + + # 15. Update SR implementation + validate_proxy_upgrade_event(dg_execution_events[14], STAKING_ROUTER_IMPL, emitted_by=contracts.staking_router) + + # 16. Grant SR REPORT_VALIDATOR_EXITING_STATUS_ROLE to ValidatorExitVerifier + validate_role_grant_event( + dg_execution_events[15], + role_hash=web3.keccak(text="REPORT_VALIDATOR_EXITING_STATUS_ROLE").hex(), + account=VALIDATOR_EXIT_VERIFIER, + emitted_by=contracts.staking_router + ) + + # 17. Grant SR REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE to TWG + validate_role_grant_event( + dg_execution_events[16], + role_hash=web3.keccak(text="REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE").hex(), + account=triggerable_withdrawals_gateway.address, + emitted_by=contracts.staking_router + ) + + # 18. Grant APP_MANAGER_ROLE on Kernel to Voting + assert 'SetPermission' in dg_execution_events[17] + assert dg_execution_events[17]['SetPermission'][0]['allowed'] is True + + # 19. Set new implementation for NOR + assert 'SetApp' in dg_execution_events[18] + + # 20. Finalize upgrade for NOR + validate_contract_version_set_event(dg_execution_events[19], version=4, emitted_by=contracts.node_operators_registry) + assert 'ExitDeadlineThresholdChanged' in dg_execution_events[19] + assert dg_execution_events[19]['ExitDeadlineThresholdChanged'][0]['threshold'] == 172800 + + # 21. Set new implementation for sDVT + assert 'SetApp' in dg_execution_events[20] + + # 22. Finalize upgrade for sDVT + validate_contract_version_set_event(dg_execution_events[21], version=4, emitted_by=contracts.simple_dvt) + assert 'ExitDeadlineThresholdChanged' in dg_execution_events[21] + assert dg_execution_events[21]['ExitDeadlineThresholdChanged'][0]['threshold'] == 172800 + + # 23. Revoke APP_MANAGER_ROLE on Kernel from Voting + assert 'SetPermission' in dg_execution_events[22] + assert dg_execution_events[22]['SetPermission'][0]['allowed'] is False + + # 24. Grant CONFIG_MANAGER_ROLE on OracleDaemonConfig to Agent + validate_role_grant_event( + dg_execution_events[23], + role_hash=contracts.oracle_daemon_config.CONFIG_MANAGER_ROLE().hex(), + account=contracts.agent.address, + emitted_by=contracts.oracle_daemon_config + ) + + # 25. Unset NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP + assert 'ConfigValueUnset' in dg_execution_events[24] + assert 'NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP' in dg_execution_events[24]['ConfigValueUnset'][0]['key'] + + # 26. Unset VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS + assert 'ConfigValueUnset' in dg_execution_events[25] + assert 'VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS' in dg_execution_events[25]['ConfigValueUnset'][0]['key'] + + # 27. Unset VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS + assert 'ConfigValueUnset' in dg_execution_events[26] + assert 'VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS' in dg_execution_events[26]['ConfigValueUnset'][0]['key'] + + # 28. Set EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS + assert 'ConfigValueSet' in dg_execution_events[27] + assert 'EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS' in dg_execution_events[27]['ConfigValueSet'][0]['key'] + assert convert.to_int(dg_execution_events[27]['ConfigValueSet'][0]['value']) == EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS + + # 29. CSM implementation upgrade + validate_proxy_upgrade_event(dg_execution_events[28], CSM_IMPL_V2_ADDRESS, emitted_by=contracts.csm) + + # 30. CSM finalize upgrade validation + assert 'Initialized' in dg_execution_events[29] + assert dg_execution_events[29]['Initialized'][0]['version'] == 2 + + # 31. CSAccounting implementation upgrade + validate_proxy_upgrade_event(dg_execution_events[30], CS_ACCOUNTING_IMPL_V2_ADDRESS, emitted_by=contracts.cs_accounting) + + # 32. CSAccounting finalize upgrade with bond curves + assert 'BondCurveAdded' in dg_execution_events[31] + assert len(dg_execution_events[31]['BondCurveAdded']) == len(CS_CURVES) + assert 'Initialized' in dg_execution_events[31] + assert dg_execution_events[31]['Initialized'][0]['version'] == 2 + + # 33. CSFeeOracle implementation upgrade + validate_proxy_upgrade_event(dg_execution_events[32], CS_FEE_ORACLE_IMPL_V2_ADDRESS, emitted_by=contracts.cs_fee_oracle) + + # 34. CSFeeOracle finalize upgrade with consensus version + validate_consensus_version_set_event(dg_execution_events[33], new_version=3, prev_version=2, emitted_by=contracts.cs_fee_oracle) + validate_contract_version_set_event(dg_execution_events[33], version=2, emitted_by=contracts.cs_fee_oracle) + + # 35. CSFeeDistributor implementation upgrade + validate_proxy_upgrade_event(dg_execution_events[34], CS_FEE_DISTRIBUTOR_IMPL_V2_ADDRESS, emitted_by=contracts.cs_fee_distributor) + + # 36. CSFeeDistributor finalize upgrade + assert 'RebateRecipientSet' in dg_execution_events[35] + assert 'Initialized' in dg_execution_events[35] + assert dg_execution_events[35]['Initialized'][0]['version'] == CS_FEE_DISTRIBUTOR_V2_VERSION + + # 37. Revoke SET_BOND_CURVE_ROLE from CSM on CSAccounting + validate_role_revoke_event( + dg_execution_events[36], + role_hash=contracts.cs_accounting.SET_BOND_CURVE_ROLE().hex(), + account=contracts.csm.address, + emitted_by=contracts.cs_accounting + ) + + # 38. Revoke RESET_BOND_CURVE_ROLE from CSM on CSAccounting + validate_role_revoke_event( + dg_execution_events[37], + role_hash=web3.keccak(text="RESET_BOND_CURVE_ROLE").hex(), + account=contracts.csm.address, + emitted_by=contracts.cs_accounting + ) + + # 39. Revoke RESET_BOND_CURVE_ROLE from CSM committee on CSAccounting + validate_role_revoke_event( + dg_execution_events[38], + role_hash=web3.keccak(text="RESET_BOND_CURVE_ROLE").hex(), + account=CSM_COMMITTEE_MS, + emitted_by=contracts.cs_accounting + ) + + # 40. Grant CREATE_NODE_OPERATOR_ROLE to permissionless gate on CSM + validate_role_grant_event( + dg_execution_events[39], + role_hash=contracts.csm.CREATE_NODE_OPERATOR_ROLE().hex(), + account=cs_permissionless_gate.address, + emitted_by=contracts.csm + ) + + # 41. Grant CREATE_NODE_OPERATOR_ROLE to vetted gate on CSM + validate_role_grant_event( + dg_execution_events[40], + role_hash=contracts.csm.CREATE_NODE_OPERATOR_ROLE().hex(), + account=cs_vetted_gate.address, + emitted_by=contracts.csm + ) + + # 42. Grant SET_BOND_CURVE_ROLE to vetted gate on CSAccounting + validate_role_grant_event( + dg_execution_events[41], + role_hash=contracts.cs_accounting.SET_BOND_CURVE_ROLE().hex(), + account=cs_vetted_gate.address, + emitted_by=contracts.cs_accounting + ) + + # 43. Revoke VERIFIER_ROLE from old verifier on CSM + validate_role_revoke_event( + dg_execution_events[42], + role_hash=contracts.csm.VERIFIER_ROLE().hex(), + account=contracts.cs_verifier.address, + emitted_by=contracts.csm + ) + + # 44. Grant VERIFIER_ROLE to new verifier on CSM + validate_role_grant_event( + dg_execution_events[43], + role_hash=contracts.csm.VERIFIER_ROLE().hex(), + account=cs_verifier_v2.address, + emitted_by=contracts.csm + ) + + # 45. Revoke PAUSE_ROLE from old GateSeal on CSM + validate_role_revoke_event( + dg_execution_events[44], + role_hash=contracts.csm.PAUSE_ROLE().hex(), + account=CS_GATE_SEAL_ADDRESS, + emitted_by=contracts.csm + ) + + # 46. Revoke PAUSE_ROLE from old GateSeal on CSAccounting + validate_role_revoke_event( + dg_execution_events[45], + role_hash=contracts.cs_accounting.PAUSE_ROLE().hex(), + account=CS_GATE_SEAL_ADDRESS, + emitted_by=contracts.cs_accounting + ) + + # 47. Revoke PAUSE_ROLE from old GateSeal on CSFeeOracle + validate_role_revoke_event( + dg_execution_events[46], + role_hash=contracts.cs_fee_oracle.PAUSE_ROLE().hex(), + account=CS_GATE_SEAL_ADDRESS, + emitted_by=contracts.cs_fee_oracle + ) + + # 48. Grant PAUSE_ROLE to new GateSeal on CSM + validate_role_grant_event( + dg_execution_events[47], + role_hash=contracts.csm.PAUSE_ROLE().hex(), + account=CS_GATE_SEAL_V2_ADDRESS, + emitted_by=contracts.csm + ) + + # 49. Grant PAUSE_ROLE to new GateSeal on CSAccounting + validate_role_grant_event( + dg_execution_events[48], + role_hash=contracts.cs_accounting.PAUSE_ROLE().hex(), + account=CS_GATE_SEAL_V2_ADDRESS, + emitted_by=contracts.cs_accounting + ) + + # 50. Grant PAUSE_ROLE to new GateSeal on CSFeeOracle + validate_role_grant_event( + dg_execution_events[49], + role_hash=contracts.cs_fee_oracle.PAUSE_ROLE().hex(), + account=CS_GATE_SEAL_V2_ADDRESS, + emitted_by=contracts.cs_fee_oracle + ) + + # 51. Grant MANAGE_BOND_CURVES_ROLE to agent on CSAccounting + validate_role_grant_event( + dg_execution_events[50], + role_hash=contracts.cs_accounting.MANAGE_BOND_CURVES_ROLE().hex(), + account=contracts.agent.address, + emitted_by=contracts.cs_accounting + ) + + # 52. Add ICS bond curve + ics_curve_id = len(CS_CURVES) + validate_bond_curve_added_event(dg_execution_events[51], curve_id=ics_curve_id, emitted_by=contracts.cs_accounting) + + # 53. Revoke MANAGE_BOND_CURVES_ROLE from agent on CSAccounting + validate_role_revoke_event( + dg_execution_events[52], + role_hash=contracts.cs_accounting.MANAGE_BOND_CURVES_ROLE().hex(), + account=contracts.agent.address, + emitted_by=contracts.cs_accounting + ) + + # 54. Increase CSM share in Staking Router + validate_staking_module_update_event( + dg_execution_events[53], + module_id=CS_MODULE_ID, + share_limit=CS_MODULE_NEW_TARGET_SHARE_BP, + priority_share_threshold=CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP, + module_fee_points_bp=CS_MODULE_MODULE_FEE_BP, + treasury_fee_points_bp=CS_MODULE_TREASURY_FEE_BP, + max_deposits_per_block=CS_MODULE_MAX_DEPOSITS_PER_BLOCK, + min_deposit_block_distance=CS_MODULE_MIN_DEPOSIT_BLOCK_DISTANCE, + emitted_by=contracts.staking_router + ) + + # 55. Add EasyTrack factory for CSSetVettedGateTree + validate_evmscript_factory_added_event( + event=dg_bypass_voting_event, + p=EVMScriptFactoryAdded( + factory_addr=CS_SET_VETTED_GATE_TREE_FACTORY, + permissions=create_permissions(cs_vetted_gate, "setTreeParams") + ), + emitted_by=contracts.easy_track, + ) diff --git a/archive/tests/test_vote_tw_csm2_hoodi.py b/archive/tests/test_vote_tw_csm2_hoodi.py new file mode 100644 index 000000000..944009e48 --- /dev/null +++ b/archive/tests/test_vote_tw_csm2_hoodi.py @@ -0,0 +1,1062 @@ +from typing import Optional +from scripts.vote_tw_csm2_hoodi import start_vote +from brownie import interface, reverts, chain, convert, web3, ZERO_ADDRESS # type: ignore +from brownie.network.event import EventDict +from utils.easy_track import create_permissions +from utils.test.tx_tracing_helpers import group_voting_events_from_receipt, group_dg_events_from_receipt +from utils.test.event_validators.easy_track import validate_evmscript_factory_added_event, EVMScriptFactoryAdded +from utils.test.event_validators.dual_governance import validate_dual_governance_submit_event +from utils.dual_governance import wait_for_noon_utc_to_satisfy_time_constrains +from utils.config import ( + DUAL_GOVERNANCE, + TIMELOCK, + DUAL_GOVERNANCE_EXECUTORS, + LDO_HOLDER_ADDRESS_FOR_TESTS, + CS_MODULE_ID, + CS_MODULE_MODULE_FEE_BP, + CS_MODULE_MAX_DEPOSITS_PER_BLOCK, + CS_MODULE_MIN_DEPOSIT_BLOCK_DISTANCE, + CS_MODULE_TREASURY_FEE_BP, + CS_GATE_SEAL_ADDRESS, + CSM_COMMITTEE_MS, + ARAGON_KERNEL, + AGENT, + VOTING, + contracts, +) + + +def validate_proxy_upgrade_event(event: EventDict, implementation: str, emitted_by: Optional[str] = None): + assert "Upgraded" in event, "No Upgraded event found" + + assert event["Upgraded"][0]["implementation"] == implementation, "Wrong implementation address" + + if emitted_by is not None: + assert convert.to_address(event["Upgraded"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + + +def validate_consensus_version_set_event(event: EventDict, new_version: int, prev_version: int, emitted_by: Optional[str] = None): + assert "ConsensusVersionSet" in event, "No ConsensusVersionSet event found" + + assert event["ConsensusVersionSet"][0]["version"] == new_version, "Wrong new version" + + assert event["ConsensusVersionSet"][0]["prevVersion"] == prev_version, "Wrong previous version" + + if emitted_by is not None: + assert convert.to_address(event["ConsensusVersionSet"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + + +def validate_role_grant_event(event: EventDict, role_hash: str, account: str, emitted_by: Optional[str] = None): + assert "RoleGranted" in event, "No RoleGranted event found" + + # Strip 0x prefix for consistent comparison + expected_role_hash = role_hash.replace('0x', '') + actual_role_hash = event["RoleGranted"][0]["role"].hex().replace('0x', '') + + assert actual_role_hash == expected_role_hash, "Wrong role hash" + + assert convert.to_address(event["RoleGranted"][0]["account"]) == convert.to_address(account), "Wrong account" + + if emitted_by is not None: + assert convert.to_address(event["RoleGranted"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + + +def validate_role_revoke_event(event: EventDict, role_hash: str, account: str, emitted_by: Optional[str] = None): + assert "RoleRevoked" in event, "No RoleRevoked event found" + + # Strip 0x prefix for consistent comparison + expected_role_hash = role_hash.replace('0x', '') + actual_role_hash = event["RoleRevoked"][0]["role"].hex().replace('0x', '') + + assert actual_role_hash == expected_role_hash, "Wrong role hash" + + assert convert.to_address(event["RoleRevoked"][0]["account"]) == convert.to_address(account), "Wrong account" + + if emitted_by is not None: + assert convert.to_address(event["RoleRevoked"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + + +def validate_contract_version_set_event(event: EventDict, version: int, emitted_by: Optional[str] = None): + assert "ContractVersionSet" in event, "No ContractVersionSet event found" + + assert event["ContractVersionSet"][0]["version"] == version, "Wrong version" + + if emitted_by is not None: + assert convert.to_address(event["ContractVersionSet"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + + +def validate_bond_curve_added_event(event: EventDict, curve_id: int, emitted_by: Optional[str] = None): + assert "BondCurveAdded" in event, "No BondCurveAdded event found" + + assert event["BondCurveAdded"][0]["curveId"] == curve_id, "Wrong curve ID" + + if emitted_by is not None: + assert convert.to_address(event["BondCurveAdded"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + + +def validate_staking_module_update_event( + event: EventDict, + module_id: int, + share_limit: int, + priority_share_threshold: int, + module_fee_points_bp: int, + treasury_fee_points_bp: int, + max_deposits_per_block: int, + min_deposit_block_distance: int, + emitted_by: Optional[str] = None +): + assert "StakingModuleShareLimitSet" in event, "No StakingModuleShareLimitSet event found" + assert "StakingModuleFeesSet" in event, "No StakingModuleFeesSet event found" + assert "StakingModuleMaxDepositsPerBlockSet" in event, "No StakingModuleMaxDepositsPerBlockSet event found" + assert "StakingModuleMinDepositBlockDistanceSet" in event, "No StakingModuleMinDepositBlockDistanceSet event found" + + assert len(event["StakingModuleShareLimitSet"]) == 1, "Multiple StakingModuleShareLimitSet events found" + assert len(event["StakingModuleFeesSet"]) == 1, "Multiple StakingModuleFeesSet events found" + assert len(event["StakingModuleMaxDepositsPerBlockSet"]) == 1, "Multiple StakingModuleMaxDepositsPerBlockSet events found" + assert len(event["StakingModuleMinDepositBlockDistanceSet"]) == 1, "Multiple StakingModuleMinDepositBlockDistanceSet events found" + + assert event["StakingModuleShareLimitSet"][0]["stakingModuleId"] == module_id, "Wrong module ID" + assert event["StakingModuleShareLimitSet"][0]["stakeShareLimit"] == share_limit, "Wrong share limit" + assert event["StakingModuleShareLimitSet"][0]["priorityExitShareThreshold"] == priority_share_threshold, "Wrong priority threshold" + + assert event["StakingModuleFeesSet"][0]["stakingModuleFee"] == module_fee_points_bp, "Wrong fee points" + assert event["StakingModuleFeesSet"][0]["treasuryFee"] == treasury_fee_points_bp, "Wrong treasury fee points" + + assert event["StakingModuleMaxDepositsPerBlockSet"][0]["maxDepositsPerBlock"] == max_deposits_per_block, "Wrong max deposits" + + assert event["StakingModuleMinDepositBlockDistanceSet"][0]["minDepositBlockDistance"] == min_deposit_block_distance, "Wrong min distance" + + if emitted_by is not None: + assert convert.to_address(event["StakingModuleShareLimitSet"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + assert convert.to_address(event["StakingModuleFeesSet"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + assert convert.to_address(event["StakingModuleMaxDepositsPerBlockSet"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + assert convert.to_address(event["StakingModuleMinDepositBlockDistanceSet"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + + +def get_ossifiable_proxy_impl(proxy_address): + """Get implementation address from an OssifiableProxy""" + proxy = interface.OssifiableProxy(proxy_address) + return proxy.proxy__getImplementation() + + +def get_wv_contract_proxy_impl(proxy_address): + """Get implementation address from an WithdrawalContractProxy""" + proxy = interface.WithdrawalContractProxy(proxy_address) + return proxy.implementation() + + +def check_proxy_implementation(proxy_address, expected_impl): + """Check that proxy has expected implementation""" + actual_impl = get_ossifiable_proxy_impl(proxy_address) + assert actual_impl == expected_impl, f"Expected impl {expected_impl}, got {actual_impl}" + + +# New core contracts implementations +LIDO_LOCATOR_IMPL = "0x003f20CD17e7683A7F88A7AfF004f0C44F0cfB31" +ACCOUNTING_ORACLE_IMPL = "0x2341c9BE0E639f262f8170f9ef1efeCC92cCF617" +VALIDATORS_EXIT_BUS_ORACLE_IMPL = "0x7E6d9C9C44417bf2EaF69685981646e9752D623A" +WITHDRAWAL_VAULT_IMPL = "0xfe7A58960Af333eAdeAeC39149F9d6A71dc3E668" +STAKING_ROUTER_IMPL = "0xd5F04A81ac472B2cB32073CE9dDABa6FaF022827" +NODE_OPERATORS_REGISTRY_IMPL = "0x95F00b016bB31b7182D96D25074684518246E42a" + +TRIGGERABLE_WITHDRAWALS_GATEWAY = "0x6679090D92b08a2a686eF8614feECD8cDFE209db" +VALIDATOR_EXIT_VERIFIER = "0xFd4386A8795956f4B6D01cbb6dB116749731D7bD" + +# Add missing constants +OLD_GATE_SEAL_ADDRESS = "0x2168Ea6D948Ab49c3D34c667A7e02F92369F3A9C" +NEW_WQ_GATE_SEAL = "0x73d76Bd3D589B2b2185c402da82cdAfbc18b958D" +NEW_TW_GATE_SEAL = "0x368f2fcb593170823cc844F1B29e75E3d26879A1" +RESEAL_MANAGER = "0x05172CbCDb7307228F781436b327679e4DAE166B" + +# Add EasyTrack constants +EASYTRACK_EVMSCRIPT_EXECUTOR = "0x79a20FD0FA36453B2F45eAbab19bfef43575Ba9E" +EASYTRACK_SDVT_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY = "0xAa3D6A8B52447F272c1E8FAaA06EA06658bd95E2" +EASYTRACK_CURATED_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY = "0x397206ecdbdcb1A55A75e60Fc4D054feC72E5f63" + +# Oracle consensus versions +AO_CONSENSUS_VERSION = 4 +VEBO_CONSENSUS_VERSION = 4 +CSM_CONSENSUS_VERSION = 3 + +EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS = 14 * 7200 + +NOR_EXIT_DEADLINE_IN_SEC = 172800 + +# CSM +CS_MODULE_NEW_TARGET_SHARE_BP = 1600 # 16% +CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP = 2100 # 21% + +CS_ACCOUNTING_IMPL_V2_ADDRESS = "0x9483b34504292a0E4f6509e5887D2c68f7129638" +CS_FEE_DISTRIBUTOR_IMPL_V2_ADDRESS = "0xe05F7Aab7177D73f26e62a5296120583F5F18031" +CS_FEE_ORACLE_IMPL_V2_ADDRESS = "0x752fF00fcacdB66Bc512a067F15A5E0B0b50EADB" +CSM_IMPL_V2_ADDRESS = "0x9aE387EB2abA80B9B1ebc145597D593EFAE61f31" + +CS_GATE_SEAL_V2_ADDRESS = "0x94a3aEB0E9148F64CB453Be2BDe2Bc0148f6AC24" +CS_EJECTOR_ADDRESS = "0x21e271cBa32672B106737AbeB3a45E53Fe9a0df4" +CS_PERMISSIONLESS_GATE_ADDRESS = "0x5553077102322689876A6AdFd48D75014c28acfb" +CS_VETTED_GATE_ADDRESS = "0x10a254E724fe2b7f305F76f3F116a3969c53845f" +CS_VERIFIER_V2_ADDRESS = "0xf805b3711cBB48F15Ae2bb27095ddC38c5339968" + +CS_CURVES = [ + ([1, 2.4 * 10**18], [2, 1.3 * 10**18]), # Default Curve + ([1, 1.5 * 10**18], [2, 1.3 * 10**18]), # Legacy EA Curve +] +CS_ICS_GATE_BOND_CURVE = ([1, 1.5 * 10**18], [2, 1.3 * 10**18]) # Identified Community Stakers Gate Bond Curve + +# Contract versions expected after upgrade +CSM_V2_VERSION = 2 +CS_ACCOUNTING_V2_VERSION = 2 +CS_FEE_ORACLE_V2_VERSION = 2 +CS_FEE_DISTRIBUTOR_V2_VERSION = 2 + +EASYTRACK_CS_SET_VETTED_GATE_TREE_FACTORY = "0xa890fc73e1b771Ee6073e2402E631c312FF92Cd9" + + +def test_tw_vote(helpers, accounts, vote_ids_from_env, stranger): + # Save original implementations for comparison + locator_impl_before = get_ossifiable_proxy_impl(contracts.lido_locator) + accounting_oracle_impl_before = get_ossifiable_proxy_impl(contracts.accounting_oracle) + vebo_impl_before = get_ossifiable_proxy_impl(contracts.validators_exit_bus_oracle) + withdrawal_vault_impl_before = get_wv_contract_proxy_impl(contracts.withdrawal_vault) + staking_router_impl_before = get_ossifiable_proxy_impl(contracts.staking_router) + + csm_impl_before = get_ossifiable_proxy_impl(contracts.csm.address) + cs_accounting_impl_before = get_ossifiable_proxy_impl(contracts.cs_accounting.address) + cs_fee_oracle_impl_before = get_ossifiable_proxy_impl(contracts.cs_fee_oracle.address) + cs_fee_distributor_impl_before = get_ossifiable_proxy_impl(contracts.cs_fee_distributor.address) + + timelock = interface.EmergencyProtectedTimelock(TIMELOCK) + dual_governance = interface.DualGovernance(DUAL_GOVERNANCE) + + # Not yet used by the protocol, but needed for the test + triggerable_withdrawals_gateway = interface.TriggerableWithdrawalsGateway(TRIGGERABLE_WITHDRAWALS_GATEWAY) + cs_ejector = interface.CSEjector(CS_EJECTOR_ADDRESS) + cs_permissionless_gate = interface.CSPermissionlessGate(CS_PERMISSIONLESS_GATE_ADDRESS) + cs_vetted_gate = interface.CSVettedGate(CS_VETTED_GATE_ADDRESS) + cs_verifier_v2 = interface.CSVerifierV2(CS_VERIFIER_V2_ADDRESS) + + # --- Initial state checks --- + + # Step 1: Check Lido Locator implementation initial state + assert locator_impl_before != LIDO_LOCATOR_IMPL, "Locator implementation should be different before upgrade" + + # Step 2: Check VEBO implementation initial state + assert vebo_impl_before != VALIDATORS_EXIT_BUS_ORACLE_IMPL, "VEBO implementation should be different before upgrade" + + # Step 3: Check VEBO finalizeUpgrade_v2 state + try: + assert contracts.validators_exit_bus_oracle.getMaxValidatorsPerReport() != 600, "VEBO max validators per report should not be 600 before upgrade" + except Exception: + pass # Function might not exist yet + + # Steps 4-6: Check VEBO consensus version management + initial_vebo_consensus_version = contracts.validators_exit_bus_oracle.getConsensusVersion() + assert initial_vebo_consensus_version < VEBO_CONSENSUS_VERSION, f"VEBO consensus version should be less than {VEBO_CONSENSUS_VERSION}" + + # Step 7: Check TWG role for CS Ejector initial state + add_full_withdrawal_request_role = triggerable_withdrawals_gateway.ADD_FULL_WITHDRAWAL_REQUEST_ROLE() + assert not triggerable_withdrawals_gateway.hasRole(add_full_withdrawal_request_role, cs_ejector), "CS Ejector should not have ADD_FULL_WITHDRAWAL_REQUEST_ROLE before upgrade" + + # Step 8: Check TWG role for VEB initial state + assert not triggerable_withdrawals_gateway.hasRole(add_full_withdrawal_request_role, contracts.validators_exit_bus_oracle), "VEBO should not have ADD_FULL_WITHDRAWAL_REQUEST_ROLE before upgrade" + + # Step 9: Check EasyTrack VEB SUBMIT_REPORT_HASH_ROLE initial state + submit_report_hash_role = web3.keccak(text="SUBMIT_REPORT_HASH_ROLE") + assert not contracts.validators_exit_bus_oracle.hasRole(submit_report_hash_role, EASYTRACK_EVMSCRIPT_EXECUTOR), "EasyTrack executor should not have SUBMIT_REPORT_HASH_ROLE on VEBO before upgrade" + + # Step 10: Check DualGovernance tiebreaker initial state + tiebreaker_details = contracts.dual_governance.getTiebreakerDetails() + initial_tiebreakers = tiebreaker_details[3] # sealableWithdrawalBlockers + assert TRIGGERABLE_WITHDRAWALS_GATEWAY not in initial_tiebreakers, "TWG should not be in tiebreaker list before upgrade" + + # Step 9: Check Withdrawal Vault implementation initial state + assert withdrawal_vault_impl_before != WITHDRAWAL_VAULT_IMPL, "Withdrawal Vault implementation should be different before upgrade" + + # Step 10: Withdrawal Vault finalizeUpgrade_v2 check is done post-execution + assert contracts.withdrawal_vault.getContractVersion() == 1, "Withdrawal Vault version should be 1 before upgrade" + + # Step 11: Check Accounting Oracle implementation initial state + assert accounting_oracle_impl_before != ACCOUNTING_ORACLE_IMPL, "Accounting Oracle implementation should be different before upgrade" + + # Steps 12-14: Check AO consensus version management + initial_ao_consensus_version = contracts.accounting_oracle.getConsensusVersion() + assert initial_ao_consensus_version < AO_CONSENSUS_VERSION, f"AO consensus version should be less than {AO_CONSENSUS_VERSION}" + assert not contracts.accounting_oracle.hasRole(contracts.accounting_oracle.MANAGE_CONSENSUS_VERSION_ROLE(), contracts.agent), "Agent should not have MANAGE_CONSENSUS_VERSION_ROLE on AO before upgrade" + + # Step 17: Check AO version before finalizeUpgrade_v3 + assert contracts.accounting_oracle.getContractVersion() == 2, "AO contract version should be 2 before finalizeUpgrade_v3" + + # Step 15: Check Staking Router implementation initial state + assert staking_router_impl_before != STAKING_ROUTER_IMPL, "Staking Router implementation should be different before upgrade" + + # Steps 16-17: Check SR roles initial state + try: + report_validator_exiting_status_role = contracts.staking_router.REPORT_VALIDATOR_EXITING_STATUS_ROLE() + report_validator_exit_triggered_role = contracts.staking_router.REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE() + except Exception as e: + assert "Unknown typed error: 0x" in str(e), f"Unexpected error: {e}" + report_validator_exiting_status_role = ZERO_ADDRESS + report_validator_exit_triggered_role = ZERO_ADDRESS + + assert report_validator_exiting_status_role == ZERO_ADDRESS, "REPORT_VALIDATOR_EXITING_STATUS_ROLE should not exist before upgrade" + assert report_validator_exit_triggered_role == ZERO_ADDRESS, "REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE should not exist before upgrade" + + # Step 18: Check APP_MANAGER_ROLE initial state + app_manager_role = web3.keccak(text="APP_MANAGER_ROLE") + assert contracts.acl.getPermissionManager(ARAGON_KERNEL, app_manager_role) == AGENT, "AGENT should be the permission manager for APP_MANAGER_ROLE" + assert contracts.node_operators_registry.kernel() == ARAGON_KERNEL, "Node Operators Registry must use the correct kernel" + assert not contracts.acl.hasPermission(VOTING, ARAGON_KERNEL, app_manager_role), "VOTING should not have APP_MANAGER_ROLE before the upgrade" + assert not contracts.acl.hasPermission(AGENT, ARAGON_KERNEL, app_manager_role), "AGENT should not have APP_MANAGER_ROLE before the upgrade" + + # Steps 19-23: Check NOR and sDVT initial state + assert not contracts.acl.hasPermission(contracts.agent, contracts.kernel, app_manager_role), "Agent should not have APP_MANAGER_ROLE before upgrade" + assert contracts.node_operators_registry.getContractVersion() == 3, "Node Operators Registry version should be 3 before upgrade" + assert contracts.simple_dvt.getContractVersion() == 3, "Simple DVT version should be 3 before upgrade" + + # Step 24: Check CONFIG_MANAGER_ROLE initial state + config_manager_role = contracts.oracle_daemon_config.CONFIG_MANAGER_ROLE() + assert not contracts.oracle_daemon_config.hasRole(config_manager_role, contracts.agent), "Agent should not have CONFIG_MANAGER_ROLE on Oracle Daemon Config before upgrade" + + # Steps 25-27: Check Oracle Daemon Config variables to be removed + try: + contracts.oracle_daemon_config.get('NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP') + contracts.oracle_daemon_config.get('VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS') + contracts.oracle_daemon_config.get('VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS') + except Exception as e: + assert False, f"Expected variables to exist before removal: {e}" + + # Step 28: Check that EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS doesn't exist yet + try: + contracts.oracle_daemon_config.get('EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS') + assert False, "EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS should not exist before vote" + except Exception: + pass # Expected to fail + + # Step 29: Check CSM implementation initial state + assert csm_impl_before != CSM_IMPL_V2_ADDRESS, "CSM implementation should be different before vote" + + # Step 30: Check CSM finalizeUpgradeV2 initial state + with reverts(): + # The function should not exist yet + contracts.csm.getInitializedVersion() + + # CSM Step 32: Check CSAccounting implementation (pre-vote state) + assert cs_accounting_impl_before != CS_ACCOUNTING_IMPL_V2_ADDRESS, "CSAccounting implementation should be different before vote" + + # CSM Step 33: Check CSAccounting finalizeUpgradeV2 was not called (pre-vote state) + with reverts(): + # The function should not exist yet + contracts.cs_accounting.getInitializedVersion() + + # CSM Step 34: Check CSFeeOracle implementation (pre-vote state) + assert cs_fee_oracle_impl_before != CS_FEE_ORACLE_IMPL_V2_ADDRESS, "CSFeeOracle implementation should be different before vote" + + # CSM Step 35: Check CSFeeOracle finalizeUpgradeV2 was not called (pre-vote state) + assert contracts.cs_fee_oracle.getContractVersion() < CS_FEE_ORACLE_V2_VERSION, f"CSFeeOracle version should be less than {CS_FEE_ORACLE_V2_VERSION} before vote" + assert contracts.cs_fee_oracle.getConsensusVersion() < 3, "CSFeeOracle consensus version should be less than 3 before vote" + + # CSM Step 36: Check CSFeeDistributor implementation (pre-vote state) + assert cs_fee_distributor_impl_before != CS_FEE_DISTRIBUTOR_IMPL_V2_ADDRESS, "CSFeeDistributor implementation should be different before vote" + + # CSM Step 37: Check CSFeeDistributor finalizeUpgradeV2 was not called (pre-vote state) + with reverts(): + # The function should not exist yet + contracts.cs_fee_distributor.getInitializedVersion() + + # CSM Steps 38-40: CSAccounting roles (pre-vote state) + assert contracts.cs_accounting.hasRole(contracts.cs_accounting.SET_BOND_CURVE_ROLE(), contracts.csm.address), "CSM should have SET_BOND_CURVE_ROLE on CSAccounting before vote" + assert contracts.cs_accounting.hasRole(web3.keccak(text="RESET_BOND_CURVE_ROLE"), contracts.csm.address), "CSM should have RESET_BOND_CURVE_ROLE on CSAccounting before vote" + assert contracts.cs_accounting.hasRole(web3.keccak(text="RESET_BOND_CURVE_ROLE"), CSM_COMMITTEE_MS), "CSM committee should have RESET_BOND_CURVE_ROLE on CSAccounting before vote" + + # CSM Steps 41-42: CSM roles (pre-vote state) + assert not contracts.csm.hasRole(web3.keccak(text="CREATE_NODE_OPERATOR_ROLE"), cs_permissionless_gate.address), "Permissionless gate should not have CREATE_NODE_OPERATOR_ROLE on CSM before vote" + assert not contracts.csm.hasRole(web3.keccak(text="CREATE_NODE_OPERATOR_ROLE"), cs_vetted_gate.address), "Vetted gate should not have CREATE_NODE_OPERATOR_ROLE on CSM before vote" + + # CSM Step 43: CSAccounting bond curve role for vetted gate (pre-vote state) + assert not contracts.cs_accounting.hasRole(contracts.cs_accounting.SET_BOND_CURVE_ROLE(), cs_vetted_gate.address), "Vetted gate should not have SET_BOND_CURVE_ROLE on CSAccounting before vote" + + # CSM Steps 44-45: Verifier roles (pre-vote state) + assert contracts.csm.hasRole(contracts.csm.VERIFIER_ROLE(), contracts.cs_verifier.address), "Old verifier should have VERIFIER_ROLE on CSM before vote" + assert not contracts.csm.hasRole(contracts.csm.VERIFIER_ROLE(), cs_verifier_v2.address), "New verifier should not have VERIFIER_ROLE on CSM before vote" + + # CSM Steps 46-51: GateSeal roles (pre-vote state) + assert contracts.csm.hasRole(contracts.csm.PAUSE_ROLE(), CS_GATE_SEAL_ADDRESS), "Old GateSeal should have PAUSE_ROLE on CSM before vote" + assert contracts.cs_accounting.hasRole(contracts.cs_accounting.PAUSE_ROLE(), CS_GATE_SEAL_ADDRESS), "Old GateSeal should have PAUSE_ROLE on CSAccounting before vote" + assert contracts.cs_fee_oracle.hasRole(contracts.cs_fee_oracle.PAUSE_ROLE(), CS_GATE_SEAL_ADDRESS), "Old GateSeal should have PAUSE_ROLE on CSFeeOracle before vote" + + assert not contracts.csm.hasRole(contracts.csm.PAUSE_ROLE(), CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should not have PAUSE_ROLE on CSM before vote" + assert not contracts.cs_accounting.hasRole(contracts.cs_accounting.PAUSE_ROLE(), CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should not have PAUSE_ROLE on CSAccounting before vote" + assert not contracts.cs_fee_oracle.hasRole(contracts.cs_fee_oracle.PAUSE_ROLE(), CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should not have PAUSE_ROLE on CSFeeOracle before vote" + + # CSM Step 52: Staking Router CSM module state before vote (pre-vote state) + csm_module_before = contracts.staking_router.getStakingModule(CS_MODULE_ID) + csm_share_before = csm_module_before['stakeShareLimit'] + csm_priority_exit_threshold_before = csm_module_before['priorityExitShareThreshold'] + assert csm_share_before != CS_MODULE_NEW_TARGET_SHARE_BP, f"CSM share should not be {CS_MODULE_NEW_TARGET_SHARE_BP} before vote, current: {csm_share_before}" + assert csm_priority_exit_threshold_before != CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP, f"CSM priority exit threshold should not be {CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP} before vote, current: {csm_priority_exit_threshold_before}" + + # CSM Step 65: EasyTrack factories before vote (pre-vote state) + initial_factories = contracts.easy_track.getEVMScriptFactories() + assert EASYTRACK_CS_SET_VETTED_GATE_TREE_FACTORY not in initial_factories, "EasyTrack should not have CSMSetVettedGateTree factory before vote" + assert EASYTRACK_SDVT_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY not in initial_factories, "EasyTrack should not have SDVT validator exit request hashes factory before vote" + assert EASYTRACK_CURATED_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY not in initial_factories, "EasyTrack should not have Curated validator exit request hashes factory before vote" + + # Gate Seals: Check initial states before vote + assert contracts.withdrawal_queue.hasRole(contracts.withdrawal_queue.PAUSE_ROLE(), OLD_GATE_SEAL_ADDRESS), "Old GateSeal should have PAUSE_ROLE on WithdrawalQueue before vote" + assert contracts.validators_exit_bus_oracle.hasRole(contracts.validators_exit_bus_oracle.PAUSE_ROLE(), OLD_GATE_SEAL_ADDRESS), "Old GateSeal should have PAUSE_ROLE on VEBO before vote" + assert not contracts.withdrawal_queue.hasRole(contracts.withdrawal_queue.PAUSE_ROLE(), NEW_WQ_GATE_SEAL), "New WQ GateSeal should not have PAUSE_ROLE on WithdrawalQueue before vote" + assert not contracts.validators_exit_bus_oracle.hasRole(contracts.validators_exit_bus_oracle.PAUSE_ROLE(), NEW_TW_GATE_SEAL), "New TW GateSeal should not have PAUSE_ROLE on VEBO before vote" + assert not triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.PAUSE_ROLE(), NEW_TW_GATE_SEAL), "New TW GateSeal should not have PAUSE_ROLE on TWG before vote" + + # ResealManager: Check initial states before vote + assert not triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.PAUSE_ROLE(), RESEAL_MANAGER), "ResealManager should not have PAUSE_ROLE on TWG before vote" + assert not triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.RESUME_ROLE(), RESEAL_MANAGER), "ResealManager should not have RESUME_ROLE on TWG before vote" + + # START VOTE + if len(vote_ids_from_env) > 0: + (vote_id,) = vote_ids_from_env + else: + tx_params = {"from": LDO_HOLDER_ADDRESS_FOR_TESTS} + vote_id, _ = start_vote(tx_params, silent=True) + + vote_tx = helpers.execute_vote(accounts, vote_id, contracts.voting) + print(f"voteId = {vote_id}") + + proposal_id = vote_tx.events["ProposalSubmitted"][1]["proposalId"] + print(f"proposalId = {proposal_id}") + + chain.sleep(timelock.getAfterSubmitDelay() + 1) + dual_governance.scheduleProposal(proposal_id, {"from": stranger}) + + chain.sleep(timelock.getAfterScheduleDelay() + 1) + wait_for_noon_utc_to_satisfy_time_constrains() + + dg_tx = timelock.execute(proposal_id, {"from": stranger}) + + # --- VALIDATE EXECUTION RESULTS --- + + # Step 1: Validate Lido Locator implementation was updated + assert get_ossifiable_proxy_impl(contracts.lido_locator) == LIDO_LOCATOR_IMPL, "Locator implementation should be updated to the new value" + + # Step 2-3: Validate VEBO implementation was updated and configured + assert get_ossifiable_proxy_impl(contracts.validators_exit_bus_oracle) == VALIDATORS_EXIT_BUS_ORACLE_IMPL, "VEBO implementation should be updated" + assert contracts.validators_exit_bus_oracle.getMaxValidatorsPerReport() == 600, "VEBO max validators per report should be set to 600" + + # Validate exit request limit parameters from finalizeUpgrade_v2 call + exit_request_limits = contracts.validators_exit_bus_oracle.getExitRequestLimitFullInfo() + assert exit_request_limits[0] == 11200, "maxExitRequestsLimit should be 11200" + assert exit_request_limits[1] == 1, "exitsPerFrame should be 1" + assert exit_request_limits[2] == 48, "frameDurationInSec should be 48 hours in seconds" + + # Steps 4-6: Validate VEBO consensus version management + assert not contracts.validators_exit_bus_oracle.hasRole(contracts.validators_exit_bus_oracle.MANAGE_CONSENSUS_VERSION_ROLE(), contracts.agent), "Agent should not have MANAGE_CONSENSUS_VERSION_ROLE on VEBO" + assert contracts.validators_exit_bus_oracle.getConsensusVersion() == VEBO_CONSENSUS_VERSION, f"VEBO consensus version should be set to {VEBO_CONSENSUS_VERSION}" + + # Steps 7-8: Validate TWG roles + assert triggerable_withdrawals_gateway.hasRole(add_full_withdrawal_request_role, cs_ejector), "CS Ejector should have ADD_FULL_WITHDRAWAL_REQUEST_ROLE on TWG" + assert triggerable_withdrawals_gateway.hasRole(add_full_withdrawal_request_role, contracts.validators_exit_bus_oracle), "VEBO should have ADD_FULL_WITHDRAWAL_REQUEST_ROLE on TWG" + + # Step 9: Validate EasyTrack VEB SUBMIT_REPORT_HASH_ROLE + assert contracts.validators_exit_bus_oracle.hasRole(submit_report_hash_role, EASYTRACK_EVMSCRIPT_EXECUTOR), "EasyTrack executor should have SUBMIT_REPORT_HASH_ROLE on VEBO" + + # Step 10: Validate DualGovernance tiebreaker connection + final_tiebreaker_details = contracts.dual_governance.getTiebreakerDetails() + final_tiebreakers = final_tiebreaker_details[3] # sealableWithdrawalBlockers + assert TRIGGERABLE_WITHDRAWALS_GATEWAY in final_tiebreakers, "TWG should be in tiebreaker list after upgrade" + + # Steps 9-10: Validate Withdrawal Vault upgrade + assert get_wv_contract_proxy_impl(contracts.withdrawal_vault) == WITHDRAWAL_VAULT_IMPL, "Withdrawal Vault implementation should be updated" + assert contracts.withdrawal_vault.getContractVersion() == 2, "Withdrawal Vault version should be 2 after finalizeUpgrade_v2" + + # Steps 11-14: Validate Accounting Oracle upgrade + assert get_ossifiable_proxy_impl(contracts.accounting_oracle) == ACCOUNTING_ORACLE_IMPL, "Accounting Oracle implementation should be updated" + assert not contracts.accounting_oracle.hasRole(contracts.accounting_oracle.MANAGE_CONSENSUS_VERSION_ROLE(), contracts.agent), "Agent should not have MANAGE_CONSENSUS_VERSION_ROLE on AO" + assert contracts.accounting_oracle.getConsensusVersion() == AO_CONSENSUS_VERSION, f"AO consensus version should be set to {AO_CONSENSUS_VERSION}" + + # Step 17: Validate AO finalizeUpgrade_v3 + assert contracts.accounting_oracle.getContractVersion() == 3, "AO contract version should be 3 after finalizeUpgrade_v3" + + # Steps 15-17: Validate Staking Router upgrade + assert get_ossifiable_proxy_impl(contracts.staking_router) == STAKING_ROUTER_IMPL, "Staking Router implementation should be updated" + assert contracts.staking_router.hasRole(contracts.staking_router.REPORT_VALIDATOR_EXITING_STATUS_ROLE(), VALIDATOR_EXIT_VERIFIER), "ValidatorExitVerifier should have REPORT_VALIDATOR_EXITING_STATUS_ROLE on SR" + assert contracts.staking_router.hasRole(contracts.staking_router.REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE(), triggerable_withdrawals_gateway), "TWG should have REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE on SR" + + # Steps 18-23: Validate NOR and sDVT updates + assert not contracts.acl.hasPermission(contracts.agent, contracts.kernel, app_manager_role), "Agent should not have APP_MANAGER_ROLE after vote" + assert contracts.node_operators_registry.getContractVersion() == 4, "Node Operators Registry version should be updated to 4" + assert contracts.simple_dvt.getContractVersion() == 4, "Simple DVT version should be updated to 4" + assert contracts.node_operators_registry.exitDeadlineThreshold(0) == NOR_EXIT_DEADLINE_IN_SEC, "NOR exit deadline threshold should be set correctly" + assert contracts.simple_dvt.exitDeadlineThreshold(0) == NOR_EXIT_DEADLINE_IN_SEC, "sDVT exit deadline threshold should be set correctly" + + # Steps 24-28: Validate Oracle Daemon Config changes + assert not contracts.oracle_daemon_config.hasRole(config_manager_role, contracts.agent), "Agent should not have CONFIG_MANAGER_ROLE on Oracle Daemon Config" + for var_name in ['NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP', 'VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS', 'VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS']: + try: + contracts.oracle_daemon_config.get(var_name) + assert False, f"Variable {var_name} should have been removed" + except Exception: + pass # Expected to fail - variable should be removed + assert convert.to_uint(contracts.oracle_daemon_config.get('EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS')) == EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS, f"EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS should be set to {EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS}" + + # Step 29: Validate CSM implementation upgrade + check_proxy_implementation(contracts.csm.address, CSM_IMPL_V2_ADDRESS) + + # Step 30: Validate CSM finalizeUpgradeV2 was called + assert contracts.csm.getInitializedVersion() == CSM_V2_VERSION, f"CSM version should be {CSM_V2_VERSION} after vote" + + # Step 31: Validate CSAccounting implementation upgrade + check_proxy_implementation(contracts.cs_accounting.address, CS_ACCOUNTING_IMPL_V2_ADDRESS) + + # Step 32: Validate CSAccounting finalizeUpgradeV2 was called with bond curves + assert contracts.cs_accounting.getInitializedVersion() == CS_ACCOUNTING_V2_VERSION, f"CSAccounting version should be {CS_ACCOUNTING_V2_VERSION} after vote" + + # Step 33: Validate CSFeeOracle implementation upgrade + check_proxy_implementation(contracts.cs_fee_oracle.address, CS_FEE_ORACLE_IMPL_V2_ADDRESS) + + # Step 34: Validate CSFeeOracle finalizeUpgradeV2 was called with consensus version 3 + assert contracts.cs_fee_oracle.getContractVersion() == CS_FEE_ORACLE_V2_VERSION, f"CSFeeOracle version should be {CS_FEE_ORACLE_V2_VERSION} after vote" + assert contracts.cs_fee_oracle.getConsensusVersion() == CSM_CONSENSUS_VERSION, "CSFeeOracle consensus version should be 3 after vote" + + # Step 35: Validate CSFeeDistributor implementation upgrade + check_proxy_implementation(contracts.cs_fee_distributor.address, CS_FEE_DISTRIBUTOR_IMPL_V2_ADDRESS) + + # Step 36: Validate CSFeeDistributor finalizeUpgradeV2 was called + assert contracts.cs_fee_distributor.getInitializedVersion() == CS_FEE_DISTRIBUTOR_V2_VERSION, f"CSFeeDistributor version should be {CS_FEE_DISTRIBUTOR_V2_VERSION} after vote" + + # Step 37: Validate SET_BOND_CURVE_ROLE was revoked from CSM on CSAccounting + assert not contracts.cs_accounting.hasRole(contracts.cs_accounting.SET_BOND_CURVE_ROLE(), contracts.csm.address), "CSM should not have SET_BOND_CURVE_ROLE on CSAccounting after vote" + + # Step 38: Validate RESET_BOND_CURVE_ROLE was revoked from CSM on CSAccounting + assert not contracts.cs_accounting.hasRole(web3.keccak(text="RESET_BOND_CURVE_ROLE"), contracts.csm.address), "CSM should not have RESET_BOND_CURVE_ROLE on CSAccounting after vote" + + # Step 39: Validate RESET_BOND_CURVE_ROLE was revoked from CSM committee on CSAccounting + assert not contracts.cs_accounting.hasRole(web3.keccak(text="RESET_BOND_CURVE_ROLE"), CSM_COMMITTEE_MS), "CSM committee should not have RESET_BOND_CURVE_ROLE on CSAccounting after vote" + + # Step 40: Validate CREATE_NODE_OPERATOR_ROLE was granted to permissionless gate on CSM + assert contracts.csm.hasRole(contracts.csm.CREATE_NODE_OPERATOR_ROLE(), cs_permissionless_gate.address), "Permissionless gate should have CREATE_NODE_OPERATOR_ROLE on CSM after vote" + + # Step 41: Validate CREATE_NODE_OPERATOR_ROLE was granted to vetted gate on CSM + assert contracts.csm.hasRole(contracts.csm.CREATE_NODE_OPERATOR_ROLE(), cs_vetted_gate.address), "Vetted gate should have CREATE_NODE_OPERATOR_ROLE on CSM after vote" + + # Step 42: Validate SET_BOND_CURVE_ROLE was granted to vetted gate on CSAccounting + assert contracts.cs_accounting.hasRole(contracts.cs_accounting.SET_BOND_CURVE_ROLE(), cs_vetted_gate.address), "Vetted gate should have SET_BOND_CURVE_ROLE on CSAccounting after vote" + + # Step 43: Validate VERIFIER_ROLE was revoked from old verifier on CSM + assert not contracts.csm.hasRole(contracts.csm.VERIFIER_ROLE(), contracts.cs_verifier.address), "Old verifier should not have VERIFIER_ROLE on CSM after vote" + + # Step 44: Validate VERIFIER_ROLE was granted to new verifier on CSM + assert contracts.csm.hasRole(contracts.csm.VERIFIER_ROLE(), cs_verifier_v2.address), "New verifier should have VERIFIER_ROLE on CSM after vote" + + # Step 45: Validate PAUSE_ROLE was revoked from old GateSeal on CSM + assert not contracts.csm.hasRole(contracts.csm.PAUSE_ROLE(), CS_GATE_SEAL_ADDRESS), "Old GateSeal should not have PAUSE_ROLE on CSM after vote" + + # Step 46: Validate PAUSE_ROLE was revoked from old GateSeal on CSAccounting + assert not contracts.cs_accounting.hasRole(contracts.cs_accounting.PAUSE_ROLE(), CS_GATE_SEAL_ADDRESS), "Old GateSeal should not have PAUSE_ROLE on CSAccounting after vote" + + # Step 47: Validate PAUSE_ROLE was revoked from old GateSeal on CSFeeOracle + assert not contracts.cs_fee_oracle.hasRole(contracts.cs_fee_oracle.PAUSE_ROLE(), CS_GATE_SEAL_ADDRESS), "Old GateSeal should not have PAUSE_ROLE on CSFeeOracle after vote" + + # Step 48: Validate PAUSE_ROLE was granted to new GateSeal on CSM + assert contracts.csm.hasRole(contracts.csm.PAUSE_ROLE(), CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should have PAUSE_ROLE on CSM after vote" + + # Step 49: Validate PAUSE_ROLE was granted to new GateSeal on CSAccounting + assert contracts.cs_accounting.hasRole(contracts.cs_accounting.PAUSE_ROLE(), CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should have PAUSE_ROLE on CSAccounting after vote" + + # Step 50: Validate PAUSE_ROLE was granted to new GateSeal on CSFeeOracle + assert contracts.cs_fee_oracle.hasRole(contracts.cs_fee_oracle.PAUSE_ROLE(), CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should have PAUSE_ROLE on CSFeeOracle after vote" + + # Step 50-52: Check add ICS Bond Curve to CSAccounting + assert not contracts.cs_accounting.hasRole(contracts.cs_accounting.MANAGE_BOND_CURVES_ROLE(), contracts.agent), "Agent should not have MANAGE_BOND_CURVES_ROLE on CSAccounting after vote" + assert contracts.cs_accounting.getCurvesCount() == len(CS_CURVES) + 1, "CSAccounting should have legacy bond curves and ICS Bond Curve after vote" + + # Step 53: Increase CSM share in Staking Router + csm_module_after = contracts.staking_router.getStakingModule(CS_MODULE_ID) + csm_share_after = csm_module_after['stakeShareLimit'] + assert csm_share_after == CS_MODULE_NEW_TARGET_SHARE_BP, f"CSM share should be {CS_MODULE_NEW_TARGET_SHARE_BP} after vote, but got {csm_share_after}" + + csm_priority_exit_threshold_after = csm_module_after['priorityExitShareThreshold'] + assert csm_priority_exit_threshold_after == CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP, f"CSM priority exit threshold should be {CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP} after vote, but got {csm_priority_exit_threshold_after}" + + + # Steps 58-62: Validate Gate Seals updates + assert not contracts.withdrawal_queue.hasRole(contracts.withdrawal_queue.PAUSE_ROLE(), OLD_GATE_SEAL_ADDRESS), "Old GateSeal should not have PAUSE_ROLE on WithdrawalQueue after vote" + assert not contracts.validators_exit_bus_oracle.hasRole(contracts.validators_exit_bus_oracle.PAUSE_ROLE(), OLD_GATE_SEAL_ADDRESS), "Old GateSeal should not have PAUSE_ROLE on VEBO after vote" + assert contracts.withdrawal_queue.hasRole(contracts.withdrawal_queue.PAUSE_ROLE(), NEW_WQ_GATE_SEAL), "New WQ GateSeal should have PAUSE_ROLE on WithdrawalQueue after vote" + assert contracts.validators_exit_bus_oracle.hasRole(contracts.validators_exit_bus_oracle.PAUSE_ROLE(), NEW_TW_GATE_SEAL), "New TW GateSeal should have PAUSE_ROLE on VEBO after vote" + assert triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.PAUSE_ROLE(), NEW_TW_GATE_SEAL), "New TW GateSeal should have PAUSE_ROLE on TWG after vote" + + # Steps 63-64: Validate ResealManager roles + assert triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.PAUSE_ROLE(), RESEAL_MANAGER), "ResealManager should have PAUSE_ROLE on TWG after vote" + assert triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.RESUME_ROLE(), RESEAL_MANAGER), "ResealManager should have RESUME_ROLE on TWG after vote" + + # Step 65: Add EasyTrack factory for CSSetVettedGateTree + new_factories = contracts.easy_track.getEVMScriptFactories() + assert EASYTRACK_CS_SET_VETTED_GATE_TREE_FACTORY in new_factories, "EasyTrack should have CSSetVettedGateTree factory after vote" + + # Steps 66-67: Validate EasyTrack factories for validator exit request hashes + assert EASYTRACK_SDVT_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY in new_factories, "EasyTrack should have SDVT validator exit request hashes factory after vote" + assert EASYTRACK_CURATED_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY in new_factories, "EasyTrack should have Curated validator exit request hashes factory after vote" + + # --- VALIDATE EVENTS --- + + voting_events = group_voting_events_from_receipt(vote_tx) + dg_execution_events = group_dg_events_from_receipt(dg_tx, timelock=TIMELOCK, admin_executor=DUAL_GOVERNANCE_EXECUTORS[0]) + + # Validate voting events structure + assert len(voting_events) == 4, "Unexpected number of voting events" + dg_voting_event, dg_bypass_voting_event1, dg_bypass_voting_event2, dg_bypass_voting_event3 = voting_events + + # Validate DG execution events structure + assert len(dg_execution_events) == 66, "Unexpected number of dual governance events" + + + # Main DG voting event validation + validate_dual_governance_submit_event( + dg_voting_event, + proposal_id, + proposer=VOTING, + executor=DUAL_GOVERNANCE_EXECUTORS[0], + ) + + # Validate EasyTrack bypass events for new factories + validate_evmscript_factory_added_event( + event=dg_bypass_voting_event1, + p=EVMScriptFactoryAdded( + factory_addr=EASYTRACK_CS_SET_VETTED_GATE_TREE_FACTORY, + permissions=create_permissions(interface.CSVettedGate(CS_VETTED_GATE_ADDRESS), "setTreeParams") + ), + emitted_by=contracts.easy_track, + ) + + validate_evmscript_factory_added_event( + event=dg_bypass_voting_event2, + p=EVMScriptFactoryAdded( + factory_addr=EASYTRACK_SDVT_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY, + permissions=create_permissions(contracts.validators_exit_bus_oracle, "submitExitRequestsHash") + ), + emitted_by=contracts.easy_track, + ) + + validate_evmscript_factory_added_event( + event=dg_bypass_voting_event3, + p=EVMScriptFactoryAdded( + factory_addr=EASYTRACK_CURATED_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY, + permissions=create_permissions(contracts.validators_exit_bus_oracle, "submitExitRequestsHash") + ), + emitted_by=contracts.easy_track, + ) + + # === DG EXECUTION EVENTS VALIDATION === + + # 0. Lido Locator upgrade events + validate_proxy_upgrade_event(dg_execution_events[0], LIDO_LOCATOR_IMPL, emitted_by=contracts.lido_locator) + + # 1. VEBO upgrade events + validate_proxy_upgrade_event(dg_execution_events[1], VALIDATORS_EXIT_BUS_ORACLE_IMPL, emitted_by=contracts.validators_exit_bus_oracle) + + # 2. VEBO finalize upgrade events + validate_contract_version_set_event(dg_execution_events[2], version=2, emitted_by=contracts.validators_exit_bus_oracle) + assert 'ExitRequestsLimitSet' in dg_execution_events[2], "ExitRequestsLimitSet event not found" + assert dg_execution_events[2]['ExitRequestsLimitSet'][0]['maxExitRequestsLimit'] == 11200, "Wrong maxExitRequestsLimit" + assert dg_execution_events[2]['ExitRequestsLimitSet'][0]['exitsPerFrame'] == 1, "Wrong exitsPerFrame" + assert dg_execution_events[2]['ExitRequestsLimitSet'][0]['frameDurationInSec'] == 48, "Wrong frameDurationInSec" + + # 3. Grant VEBO MANAGE_CONSENSUS_VERSION_ROLE to Agent + validate_role_grant_event( + dg_execution_events[3], + role_hash=web3.keccak(text="MANAGE_CONSENSUS_VERSION_ROLE").hex(), + account=contracts.agent.address, + emitted_by=contracts.validators_exit_bus_oracle + ) + + # 4. Set VEBO consensus version to 4 + validate_consensus_version_set_event( + dg_execution_events[4], + new_version=4, + prev_version=3, + emitted_by=contracts.validators_exit_bus_oracle + ) + + # 5. Revoke VEBO MANAGE_CONSENSUS_VERSION_ROLE from Agent + validate_role_revoke_event( + dg_execution_events[5], + role_hash=web3.keccak(text="MANAGE_CONSENSUS_VERSION_ROLE").hex(), + account=contracts.agent.address, + emitted_by=contracts.validators_exit_bus_oracle + ) + + # 6. Grant VEBO SUBMIT_REPORT_HASH_ROLE to EasyTrack executor + validate_role_grant_event( + dg_execution_events[6], + role_hash=web3.keccak(text="SUBMIT_REPORT_HASH_ROLE").hex(), + account=EASYTRACK_EVMSCRIPT_EXECUTOR, + emitted_by=contracts.validators_exit_bus_oracle + ) + + # 7. Grant TWG ADD_FULL_WITHDRAWAL_REQUEST_ROLE to CS Ejector + validate_role_grant_event( + dg_execution_events[7], + role_hash=web3.keccak(text="ADD_FULL_WITHDRAWAL_REQUEST_ROLE").hex(), + account=CS_EJECTOR_ADDRESS, + emitted_by=triggerable_withdrawals_gateway + ) + + # 8. Grant TWG ADD_FULL_WITHDRAWAL_REQUEST_ROLE to VEBO + validate_role_grant_event( + dg_execution_events[8], + role_hash=web3.keccak(text="ADD_FULL_WITHDRAWAL_REQUEST_ROLE").hex(), + account=contracts.validators_exit_bus_oracle.address, + emitted_by=triggerable_withdrawals_gateway + ) + + # 9. Connect TWG to Dual Governance tiebreaker + assert 'SealableWithdrawalBlockerAdded' in dg_execution_events[9], "SealableWithdrawalBlockerAdded event not found" + assert dg_execution_events[9]['SealableWithdrawalBlockerAdded'][0]['sealable'] == TRIGGERABLE_WITHDRAWALS_GATEWAY, "Wrong sealableWithdrawalBlocker" + + # 10. Update WithdrawalVault implementation + validate_proxy_upgrade_event(dg_execution_events[10], WITHDRAWAL_VAULT_IMPL, emitted_by=contracts.withdrawal_vault) + + # 11. Call finalizeUpgrade_v2 on WithdrawalVault + validate_contract_version_set_event(dg_execution_events[11], version=2, emitted_by=contracts.withdrawal_vault) + + # 12. Update AO implementation + validate_proxy_upgrade_event(dg_execution_events[12], ACCOUNTING_ORACLE_IMPL, emitted_by=contracts.accounting_oracle) + + # 13. Grant AO MANAGE_CONSENSUS_VERSION_ROLE to the AGENT + validate_role_grant_event( + dg_execution_events[13], + role_hash=web3.keccak(text="MANAGE_CONSENSUS_VERSION_ROLE").hex(), + account=contracts.agent.address, + emitted_by=contracts.accounting_oracle + ) + + # 14. Bump AO consensus version to 4 + validate_consensus_version_set_event( + dg_execution_events[14], + new_version=4, + prev_version=3, + emitted_by=contracts.accounting_oracle + ) + + # 15. Revoke AO MANAGE_CONSENSUS_VERSION_ROLE from the AGENT + validate_role_revoke_event( + dg_execution_events[15], + role_hash=web3.keccak(text="MANAGE_CONSENSUS_VERSION_ROLE").hex(), + account=contracts.agent.address, + emitted_by=contracts.accounting_oracle + ) + + # 16. Call finalizeUpgrade_v3() on AO + validate_contract_version_set_event(dg_execution_events[16], version=3, emitted_by=contracts.accounting_oracle) + + # 17. Update SR implementation + validate_proxy_upgrade_event(dg_execution_events[17], STAKING_ROUTER_IMPL, emitted_by=contracts.staking_router) + + # 18. Call finalizeUpgrade_v3() on SR + validate_contract_version_set_event(dg_execution_events[18], version=3, emitted_by=contracts.staking_router) + + # 19. Grant SR REPORT_VALIDATOR_EXITING_STATUS_ROLE to ValidatorExitVerifier + validate_role_grant_event( + dg_execution_events[19], + role_hash=web3.keccak(text="REPORT_VALIDATOR_EXITING_STATUS_ROLE").hex(), + account=VALIDATOR_EXIT_VERIFIER, + emitted_by=contracts.staking_router + ) + + # 20. Grant SR REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE to TWG + validate_role_grant_event( + dg_execution_events[20], + role_hash=web3.keccak(text="REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE").hex(), + account=triggerable_withdrawals_gateway.address, + emitted_by=contracts.staking_router + ) + + # 21. Grant APP_MANAGER_ROLE on Kernel to Voting + assert 'SetPermission' in dg_execution_events[21] + assert dg_execution_events[21]['SetPermission'][0]['allowed'] is True + + # 22. Set new implementation for NOR + assert 'SetApp' in dg_execution_events[22] + + # 23. Finalize upgrade for NOR + validate_contract_version_set_event(dg_execution_events[23], version=4, emitted_by=contracts.node_operators_registry) + assert 'ExitDeadlineThresholdChanged' in dg_execution_events[23] + assert dg_execution_events[23]['ExitDeadlineThresholdChanged'][0]['threshold'] == NOR_EXIT_DEADLINE_IN_SEC + + # 24. Set new implementation for sDVT + assert 'SetApp' in dg_execution_events[24] + + # 25. Finalize upgrade for sDVT + validate_contract_version_set_event(dg_execution_events[25], version=4, emitted_by=contracts.simple_dvt) + assert 'ExitDeadlineThresholdChanged' in dg_execution_events[25] + assert dg_execution_events[25]['ExitDeadlineThresholdChanged'][0]['threshold'] == NOR_EXIT_DEADLINE_IN_SEC + + # 26. Revoke APP_MANAGER_ROLE on Kernel from Voting + assert 'SetPermission' in dg_execution_events[26] + assert dg_execution_events[26]['SetPermission'][0]['allowed'] is False + + # 27. Grant CONFIG_MANAGER_ROLE on OracleDaemonConfig to Agent + validate_role_grant_event( + dg_execution_events[27], + role_hash=contracts.oracle_daemon_config.CONFIG_MANAGER_ROLE().hex(), + account=contracts.agent.address, + emitted_by=contracts.oracle_daemon_config + ) + + # 28. Unset NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP + assert 'ConfigValueUnset' in dg_execution_events[28] + assert 'NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP' in dg_execution_events[28]['ConfigValueUnset'][0]['key'] + + # 29. Unset VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS + assert 'ConfigValueUnset' in dg_execution_events[29] + assert 'VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS' in dg_execution_events[29]['ConfigValueUnset'][0]['key'] + + # 30. Unset VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS + assert 'ConfigValueUnset' in dg_execution_events[30] + assert 'VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS' in dg_execution_events[30]['ConfigValueUnset'][0]['key'] + + # 31. Set EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS + assert 'ConfigValueSet' in dg_execution_events[31] + assert 'EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS' in dg_execution_events[31]['ConfigValueSet'][0]['key'] + assert convert.to_int(dg_execution_events[31]['ConfigValueSet'][0]['value']) == EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS + + # 32. Revoke CONFIG_MANAGER_ROLE from the AGENT + validate_role_revoke_event( + dg_execution_events[32], + role_hash=contracts.oracle_daemon_config.CONFIG_MANAGER_ROLE().hex(), + account=contracts.agent.address, + emitted_by=contracts.oracle_daemon_config + ) + + # 33. CSM implementation upgrade + validate_proxy_upgrade_event(dg_execution_events[33], CSM_IMPL_V2_ADDRESS, emitted_by=contracts.csm) + + # 34. CSM finalize upgrade validation + assert 'Initialized' in dg_execution_events[34] + assert dg_execution_events[34]['Initialized'][0]['version'] == CSM_V2_VERSION + + # 35. CSAccounting implementation upgrade + validate_proxy_upgrade_event(dg_execution_events[35], CS_ACCOUNTING_IMPL_V2_ADDRESS, emitted_by=contracts.cs_accounting) + + # 36. CSAccounting finalize upgrade with bond curves + assert 'BondCurveAdded' in dg_execution_events[36] + assert len(dg_execution_events[36]['BondCurveAdded']) == len(CS_CURVES) + assert 'Initialized' in dg_execution_events[36] + assert dg_execution_events[36]['Initialized'][0]['version'] == CS_ACCOUNTING_V2_VERSION + + # 37. CSFeeOracle implementation upgrade + validate_proxy_upgrade_event(dg_execution_events[37], CS_FEE_ORACLE_IMPL_V2_ADDRESS, emitted_by=contracts.cs_fee_oracle) + + # 38. CSFeeOracle finalize upgrade with consensus version + validate_consensus_version_set_event(dg_execution_events[38], new_version=3, prev_version=2, emitted_by=contracts.cs_fee_oracle) + validate_contract_version_set_event(dg_execution_events[38], version=CS_FEE_ORACLE_V2_VERSION, emitted_by=contracts.cs_fee_oracle) + + # 39. CSFeeDistributor implementation upgrade + validate_proxy_upgrade_event(dg_execution_events[39], CS_FEE_DISTRIBUTOR_IMPL_V2_ADDRESS, emitted_by=contracts.cs_fee_distributor) + + # 40. CSFeeDistributor finalize upgrade + assert 'RebateRecipientSet' in dg_execution_events[40] + assert 'Initialized' in dg_execution_events[40] + assert dg_execution_events[40]['Initialized'][0]['version'] == CS_FEE_DISTRIBUTOR_V2_VERSION + + # 41. Revoke SET_BOND_CURVE_ROLE from CSM on CSAccounting + validate_role_revoke_event( + dg_execution_events[41], + role_hash=contracts.cs_accounting.SET_BOND_CURVE_ROLE().hex(), + account=contracts.csm.address, + emitted_by=contracts.cs_accounting + ) + + # 42. Revoke RESET_BOND_CURVE_ROLE from CSM on CSAccounting + validate_role_revoke_event( + dg_execution_events[42], + role_hash=web3.keccak(text="RESET_BOND_CURVE_ROLE").hex(), + account=contracts.csm.address, + emitted_by=contracts.cs_accounting + ) + + # 43. Revoke RESET_BOND_CURVE_ROLE from CSM committee on CSAccounting + validate_role_revoke_event( + dg_execution_events[43], + role_hash=web3.keccak(text="RESET_BOND_CURVE_ROLE").hex(), + account=CSM_COMMITTEE_MS, + emitted_by=contracts.cs_accounting + ) + + # 44. Grant CREATE_NODE_OPERATOR_ROLE to permissionless gate on CSM + validate_role_grant_event( + dg_execution_events[44], + role_hash=contracts.csm.CREATE_NODE_OPERATOR_ROLE().hex(), + account=CS_PERMISSIONLESS_GATE_ADDRESS, + emitted_by=contracts.csm + ) + + # 45. Grant CREATE_NODE_OPERATOR_ROLE to vetted gate on CSM + validate_role_grant_event( + dg_execution_events[45], + role_hash=contracts.csm.CREATE_NODE_OPERATOR_ROLE().hex(), + account=CS_VETTED_GATE_ADDRESS, + emitted_by=contracts.csm + ) + + # 46. Grant SET_BOND_CURVE_ROLE to vetted gate on CSAccounting + validate_role_grant_event( + dg_execution_events[46], + role_hash=contracts.cs_accounting.SET_BOND_CURVE_ROLE().hex(), + account=CS_VETTED_GATE_ADDRESS, + emitted_by=contracts.cs_accounting + ) + + # 47. Revoke VERIFIER_ROLE from old verifier on CSM + validate_role_revoke_event( + dg_execution_events[47], + role_hash=contracts.csm.VERIFIER_ROLE().hex(), + account=contracts.cs_verifier.address, + emitted_by=contracts.csm + ) + + # 48. Grant VERIFIER_ROLE to new verifier on CSM + validate_role_grant_event( + dg_execution_events[48], + role_hash=contracts.csm.VERIFIER_ROLE().hex(), + account=CS_VERIFIER_V2_ADDRESS, + emitted_by=contracts.csm + ) + + # 49. Revoke PAUSE_ROLE from old GateSeal on CSM + validate_role_revoke_event( + dg_execution_events[49], + role_hash=contracts.csm.PAUSE_ROLE().hex(), + account=CS_GATE_SEAL_ADDRESS, + emitted_by=contracts.csm + ) + + # 50. Revoke PAUSE_ROLE from old GateSeal on CSAccounting + validate_role_revoke_event( + dg_execution_events[50], + role_hash=contracts.cs_accounting.PAUSE_ROLE().hex(), + account=CS_GATE_SEAL_ADDRESS, + emitted_by=contracts.cs_accounting + ) + + # 51. Revoke PAUSE_ROLE from old GateSeal on CSFeeOracle + validate_role_revoke_event( + dg_execution_events[51], + role_hash=contracts.cs_fee_oracle.PAUSE_ROLE().hex(), + account=CS_GATE_SEAL_ADDRESS, + emitted_by=contracts.cs_fee_oracle + ) + + # 52. Grant PAUSE_ROLE to new GateSeal on CSM + validate_role_grant_event( + dg_execution_events[52], + role_hash=contracts.csm.PAUSE_ROLE().hex(), + account=CS_GATE_SEAL_V2_ADDRESS, + emitted_by=contracts.csm + ) + + # 53. Grant PAUSE_ROLE to new GateSeal on CSAccounting + validate_role_grant_event( + dg_execution_events[53], + role_hash=contracts.cs_accounting.PAUSE_ROLE().hex(), + account=CS_GATE_SEAL_V2_ADDRESS, + emitted_by=contracts.cs_accounting + ) + + # 54. Grant PAUSE_ROLE to new GateSeal on CSFeeOracle + validate_role_grant_event( + dg_execution_events[54], + role_hash=contracts.cs_fee_oracle.PAUSE_ROLE().hex(), + account=CS_GATE_SEAL_V2_ADDRESS, + emitted_by=contracts.cs_fee_oracle + ) + + # 55. Grant MANAGE_BOND_CURVES_ROLE to agent on CSAccounting + validate_role_grant_event( + dg_execution_events[55], + role_hash=contracts.cs_accounting.MANAGE_BOND_CURVES_ROLE().hex(), + account=contracts.agent.address, + emitted_by=contracts.cs_accounting + ) + + # 56. Add ICS bond curve + ics_curve_id = len(CS_CURVES) + validate_bond_curve_added_event(dg_execution_events[56], curve_id=ics_curve_id, emitted_by=contracts.cs_accounting) + + # 57. Revoke MANAGE_BOND_CURVES_ROLE from agent on CSAccounting + validate_role_revoke_event( + dg_execution_events[57], + role_hash=contracts.cs_accounting.MANAGE_BOND_CURVES_ROLE().hex(), + account=contracts.agent.address, + emitted_by=contracts.cs_accounting + ) + + # 58. Increase CSM share in Staking Router + validate_staking_module_update_event( + dg_execution_events[58], + module_id=CS_MODULE_ID, + share_limit=CS_MODULE_NEW_TARGET_SHARE_BP, + priority_share_threshold=CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP, + module_fee_points_bp=CS_MODULE_MODULE_FEE_BP, + treasury_fee_points_bp=CS_MODULE_TREASURY_FEE_BP, + max_deposits_per_block=CS_MODULE_MAX_DEPOSITS_PER_BLOCK, + min_deposit_block_distance=CS_MODULE_MIN_DEPOSIT_BLOCK_DISTANCE, + emitted_by=contracts.staking_router + ) + + # 59-65. Gate Seals and ResealManager role updates + # 59. Revoke PAUSE_ROLE on WithdrawalQueue from the old GateSeal + validate_role_revoke_event( + dg_execution_events[59], + role_hash=contracts.withdrawal_queue.PAUSE_ROLE().hex(), + account=OLD_GATE_SEAL_ADDRESS, + emitted_by=contracts.withdrawal_queue + ) + + # 60. Revoke PAUSE_ROLE on ValidatorsExitBusOracle from the old GateSeal + validate_role_revoke_event( + dg_execution_events[60], + role_hash=contracts.validators_exit_bus_oracle.PAUSE_ROLE().hex(), + account=OLD_GATE_SEAL_ADDRESS, + emitted_by=contracts.validators_exit_bus_oracle + ) + + # 61. Grant PAUSE_ROLE on WithdrawalQueue to the new WithdrawalQueue GateSeal + validate_role_grant_event( + dg_execution_events[61], + role_hash=contracts.withdrawal_queue.PAUSE_ROLE().hex(), + account=NEW_WQ_GATE_SEAL, + emitted_by=contracts.withdrawal_queue + ) + + # 62. Grant PAUSE_ROLE on ValidatorsExitBusOracle to the new Triggerable Withdrawals GateSeal + validate_role_grant_event( + dg_execution_events[62], + role_hash=contracts.validators_exit_bus_oracle.PAUSE_ROLE().hex(), + account=NEW_TW_GATE_SEAL, + emitted_by=contracts.validators_exit_bus_oracle + ) + + # 63. Grant PAUSE_ROLE on TriggerableWithdrawalsGateway to the new Triggerable Withdrawals GateSeal + validate_role_grant_event( + dg_execution_events[63], + role_hash=triggerable_withdrawals_gateway.PAUSE_ROLE().hex(), + account=NEW_TW_GATE_SEAL, + emitted_by=triggerable_withdrawals_gateway + ) + + # 64. Grant PAUSE_ROLE on TriggerableWithdrawalsGateway to ResealManager + validate_role_grant_event( + dg_execution_events[64], + role_hash=triggerable_withdrawals_gateway.PAUSE_ROLE().hex(), + account=RESEAL_MANAGER, + emitted_by=triggerable_withdrawals_gateway + ) + + # 65. Grant RESUME_ROLE on TriggerableWithdrawalsGateway to ResealManager + validate_role_grant_event( + dg_execution_events[65], + role_hash=triggerable_withdrawals_gateway.RESUME_ROLE().hex(), + account=RESEAL_MANAGER, + emitted_by=triggerable_withdrawals_gateway + ) diff --git a/archive/tests/test_vote_update_sandbox_impl_holesky.py b/archive/tests/test_vote_update_sandbox_impl_holesky.py new file mode 100644 index 000000000..f793f50cd --- /dev/null +++ b/archive/tests/test_vote_update_sandbox_impl_holesky.py @@ -0,0 +1,137 @@ +from typing import Optional +from scripts.vote_update_sandbox_impl_holesky import start_vote +from brownie import interface, chain, convert, web3 # type: ignore +from brownie.network.event import EventDict +from utils.test.tx_tracing_helpers import group_voting_events_from_receipt, group_dg_events_from_receipt +from utils.test.event_validators.dual_governance import validate_dual_governance_submit_event +from utils.dual_governance import wait_for_noon_utc_to_satisfy_time_constrains +from utils.config import ( + DUAL_GOVERNANCE, + TIMELOCK, + DUAL_GOVERNANCE_EXECUTORS, + LDO_HOLDER_ADDRESS_FOR_TESTS, + ARAGON_KERNEL, + AGENT, + VOTING, + contracts, +) + +# Implementation address from vote script +NODE_OPERATORS_REGISTRY_IMPL = "0x834aa47DCd21A32845099a78B4aBb17A7f0bD503" +NOR_EXIT_DEADLINE_IN_SEC = 172800 +SANDBOX_APP_ID = "0x85d2fceef13a6c14c43527594f79fb91a8ef8f15024a43486efac8df2b11e632" + +def validate_role_grant_event(event: EventDict, role_name: str, account: str, emitted_by: Optional[str] = None): + """Validates a permission grant event from ACL""" + assert "SetPermission" in event, "No SetPermission event found" + assert event["SetPermission"][0]["allowed"] is True, "Permission was not granted" + assert event["SetPermission"][0]["entity"] == convert.to_address(account), "Wrong account" + + role_hash = convert.to_uint(web3.keccak(text=role_name)) + assert convert.to_uint(event["SetPermission"][0]["role"]) == role_hash, "Wrong role hash" + + if emitted_by is not None: + assert convert.to_address(event["SetPermission"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + + +def validate_role_revoke_event(event: EventDict, role_name: str, account: str, emitted_by: Optional[str] = None): + """Validates a permission revoke event from ACL""" + assert "SetPermission" in event, "No SetPermission event found" + assert event["SetPermission"][0]["allowed"] is False, "Permission was not revoked" + assert event["SetPermission"][0]["entity"] == convert.to_address(account), "Wrong account" + + role_hash = convert.to_uint(web3.keccak(text=role_name)) + assert convert.to_uint(event["SetPermission"][0]["role"]) == role_hash, "Wrong role hash" + + if emitted_by is not None: + assert convert.to_address(event["SetPermission"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + + +def validate_app_set_event(event: EventDict, app_id: str, app_addr: str, emitted_by: Optional[str] = None): + """Validates SetApp event from Kernel""" + assert "SetApp" in event, "No SetApp event found" + + app_id_bytes = bytes.fromhex(app_id.replace('0x', '')) + assert event["SetApp"][0]["appId"] == app_id_bytes, "Wrong app ID" + assert event["SetApp"][0]["appAddress"] == app_addr, "Wrong app address" + + if emitted_by is not None: + assert convert.to_address(event["SetApp"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + + +def validate_contract_version_set_event(event: EventDict, version: int, emitted_by: Optional[str] = None): + assert "ContractVersionSet" in event, "No ContractVersionSet event found" + assert event["ContractVersionSet"][0]["version"] == version, "Wrong version" + if emitted_by is not None: + assert convert.to_address(event["ContractVersionSet"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + + +def test_vote_update_sandbox_impl(helpers, accounts, vote_ids_from_env, stranger): + # Save original state for comparison + app_manager_role = web3.keccak(text="APP_MANAGER_ROLE") + + # Check initial state + assert not contracts.acl.hasPermission(AGENT, ARAGON_KERNEL, app_manager_role), "AGENT should not have APP_MANAGER_ROLE before upgrade" + + # Get sandbox contract + sandbox = interface.NodeOperatorsRegistry(contracts.sandbox) + + # Check initial sandbox version + assert sandbox.getContractVersion() < 4, "Sandbox module version should be less than 4 before upgrade" + + # Get current implementation + base_namespace = contracts.kernel.APP_BASES_NAMESPACE() + sandbox_impl_before = contracts.kernel.getApp(base_namespace, SANDBOX_APP_ID) + assert sandbox_impl_before.lower() != NODE_OPERATORS_REGISTRY_IMPL.lower(), "Sandbox implementation should be different before upgrade" + + timelock = interface.EmergencyProtectedTimelock(TIMELOCK) + dual_governance = interface.DualGovernance(DUAL_GOVERNANCE) + + # START VOTE + if len(vote_ids_from_env) > 0: + (vote_id,) = vote_ids_from_env + else: + tx_params = {"from": LDO_HOLDER_ADDRESS_FOR_TESTS} + vote_id, _ = start_vote(tx_params, silent=True) + + vote_tx = helpers.execute_vote(accounts, vote_id, contracts.voting) + print(f"voteId = {vote_id}") + + proposal_id = vote_tx.events["ProposalSubmitted"][1]["proposalId"] + print(f"proposalId = {proposal_id}") + + chain.sleep(timelock.getAfterSubmitDelay() + 1) + dual_governance.scheduleProposal(proposal_id, {"from": stranger}) + + chain.sleep(timelock.getAfterScheduleDelay() + 1) + wait_for_noon_utc_to_satisfy_time_constrains() + + dg_tx = timelock.execute(proposal_id, {"from": stranger}) + + # --- VALIDATE EXECUTION RESULTS --- + + # 1. Verify APP_MANAGER_ROLE was granted and then revoked (final state is revoked) + assert not contracts.acl.hasPermission(AGENT, ARAGON_KERNEL, app_manager_role), "AGENT should not have APP_MANAGER_ROLE after upgrade" + + # 2. Verify Sandbox implementation was updated + sandbox_impl_after = contracts.kernel.getApp(base_namespace, SANDBOX_APP_ID) + assert sandbox_impl_after.lower() == NODE_OPERATORS_REGISTRY_IMPL.lower(), "Sandbox implementation should be updated" + + # 3. Verify finalizeUpgrade_v4 was called + assert sandbox.getContractVersion() == 4, "Sandbox module version should be 4 after upgrade" + assert sandbox.exitDeadlineThreshold(0) == NOR_EXIT_DEADLINE_IN_SEC, "Sandbox exit deadline threshold should be set correctly" + + # --- VALIDATE EVENTS --- + voting_events = group_voting_events_from_receipt(vote_tx) + assert len(voting_events) >= 1, "No voting events found" + + validate_dual_governance_submit_event( + voting_events[0], + proposal_id, + proposer=VOTING, + executor=DUAL_GOVERNANCE_EXECUTORS[0], + ) + + dg_execution_events = group_dg_events_from_receipt(dg_tx, timelock=TIMELOCK, admin_executor=DUAL_GOVERNANCE_EXECUTORS[0]) + assert len(dg_execution_events) == 4, "Unexpected number of dual governance events" + diff --git a/archive/tests/test_vote_update_sandbox_impl_hoodi.py b/archive/tests/test_vote_update_sandbox_impl_hoodi.py new file mode 100644 index 000000000..e1bccbe84 --- /dev/null +++ b/archive/tests/test_vote_update_sandbox_impl_hoodi.py @@ -0,0 +1,179 @@ +from typing import Optional +from scripts.vote_update_sandbox_impl_hoodi import start_vote +from brownie import interface, chain, convert, web3 # type: ignore +from brownie.network.event import EventDict +from utils.test.tx_tracing_helpers import group_voting_events_from_receipt, group_dg_events_from_receipt +from utils.test.event_validators.dual_governance import validate_dual_governance_submit_event +from utils.dual_governance import wait_for_noon_utc_to_satisfy_time_constrains +from utils.config import ( + DUAL_GOVERNANCE, + TIMELOCK, + DUAL_GOVERNANCE_EXECUTORS, + LDO_HOLDER_ADDRESS_FOR_TESTS, + ARAGON_KERNEL, + AGENT, + VOTING, + contracts, +) + +# Implementation address from vote script +NODE_OPERATORS_REGISTRY_IMPL = "0x95F00b016bB31b7182D96D25074684518246E42a" +NOR_EXIT_DEADLINE_IN_SEC = 172800 +SANDBOX_APP_ID = "0x85d2fceef13a6c14c43527594f79fb91a8ef8f15024a43486efac8df2b11e632" + +def validate_role_grant_event(event: EventDict, role_name: str, account: str, emitted_by: Optional[str] = None): + """Validates a permission grant event from ACL""" + assert "SetPermission" in event, "No SetPermission event found" + assert event["SetPermission"][0]["allowed"] is True, "Permission was not granted" + assert event["SetPermission"][0]["entity"] == convert.to_address(account), "Wrong account" + + role_hash = convert.to_uint(web3.keccak(text=role_name)) + assert convert.to_uint(event["SetPermission"][0]["role"]) == role_hash, "Wrong role hash" + + if emitted_by is not None: + assert convert.to_address(event["SetPermission"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + + +def validate_role_revoke_event(event: EventDict, role_name: str, account: str, emitted_by: Optional[str] = None): + """Validates a permission revoke event from ACL""" + assert "SetPermission" in event, "No SetPermission event found" + assert event["SetPermission"][0]["allowed"] is False, "Permission was not revoked" + assert event["SetPermission"][0]["entity"] == convert.to_address(account), "Wrong account" + + role_hash = convert.to_uint(web3.keccak(text=role_name)) + assert convert.to_uint(event["SetPermission"][0]["role"]) == role_hash, "Wrong role hash" + + if emitted_by is not None: + assert convert.to_address(event["SetPermission"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + + +def validate_app_set_event(event: EventDict, app_id: str, app_addr: str, emitted_by: Optional[str] = None): + """Validates SetApp event from Kernel""" + assert "SetApp" in event, "No SetApp event found" + + # Convert event appId to hex string for comparison + actual_app_id = event["SetApp"][0]["appId"] + if isinstance(actual_app_id, bytes): + actual_app_id_hex = "0x" + actual_app_id.hex() + else: + actual_app_id_hex = str(actual_app_id) + + expected_app_id = app_id.lower() + assert actual_app_id_hex.lower() == expected_app_id, f"Wrong app ID: expected {expected_app_id}, got {actual_app_id_hex.lower()}" + assert convert.to_address(event["SetApp"][0]["app"]) == convert.to_address(app_addr), "Wrong app address" + + if emitted_by is not None: + assert convert.to_address(event["SetApp"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + + +def validate_contract_version_set_event(event: EventDict, version: int, emitted_by: Optional[str] = None): + assert "ContractVersionSet" in event, "No ContractVersionSet event found" + assert event["ContractVersionSet"][0]["version"] == version, "Wrong version" + if emitted_by is not None: + assert convert.to_address(event["ContractVersionSet"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + + +def test_vote_update_sandbox_impl(helpers, accounts, vote_ids_from_env, stranger): + # Save original state for comparison + app_manager_role = web3.keccak(text="APP_MANAGER_ROLE") + + # Check initial state + assert not contracts.acl.hasPermission(AGENT, ARAGON_KERNEL, app_manager_role), "AGENT should not have APP_MANAGER_ROLE before upgrade" + + # Get sandbox contract + sandbox = interface.NodeOperatorsRegistry(contracts.sandbox) + + # Check initial sandbox version + assert sandbox.getContractVersion() < 4, "Sandbox module version should be less than 4 before upgrade" + + # Get current implementation + base_namespace = contracts.kernel.APP_BASES_NAMESPACE() + sandbox_impl_before = contracts.kernel.getApp(base_namespace, SANDBOX_APP_ID) + assert sandbox_impl_before.lower() != NODE_OPERATORS_REGISTRY_IMPL.lower(), "Sandbox implementation should be different before upgrade" + + timelock = interface.EmergencyProtectedTimelock(TIMELOCK) + dual_governance = interface.DualGovernance(DUAL_GOVERNANCE) + + # START VOTE + if len(vote_ids_from_env) > 0: + (vote_id,) = vote_ids_from_env + else: + tx_params = {"from": LDO_HOLDER_ADDRESS_FOR_TESTS} + vote_id, _ = start_vote(tx_params, silent=True) + + vote_tx = helpers.execute_vote(accounts, vote_id, contracts.voting) + print(f"voteId = {vote_id}") + + proposal_id = vote_tx.events["ProposalSubmitted"][1]["proposalId"] + print(f"proposalId = {proposal_id}") + + chain.sleep(timelock.getAfterSubmitDelay() + 1) + dual_governance.scheduleProposal(proposal_id, {"from": stranger}) + + chain.sleep(timelock.getAfterScheduleDelay() + 1) + wait_for_noon_utc_to_satisfy_time_constrains() + + dg_tx = timelock.execute(proposal_id, {"from": stranger}) + + # --- VALIDATE EXECUTION RESULTS --- + + # 1. Verify APP_MANAGER_ROLE was granted and then revoked (final state is revoked) + assert not contracts.acl.hasPermission(AGENT, ARAGON_KERNEL, app_manager_role), "AGENT should not have APP_MANAGER_ROLE after upgrade" + + # 2. Verify Sandbox implementation was updated + sandbox_impl_after = contracts.kernel.getApp(base_namespace, SANDBOX_APP_ID) + assert sandbox_impl_after.lower() == NODE_OPERATORS_REGISTRY_IMPL.lower(), "Sandbox implementation should be updated" + + # 3. Verify finalizeUpgrade_v4 was called + assert sandbox.getContractVersion() == 4, "Sandbox module version should be 4 after upgrade" + assert sandbox.exitDeadlineThreshold(0) == NOR_EXIT_DEADLINE_IN_SEC, "Sandbox exit deadline threshold should be set correctly" + + # --- VALIDATE EVENTS --- + voting_events = group_voting_events_from_receipt(vote_tx) + assert len(voting_events) >= 1, "No voting events found" + + validate_dual_governance_submit_event( + voting_events[0], + proposal_id, + proposer=VOTING, + executor=DUAL_GOVERNANCE_EXECUTORS[0], + ) + + dg_execution_events = group_dg_events_from_receipt(dg_tx, timelock=TIMELOCK, admin_executor=DUAL_GOVERNANCE_EXECUTORS[0]) + assert len(dg_execution_events) == 4, "Unexpected number of dual governance events" + + # 0. Grant APP_MANAGER_ROLE to AGENT + validate_role_grant_event( + dg_execution_events[0], + "APP_MANAGER_ROLE", + AGENT, + emitted_by=contracts.acl + ) + + # 1. Update Sandbox Module implementation + validate_app_set_event( + dg_execution_events[1], + SANDBOX_APP_ID, + NODE_OPERATORS_REGISTRY_IMPL, + emitted_by=contracts.kernel + ) + + # 2. Call finalizeUpgrade_v4 on Sandbox Module + validate_contract_version_set_event( + dg_execution_events[2], + version=4, + emitted_by=contracts.sandbox + ) + + # Check that ExitDeadlineThresholdChanged event was emitted + assert 'ExitDeadlineThresholdChanged' in dg_execution_events[2], "ExitDeadlineThresholdChanged event not found" + assert dg_execution_events[2]['ExitDeadlineThresholdChanged'][0]['threshold'] == NOR_EXIT_DEADLINE_IN_SEC, "Wrong exit deadline threshold" + + # 3. Revoke APP_MANAGER_ROLE from AGENT + validate_role_revoke_event( + dg_execution_events[3], + "APP_MANAGER_ROLE", + AGENT, + emitted_by=contracts.acl + ) + diff --git a/configs/config_holesky.py b/configs/config_holesky.py index 6927fc841..77c3bbfdc 100644 --- a/configs/config_holesky.py +++ b/configs/config_holesky.py @@ -110,7 +110,7 @@ # GateSeal GATE_SEAL_FACTORY = "0x1134F7077055b0B3559BE52AfeF9aA22A0E1eEC2" -GATE_SEAL = "0x7f6FA688d4C12a2d51936680b241f3B0F0F9ca60" +GATE_SEAL = "0xAE6eCd77DCC656c5533c4209454Fd56fB46e1778" GATE_SEAL_PAUSE_DURATION = 518400 # 6 days GATE_SEAL_EXPIRY_TIMESTAMP = 1714521600 # 2024-05-01 00:00GMT GATE_SEAL_COMMITTEE = "0x6165267E76D609465640bffc158aff7905D47B46" @@ -134,14 +134,35 @@ SANDBOX_IMPL = "0x605A3AFadF35A8a8fa4f4Cd4fe34a09Bbcea7718" +CS_MODULE_ID = 4 +CS_MODULE_NAME = "Community Staking" +CS_MODULE_MODULE_FEE_BP = 700 +CS_MODULE_TREASURY_FEE_BP = 300 +CS_MODULE_TARGET_SHARE_BP = 1500 +CS_MODULE_PRIORITY_EXIT_SHARE_THRESHOLD = 2000 +CS_MODULE_MAX_DEPOSITS_PER_BLOCK = 30 +CS_MODULE_MIN_DEPOSIT_BLOCK_DISTANCE = 25 +CSM_COMMITTEE_MS = "0xc4DAB3a3ef68C6DFd8614a870D64D475bA44F164" # EOA CSM_ADDRESS = "0x4562c3e63c2e586cD1651B958C22F88135aCAd4f" CS_ACCOUNTING_ADDRESS = "0xc093e53e8F4b55A223c18A2Da6fA00e60DD5EFE1" CS_ORACLE_HASH_CONSENSUS_ADDRESS = "0xbF38618Ea09B503c1dED867156A0ea276Ca1AE37" CS_EARLY_ADOPTION_ADDRESS = "0x71E92eA77C198a770d9f33A03277DbeB99989660" CS_FEE_DISTRIBUTOR_ADDRESS = "0xD7ba648C8F72669C6aE649648B516ec03D07c8ED" CS_FEE_ORACLE_ADDRESS = "0xaF57326C7d513085051b50912D51809ECC5d98Ee" -CS_GATE_SEAL_ADDRESS = "0x41F2677fae0222cF1f08Cd1c0AAa607B469654Ce" +CS_GATE_SEAL_ADDRESS = "0xf1C03536dbC77B1bD493a2D1C0b1831Ea78B540a" CS_VERIFIER_ADDRESS = "0xc099dfd61f6e5420e0ca7e84d820daad17fc1d44" CS_ORACLE_EPOCHS_PER_FRAME = 225 * 7 # 7 days CS_VERIFIER_ADDRESS_OLD = "0x6FDAA094227CF8E1593f9fB9C1b867C1f846F916" + +# DUAL_GOVERNANCE +DUAL_GOVERNANCE = "0x490bf377734CA134A8E207525E8576745652212e" +TIMELOCK = "0xe9c5FfEAd0668AFdBB9aac16163840d649DB76DD" +DUAL_GOVERNANCE_ADMIN_EXECUTOR = "0x8BD0a916faDa88Ba3accb595a3Acd28F467130e8" +DUAL_GOVERNANCE_EXECUTORS = [DUAL_GOVERNANCE_ADMIN_EXECUTOR] +RESEAL_MANAGER = "0x9dE2273f9f1e81145171CcA927EFeE7aCC64c9fb" +DAO_EMERGENCY_GOVERNANCE = "0x46c6C7E1Cc438456d658Eed61A764a475abDa0C1" +AGENT_MANAGER = "0xc807d4036B400dE8f6cD2aDbd8d9cf9a3a01CC30" +TIME_CONSTRAINTS = "0x4D36598EA14bd70a1040CF59ABF6f9439afBf5d9" +ROLES_VALIDATOR = "0xf532fC0a18D3339A52b3f1152FcA9925De5855AA" +ALLOWED_TOKENS_REGISTRY = "0x091C0eC8B4D54a9fcB36269B5D5E5AF43309e666" diff --git a/configs/config_hoodi.py b/configs/config_hoodi.py index b433e0d0a..24c84baaf 100644 --- a/configs/config_hoodi.py +++ b/configs/config_hoodi.py @@ -1,10 +1,8 @@ -ACCOUNTING_ORACLE = "0xcb883B1bD0a41512b42D2dB267F2A2cd919FB216" -VALIDATORS_EXIT_BUS_ORACLE = "0x8664d394C2B3278F26A1B44B967aEf99707eeAB2" -AO_CONSENSUS_VERSION = 3 - +# Ethereum Chain parameters CHAIN_NETWORK_NAME = "hoodi" # DAO +ARAGON_KERNEL = "0xA48DF029Fd2e5FCECB3886c5c2F60e3625A1E87d" LDO_TOKEN = "0xEf2573966D009CcEA0Fc74451dee2193564198dc" # Standard (or forked) Aragon apps @@ -14,14 +12,17 @@ VOTING = "0x49B3512c44891bef83F8967d075121Bd1b07a01B" TOKEN_MANAGER = "0x8ab4a56721Ad8e68c6Ad86F9D9929782A78E39E5" -# Custom Aragon apps +SANDBOX = "0x682E94d2630846a503BDeE8b6810DF71C9806891" +SANDBOX_IMPL = "0x95F00b016bB31b7182D96D25074684518246E42a" +SANDBOX_REPO = "0x89D37eC788988e98BEceB32a8774394F1338B09C" + +# Our custom Aragon apps LIDO = "0x3508A952176b3c15387C97BE809eaffB1982176a" +NODE_OPERATORS_REGISTRY = "0x5cDbE1590c083b5A2A64427fAA63A7cfDB91FbB5" SIMPLE_DVT = "0x0B5236BECA68004DB89434462DfC3BB074d2c830" -CS_FEE_ORACLE_ADDRESS = "0xe7314f561B2e72f9543F1004e741bab6Fc51028B" -CS_VERIFIER_ADDRESS = "0xB6bafBD970a4537077dE59cebE33081d794513d6" -CS_VERIFIER_ADDRESS_OLD = "0x16D0f6068D211608e3703323314aa976a6492D09" -CSM_ADDRESS = "0x79CEf36D84743222f37765204Bec41E92a93E59d" +# Other (non-aragon) protocol contracts +WITHDRAWAL_VAULT = "0x4473dCDDbf77679A643BdB654dbd86D67F8d32f2" # EasyTracks EASYTRACK = "0x284D91a7D47850d21A6DEaaC6E538AC7E5E6fc2a" @@ -29,7 +30,6 @@ EASYTRACK_EVMSCRIPT_EXECUTOR = "0x79a20FD0FA36453B2F45eAbab19bfef43575Ba9E" EASYTRACK_INCREASE_NOP_STAKING_LIMIT_FACTORY = "0x0f121e4069e17a2Dc5bAbF39d769313a1e20f323" EASYTRACK_SIMPLE_DVT_TRUSTED_CALLER = "0xbB958292042c604855d23F8db458855d20e16996" - EASYTRACK_SIMPLE_DVT_ADD_NODE_OPERATORS_FACTORY = "0x42f2532ab3d41dfD6030db1EC2fF3DBC8DCdf89a" EASYTRACK_SIMPLE_DVT_ACTIVATE_NODE_OPERATORS_FACTORY = "0xfA3B3EE204E1f0f165379326768667300992530e" EASYTRACK_SIMPLE_DVT_DEACTIVATE_NODE_OPERATORS_FACTORY = "0x3114bEbC222Faec27DF8AB7f9bD8dF2063d7fc77" @@ -41,11 +41,12 @@ EASYTRACK_MEV_BOOST_ADD_RELAYS_FACTORY = "0xF02DbeaA1Bbc90226CaB995db4C190DbE25983af" EASYTRACK_MEV_BOOST_REMOVE_RELAYS_FACTORY = "0x7FCc2901C6C3D62784cB178B14d44445B038f736" EASYTRACK_MEV_BOOST_EDIT_RELAYS_FACTORY = "0x27A99a7104190DdA297B222104A6C70A4Ca5A17e" +EASYTRACK_SDVT_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY = "0xAa3D6A8B52447F272c1E8FAaA06EA06658bd95E2" +EASYTRACK_CURATED_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY = "0x397206ecdbdcb1A55A75e60Fc4D054feC72E5f63" +EASYTRACK_CS_SET_VETTED_GATE_TREE_FACTORY = "0xa890fc73e1b771Ee6073e2402E631c312FF92Cd9" # Other RELAY_ALLOWED_LIST = "0x279d3A456212a1294DaEd0faEE98675a52E8A4Bf" - -# Other (non-aragon) protocol contracts WSTETH_TOKEN = "0x7E99eE3C66636DE415D2d7C880938F2f40f94De4" LDO_HOLDER_ADDRESS_FOR_TESTS = "0xD500a8aDB182F55741E267730dfbfb4F1944C205" @@ -55,12 +56,71 @@ "0xc3C65cB7aa6D36F051f875708b8E17f9a0B210eD", ] +# LidoLocator +LIDO_LOCATOR = "0xe2EF9536DAAAEBFf5b1c130957AB3E80056b06D8" + +# NodeOperatorsRegistry aka Curated Staking Module +## see NodeOperatorsRegistry's proxy appId() +NODE_OPERATORS_REGISTRY_ARAGON_APP_ID = "0x7071f283424072341f856ac9e947e7ec0eb68719f757a7e785979b6b8717579d" + +# NodeOperatorsRegistry clone aka SimpleDVT +## see SimpleDVT's proxy appId() +SIMPLE_DVT_ARAGON_APP_ID = "0xe1635b63b5f7b5e545f2a637558a4029dea7905361a2f0fc28c66e9136cf86a4" + +# CSM staking router parameters +CS_MODULE_ID = 4 +CS_MODULE_NAME = "Community Staking" +CS_MODULE_MODULE_FEE_BP = 600 +CS_MODULE_TREASURY_FEE_BP = 400 +CS_MODULE_TARGET_SHARE_BP = 1600 +CS_MODULE_PRIORITY_EXIT_SHARE_THRESHOLD = 2100 +CS_MODULE_MAX_DEPOSITS_PER_BLOCK = 30 +CS_MODULE_MIN_DEPOSIT_BLOCK_DISTANCE = 25 + +# OracleDaemonConfig +ORACLE_DAEMON_CONFIG = "0x2a833402e3F46fFC1ecAb3598c599147a78731a9" + +# AccountingOracle +# and its corresponding HashConsensus +ACCOUNTING_ORACLE = "0xcb883B1bD0a41512b42D2dB267F2A2cd919FB216" +ACCOUNTING_ORACLE_CONSENSUS_VERSION = 4 # updated from 3 to 4 after vote + +# ValidatorsExitBusOracle +VALIDATORS_EXIT_BUS_ORACLE = "0x8664d394C2B3278F26A1B44B967aEf99707eeAB2" +VALIDATORS_EXIT_BUS_CONSENSUS_VERSION = 4 # added after vote + +# CSOracle +CS_ORACLE_EPOCHS_PER_FRAME = 225 * 7 # 7 days +CS_ORACLE_CONSENSUS_VERSION = 3 + # WithdrawalQueueERC721 WITHDRAWAL_QUEUE = "0xfe56573178f1bcdf53F01A6E9977670dcBBD9186" # StakingRouter STAKING_ROUTER = "0xCc820558B39ee15C7C45B59390B503b83fb499A8" +# Triggerable Withdrawals Gateway +TRIGGERABLE_WITHDRAWALS_GATEWAY = "0x6679090D92b08a2a686eF8614feECD8cDFE209db" +VALIDATOR_EXIT_VERIFIER = "0xFd4386A8795956f4B6D01cbb6dB116749731D7bD" + +# CSM addresses +CSM_COMMITTEE_MS = "0x4AF43Ee34a6fcD1fEcA1e1F832124C763561dA53" +CSM_ADDRESS = "0x79CEf36D84743222f37765204Bec41E92a93E59d" +CS_ACCOUNTING_ADDRESS = "0xA54b90BA34C5f326BC1485054080994e38FB4C60" +CS_ORACLE_HASH_CONSENSUS_ADDRESS = "0x54f74a10e4397dDeF85C4854d9dfcA129D72C637" +CS_EARLY_ADOPTION_ADDRESS = "0x3281b9E45518F462E594697f8fba1896a8B43939" +CS_FEE_DISTRIBUTOR_ADDRESS = "0xaCd9820b0A2229a82dc1A0770307ce5522FF3582" +CS_FEE_ORACLE_ADDRESS = "0xe7314f561B2e72f9543F1004e741bab6Fc51028B" +CS_VERIFIER_ADDRESS = "0xf805b3711cBB48F15Ae2bb27095ddC38c5339968" +CS_EJECTOR_ADDRESS = "0x21e271cBa32672B106737AbeB3a45E53Fe9a0df4" +CS_PERMISSIONLESS_GATE_ADDRESS = "0x5553077102322689876A6AdFd48D75014c28acfb" +CS_VETTED_GATE_ADDRESS = "0x10a254E724fe2b7f305F76f3F116a3969c53845f" + +# Gate Seals +CS_GATE_SEAL_ADDRESS = "0x94a3aEB0E9148F64CB453Be2BDe2Bc0148f6AC24" +WITHDRAWAL_QUEUE_GATE_SEAL_ADDRESS = "0x73d76Bd3D589B2b2185c402da82cdAfbc18b958D" +TRIGGERABLE_WITHDRAWALS_GATE_SEAL_ADDRESS = "0x368f2fcb593170823cc844F1B29e75E3d26879A1" + # DualGovernance DUAL_GOVERNANCE = "0x9CAaCCc62c66d817CC59c44780D1b722359795bF" diff --git a/interfaces/AccountingOracle.json b/interfaces/AccountingOracle.json index 069da4f74..35c6e7e9f 100644 --- a/interfaces/AccountingOracle.json +++ b/interfaces/AccountingOracle.json @@ -50,6 +50,22 @@ "name": "CannotSubmitExtraDataBeforeMainData", "type": "error" }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "itemIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "dataType", + "type": "uint256" + } + ], + "name": "DeprecatedExtraDataType", + "type": "error" + }, { "inputs": [], "name": "ExtraDataAlreadyProcessed", @@ -334,11 +350,6 @@ "name": "UnexpectedExtraDataItemsCount", "type": "error" }, - { - "inputs": [], - "name": "UnexpectedExtraDataLength", - "type": "error" - }, { "inputs": [ { @@ -834,6 +845,13 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [], + "name": "finalizeUpgrade_v3", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [], "name": "getConsensusContract", diff --git a/interfaces/CSAccounting.json b/interfaces/CSAccounting.json new file mode 100644 index 000000000..8eaef61dc --- /dev/null +++ b/interfaces/CSAccounting.json @@ -0,0 +1 @@ +[{"type":"constructor","inputs":[{"name":"lidoLocator","type":"address","internalType":"address"},{"name":"module","type":"address","internalType":"address"},{"name":"_feeDistributor","type":"address","internalType":"address"},{"name":"maxCurveLength","type":"uint256","internalType":"uint256"},{"name":"minBondLockPeriod","type":"uint256","internalType":"uint256"},{"name":"maxBondLockPeriod","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"DEFAULT_ADMIN_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"DEFAULT_BOND_CURVE_ID","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"FEE_DISTRIBUTOR","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ICSFeeDistributor"}],"stateMutability":"view"},{"type":"function","name":"LIDO","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ILido"}],"stateMutability":"view"},{"type":"function","name":"LIDO_LOCATOR","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ILidoLocator"}],"stateMutability":"view"},{"type":"function","name":"MANAGE_BOND_CURVES_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"MAX_BOND_LOCK_PERIOD","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"MAX_CURVE_LENGTH","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"MIN_BOND_LOCK_PERIOD","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"MIN_CURVE_LENGTH","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"MODULE","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ICSModule"}],"stateMutability":"view"},{"type":"function","name":"PAUSE_INFINITELY","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"PAUSE_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"RECOVERER_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"RESUME_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"SET_BOND_CURVE_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"WITHDRAWAL_QUEUE","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IWithdrawalQueue"}],"stateMutability":"view"},{"type":"function","name":"WSTETH","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IWstETH"}],"stateMutability":"view"},{"type":"function","name":"addBondCurve","inputs":[{"name":"bondCurve","type":"tuple[]","internalType":"struct ICSBondCurve.BondCurveIntervalInput[]","components":[{"name":"minKeysCount","type":"uint256","internalType":"uint256"},{"name":"trend","type":"uint256","internalType":"uint256"}]}],"outputs":[{"name":"id","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"chargeFee","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"amount","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"chargePenaltyRecipient","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"claimRewardsStETH","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"stETHAmount","type":"uint256","internalType":"uint256"},{"name":"cumulativeFeeShares","type":"uint256","internalType":"uint256"},{"name":"rewardsProof","type":"bytes32[]","internalType":"bytes32[]"}],"outputs":[{"name":"claimedShares","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"claimRewardsUnstETH","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"stEthAmount","type":"uint256","internalType":"uint256"},{"name":"cumulativeFeeShares","type":"uint256","internalType":"uint256"},{"name":"rewardsProof","type":"bytes32[]","internalType":"bytes32[]"}],"outputs":[{"name":"requestId","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"claimRewardsWstETH","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"wstETHAmount","type":"uint256","internalType":"uint256"},{"name":"cumulativeFeeShares","type":"uint256","internalType":"uint256"},{"name":"rewardsProof","type":"bytes32[]","internalType":"bytes32[]"}],"outputs":[{"name":"claimedWstETH","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"compensateLockedBondETH","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"payable"},{"type":"function","name":"depositETH","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"payable"},{"type":"function","name":"depositETH","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"payable"},{"type":"function","name":"depositStETH","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"stETHAmount","type":"uint256","internalType":"uint256"},{"name":"permit","type":"tuple","internalType":"struct ICSAccounting.PermitInput","components":[{"name":"value","type":"uint256","internalType":"uint256"},{"name":"deadline","type":"uint256","internalType":"uint256"},{"name":"v","type":"uint8","internalType":"uint8"},{"name":"r","type":"bytes32","internalType":"bytes32"},{"name":"s","type":"bytes32","internalType":"bytes32"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"depositStETH","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"stETHAmount","type":"uint256","internalType":"uint256"},{"name":"permit","type":"tuple","internalType":"struct ICSAccounting.PermitInput","components":[{"name":"value","type":"uint256","internalType":"uint256"},{"name":"deadline","type":"uint256","internalType":"uint256"},{"name":"v","type":"uint8","internalType":"uint8"},{"name":"r","type":"bytes32","internalType":"bytes32"},{"name":"s","type":"bytes32","internalType":"bytes32"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"depositWstETH","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"wstETHAmount","type":"uint256","internalType":"uint256"},{"name":"permit","type":"tuple","internalType":"struct ICSAccounting.PermitInput","components":[{"name":"value","type":"uint256","internalType":"uint256"},{"name":"deadline","type":"uint256","internalType":"uint256"},{"name":"v","type":"uint8","internalType":"uint8"},{"name":"r","type":"bytes32","internalType":"bytes32"},{"name":"s","type":"bytes32","internalType":"bytes32"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"depositWstETH","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"wstETHAmount","type":"uint256","internalType":"uint256"},{"name":"permit","type":"tuple","internalType":"struct ICSAccounting.PermitInput","components":[{"name":"value","type":"uint256","internalType":"uint256"},{"name":"deadline","type":"uint256","internalType":"uint256"},{"name":"v","type":"uint8","internalType":"uint8"},{"name":"r","type":"bytes32","internalType":"bytes32"},{"name":"s","type":"bytes32","internalType":"bytes32"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"feeDistributor","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ICSFeeDistributor"}],"stateMutability":"view"},{"type":"function","name":"finalizeUpgradeV2","inputs":[{"name":"bondCurvesInputs","type":"tuple[][]","internalType":"struct ICSBondCurve.BondCurveIntervalInput[][]","components":[{"name":"minKeysCount","type":"uint256","internalType":"uint256"},{"name":"trend","type":"uint256","internalType":"uint256"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"getActualLockedBond","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getBond","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getBondAmountByKeysCount","inputs":[{"name":"keys","type":"uint256","internalType":"uint256"},{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getBondAmountByKeysCountWstETH","inputs":[{"name":"keysCount","type":"uint256","internalType":"uint256"},{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getBondCurve","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"tuple","internalType":"struct ICSBondCurve.BondCurve","components":[{"name":"intervals","type":"tuple[]","internalType":"struct ICSBondCurve.BondCurveInterval[]","components":[{"name":"minKeysCount","type":"uint256","internalType":"uint256"},{"name":"minBond","type":"uint256","internalType":"uint256"},{"name":"trend","type":"uint256","internalType":"uint256"}]}]}],"stateMutability":"view"},{"type":"function","name":"getBondCurveId","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getBondLockPeriod","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getBondShares","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getBondSummary","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"current","type":"uint256","internalType":"uint256"},{"name":"required","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getBondSummaryShares","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"current","type":"uint256","internalType":"uint256"},{"name":"required","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getClaimableBondShares","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getClaimableRewardsAndBondShares","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"cumulativeFeeShares","type":"uint256","internalType":"uint256"},{"name":"rewardsProof","type":"bytes32[]","internalType":"bytes32[]"}],"outputs":[{"name":"claimableShares","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getCurveInfo","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"tuple","internalType":"struct ICSBondCurve.BondCurve","components":[{"name":"intervals","type":"tuple[]","internalType":"struct ICSBondCurve.BondCurveInterval[]","components":[{"name":"minKeysCount","type":"uint256","internalType":"uint256"},{"name":"minBond","type":"uint256","internalType":"uint256"},{"name":"trend","type":"uint256","internalType":"uint256"}]}]}],"stateMutability":"view"},{"type":"function","name":"getCurvesCount","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getInitializedVersion","inputs":[],"outputs":[{"name":"","type":"uint64","internalType":"uint64"}],"stateMutability":"view"},{"type":"function","name":"getKeysCountByBondAmount","inputs":[{"name":"amount","type":"uint256","internalType":"uint256"},{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getLockedBondInfo","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"tuple","internalType":"struct ICSBondLock.BondLock","components":[{"name":"amount","type":"uint128","internalType":"uint128"},{"name":"until","type":"uint128","internalType":"uint128"}]}],"stateMutability":"view"},{"type":"function","name":"getRequiredBondForNextKeys","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"additionalKeys","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getRequiredBondForNextKeysWstETH","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"additionalKeys","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getResumeSinceTimestamp","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getRoleAdmin","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"getRoleMember","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"index","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"getRoleMemberCount","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getUnbondedKeysCount","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getUnbondedKeysCountToEject","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"grantRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"hasRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"initialize","inputs":[{"name":"bondCurve","type":"tuple[]","internalType":"struct ICSBondCurve.BondCurveIntervalInput[]","components":[{"name":"minKeysCount","type":"uint256","internalType":"uint256"},{"name":"trend","type":"uint256","internalType":"uint256"}]},{"name":"admin","type":"address","internalType":"address"},{"name":"bondLockPeriod","type":"uint256","internalType":"uint256"},{"name":"_chargePenaltyRecipient","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"isPaused","inputs":[],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"lockBondETH","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"amount","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"pauseFor","inputs":[{"name":"duration","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"penalize","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"amount","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"pullFeeRewards","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"cumulativeFeeShares","type":"uint256","internalType":"uint256"},{"name":"rewardsProof","type":"bytes32[]","internalType":"bytes32[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"recoverERC1155","inputs":[{"name":"token","type":"address","internalType":"address"},{"name":"tokenId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"recoverERC20","inputs":[{"name":"token","type":"address","internalType":"address"},{"name":"amount","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"recoverERC721","inputs":[{"name":"token","type":"address","internalType":"address"},{"name":"tokenId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"recoverEther","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"recoverStETHShares","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"releaseLockedBondETH","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"amount","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"renewBurnerAllowance","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"renounceRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"callerConfirmation","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"resume","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"revokeRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setBondCurve","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setBondLockPeriod","inputs":[{"name":"period","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setChargePenaltyRecipient","inputs":[{"name":"_chargePenaltyRecipient","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"settleLockedBondETH","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"applied","type":"bool","internalType":"bool"}],"stateMutability":"nonpayable"},{"type":"function","name":"supportsInterface","inputs":[{"name":"interfaceId","type":"bytes4","internalType":"bytes4"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"totalBondShares","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"updateBondCurve","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"},{"name":"bondCurve","type":"tuple[]","internalType":"struct ICSBondCurve.BondCurveIntervalInput[]","components":[{"name":"minKeysCount","type":"uint256","internalType":"uint256"},{"name":"trend","type":"uint256","internalType":"uint256"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"event","name":"BondBurned","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"toBurnAmount","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"burnedAmount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"BondCharged","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"toChargeAmount","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"chargedAmount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"BondClaimedStETH","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"to","type":"address","indexed":false,"internalType":"address"},{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"BondClaimedUnstETH","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"to","type":"address","indexed":false,"internalType":"address"},{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"requestId","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"BondClaimedWstETH","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"to","type":"address","indexed":false,"internalType":"address"},{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"BondCurveAdded","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"bondCurveIntervals","type":"tuple[]","indexed":false,"internalType":"struct ICSBondCurve.BondCurveIntervalInput[]","components":[{"name":"minKeysCount","type":"uint256","internalType":"uint256"},{"name":"trend","type":"uint256","internalType":"uint256"}]}],"anonymous":false},{"type":"event","name":"BondCurveSet","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"curveId","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"BondCurveUpdated","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"bondCurveIntervals","type":"tuple[]","indexed":false,"internalType":"struct ICSBondCurve.BondCurveIntervalInput[]","components":[{"name":"minKeysCount","type":"uint256","internalType":"uint256"},{"name":"trend","type":"uint256","internalType":"uint256"}]}],"anonymous":false},{"type":"event","name":"BondDepositedETH","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"from","type":"address","indexed":false,"internalType":"address"},{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"BondDepositedStETH","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"from","type":"address","indexed":false,"internalType":"address"},{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"BondDepositedWstETH","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"from","type":"address","indexed":false,"internalType":"address"},{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"BondLockChanged","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"newAmount","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"until","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"BondLockCompensated","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"BondLockPeriodChanged","inputs":[{"name":"period","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"BondLockRemoved","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ChargePenaltyRecipientSet","inputs":[{"name":"chargePenaltyRecipient","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"ERC1155Recovered","inputs":[{"name":"token","type":"address","indexed":true,"internalType":"address"},{"name":"tokenId","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"recipient","type":"address","indexed":true,"internalType":"address"},{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ERC20Recovered","inputs":[{"name":"token","type":"address","indexed":true,"internalType":"address"},{"name":"recipient","type":"address","indexed":true,"internalType":"address"},{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ERC721Recovered","inputs":[{"name":"token","type":"address","indexed":true,"internalType":"address"},{"name":"tokenId","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"recipient","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"EtherRecovered","inputs":[{"name":"recipient","type":"address","indexed":true,"internalType":"address"},{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"Initialized","inputs":[{"name":"version","type":"uint64","indexed":false,"internalType":"uint64"}],"anonymous":false},{"type":"event","name":"Paused","inputs":[{"name":"duration","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"Resumed","inputs":[],"anonymous":false},{"type":"event","name":"RoleAdminChanged","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"previousAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"newAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"}],"anonymous":false},{"type":"event","name":"RoleGranted","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"RoleRevoked","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"StETHSharesRecovered","inputs":[{"name":"recipient","type":"address","indexed":true,"internalType":"address"},{"name":"shares","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"error","name":"AccessControlBadConfirmation","inputs":[]},{"type":"error","name":"AccessControlUnauthorizedAccount","inputs":[{"name":"account","type":"address","internalType":"address"},{"name":"neededRole","type":"bytes32","internalType":"bytes32"}]},{"type":"error","name":"ElRewardsVaultReceiveFailed","inputs":[]},{"type":"error","name":"FailedToSendEther","inputs":[]},{"type":"error","name":"InvalidBondCurveId","inputs":[]},{"type":"error","name":"InvalidBondCurveLength","inputs":[]},{"type":"error","name":"InvalidBondCurveMaxLength","inputs":[]},{"type":"error","name":"InvalidBondCurveValues","inputs":[]},{"type":"error","name":"InvalidBondCurvesLength","inputs":[]},{"type":"error","name":"InvalidBondLockAmount","inputs":[]},{"type":"error","name":"InvalidBondLockPeriod","inputs":[]},{"type":"error","name":"InvalidInitialization","inputs":[]},{"type":"error","name":"InvalidInitializationCurveId","inputs":[]},{"type":"error","name":"NodeOperatorDoesNotExist","inputs":[]},{"type":"error","name":"NotAllowedToRecover","inputs":[]},{"type":"error","name":"NotInitializing","inputs":[]},{"type":"error","name":"NothingToClaim","inputs":[]},{"type":"error","name":"PauseUntilMustBeInFuture","inputs":[]},{"type":"error","name":"PausedExpected","inputs":[]},{"type":"error","name":"ResumedExpected","inputs":[]},{"type":"error","name":"SafeCastOverflowedUintDowncast","inputs":[{"name":"bits","type":"uint8","internalType":"uint8"},{"name":"value","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"SenderIsNotEligible","inputs":[]},{"type":"error","name":"SenderIsNotModule","inputs":[]},{"type":"error","name":"ZeroAdminAddress","inputs":[]},{"type":"error","name":"ZeroChargePenaltyRecipientAddress","inputs":[]},{"type":"error","name":"ZeroFeeDistributorAddress","inputs":[]},{"type":"error","name":"ZeroLocatorAddress","inputs":[]},{"type":"error","name":"ZeroModuleAddress","inputs":[]},{"type":"error","name":"ZeroPauseDuration","inputs":[]}] diff --git a/interfaces/csm/CSEarlyAdoption.json b/interfaces/CSEarlyAdoption.json similarity index 100% rename from interfaces/csm/CSEarlyAdoption.json rename to interfaces/CSEarlyAdoption.json diff --git a/interfaces/CSEjector.json b/interfaces/CSEjector.json new file mode 100644 index 000000000..c27efed2b --- /dev/null +++ b/interfaces/CSEjector.json @@ -0,0 +1 @@ +[{"type":"constructor","inputs":[{"name":"module","type":"address","internalType":"address"},{"name":"strikes","type":"address","internalType":"address"},{"name":"twg","type":"address","internalType":"address"},{"name":"stakingModuleId","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"DEFAULT_ADMIN_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"MODULE","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ICSModule"}],"stateMutability":"view"},{"type":"function","name":"PAUSE_INFINITELY","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"PAUSE_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"RESUME_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"STAKING_MODULE_ID","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"STRIKES","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"STRIKES_EXIT_TYPE_ID","inputs":[],"outputs":[{"name":"","type":"uint8","internalType":"uint8"}],"stateMutability":"view"},{"type":"function","name":"TWG","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ITriggerableWithdrawalsGateway"}],"stateMutability":"view"},{"type":"function","name":"VOLUNTARY_EXIT_TYPE_ID","inputs":[],"outputs":[{"name":"","type":"uint8","internalType":"uint8"}],"stateMutability":"view"},{"type":"function","name":"ejectBadPerformer","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"keyIndex","type":"uint256","internalType":"uint256"},{"name":"refundRecipient","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"payable"},{"type":"function","name":"getResumeSinceTimestamp","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getRoleAdmin","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"getRoleMember","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"index","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"getRoleMemberCount","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"grantRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"hasRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"initialize","inputs":[{"name":"admin","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"isPaused","inputs":[],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"pauseFor","inputs":[{"name":"duration","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"renounceRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"callerConfirmation","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"resume","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"revokeRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"supportsInterface","inputs":[{"name":"interfaceId","type":"bytes4","internalType":"bytes4"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"voluntaryEject","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"startFrom","type":"uint256","internalType":"uint256"},{"name":"keysCount","type":"uint256","internalType":"uint256"},{"name":"refundRecipient","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"payable"},{"type":"function","name":"voluntaryEjectByArray","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"keyIndices","type":"uint256[]","internalType":"uint256[]"},{"name":"refundRecipient","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"payable"},{"type":"event","name":"Initialized","inputs":[{"name":"version","type":"uint64","indexed":false,"internalType":"uint64"}],"anonymous":false},{"type":"event","name":"Paused","inputs":[{"name":"duration","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"Resumed","inputs":[],"anonymous":false},{"type":"event","name":"RoleAdminChanged","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"previousAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"newAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"}],"anonymous":false},{"type":"event","name":"RoleGranted","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"RoleRevoked","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"error","name":"AccessControlBadConfirmation","inputs":[]},{"type":"error","name":"AccessControlUnauthorizedAccount","inputs":[{"name":"account","type":"address","internalType":"address"},{"name":"neededRole","type":"bytes32","internalType":"bytes32"}]},{"type":"error","name":"AlreadyWithdrawn","inputs":[]},{"type":"error","name":"InvalidInitialization","inputs":[]},{"type":"error","name":"NodeOperatorDoesNotExist","inputs":[]},{"type":"error","name":"NotInitializing","inputs":[]},{"type":"error","name":"PauseUntilMustBeInFuture","inputs":[]},{"type":"error","name":"PausedExpected","inputs":[]},{"type":"error","name":"ResumedExpected","inputs":[]},{"type":"error","name":"SenderIsNotEligible","inputs":[]},{"type":"error","name":"SenderIsNotStrikes","inputs":[]},{"type":"error","name":"SigningKeysInvalidOffset","inputs":[]},{"type":"error","name":"ZeroAdminAddress","inputs":[]},{"type":"error","name":"ZeroModuleAddress","inputs":[]},{"type":"error","name":"ZeroPauseDuration","inputs":[]},{"type":"error","name":"ZeroStrikesAddress","inputs":[]},{"type":"error","name":"ZeroTWGAddress","inputs":[]}] diff --git a/interfaces/CSExitPenalties.json b/interfaces/CSExitPenalties.json new file mode 100644 index 000000000..e45976af2 --- /dev/null +++ b/interfaces/CSExitPenalties.json @@ -0,0 +1 @@ +[{"type":"constructor","inputs":[{"name":"module","type":"address","internalType":"address"},{"name":"parametersRegistry","type":"address","internalType":"address"},{"name":"strikes","type":"address","internalType":"address"}],"stateMutability":"nonpayable"},{"type":"function","name":"ACCOUNTING","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ICSAccounting"}],"stateMutability":"view"},{"type":"function","name":"MODULE","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ICSModule"}],"stateMutability":"view"},{"type":"function","name":"PARAMETERS_REGISTRY","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ICSParametersRegistry"}],"stateMutability":"view"},{"type":"function","name":"STRIKES","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"STRIKES_EXIT_TYPE_ID","inputs":[],"outputs":[{"name":"","type":"uint8","internalType":"uint8"}],"stateMutability":"view"},{"type":"function","name":"VOLUNTARY_EXIT_TYPE_ID","inputs":[],"outputs":[{"name":"","type":"uint8","internalType":"uint8"}],"stateMutability":"view"},{"type":"function","name":"getExitPenaltyInfo","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"publicKey","type":"bytes","internalType":"bytes"}],"outputs":[{"name":"","type":"tuple","internalType":"struct ExitPenaltyInfo","components":[{"name":"delayPenalty","type":"tuple","internalType":"struct MarkedUint248","components":[{"name":"value","type":"uint248","internalType":"uint248"},{"name":"isValue","type":"bool","internalType":"bool"}]},{"name":"strikesPenalty","type":"tuple","internalType":"struct MarkedUint248","components":[{"name":"value","type":"uint248","internalType":"uint248"},{"name":"isValue","type":"bool","internalType":"bool"}]},{"name":"withdrawalRequestFee","type":"tuple","internalType":"struct MarkedUint248","components":[{"name":"value","type":"uint248","internalType":"uint248"},{"name":"isValue","type":"bool","internalType":"bool"}]}]}],"stateMutability":"view"},{"type":"function","name":"isValidatorExitDelayPenaltyApplicable","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"publicKey","type":"bytes","internalType":"bytes"},{"name":"eligibleToExitInSec","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"processExitDelayReport","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"publicKey","type":"bytes","internalType":"bytes"},{"name":"eligibleToExitInSec","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"processStrikesReport","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"publicKey","type":"bytes","internalType":"bytes"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"processTriggeredExit","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"publicKey","type":"bytes","internalType":"bytes"},{"name":"withdrawalRequestPaidFee","type":"uint256","internalType":"uint256"},{"name":"exitType","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"event","name":"StrikesPenaltyProcessed","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"pubkey","type":"bytes","indexed":false,"internalType":"bytes"},{"name":"strikesPenalty","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"TriggeredExitFeeRecorded","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"exitType","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"pubkey","type":"bytes","indexed":false,"internalType":"bytes"},{"name":"withdrawalRequestFee","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ValidatorExitDelayProcessed","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"pubkey","type":"bytes","indexed":false,"internalType":"bytes"},{"name":"delayPenalty","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"error","name":"SafeCastOverflowedUintDowncast","inputs":[{"name":"bits","type":"uint8","internalType":"uint8"},{"name":"value","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"SenderIsNotModule","inputs":[]},{"type":"error","name":"SenderIsNotStrikes","inputs":[]},{"type":"error","name":"ValidatorExitDelayAlreadyReported","inputs":[]},{"type":"error","name":"ValidatorExitDelayNotApplicable","inputs":[]},{"type":"error","name":"ZeroAccountingAddress","inputs":[]},{"type":"error","name":"ZeroModuleAddress","inputs":[]},{"type":"error","name":"ZeroParametersRegistryAddress","inputs":[]},{"type":"error","name":"ZeroStrikesAddress","inputs":[]}] diff --git a/interfaces/CSFeeDistributor.json b/interfaces/CSFeeDistributor.json new file mode 100644 index 000000000..e5f46981c --- /dev/null +++ b/interfaces/CSFeeDistributor.json @@ -0,0 +1 @@ +[{"type":"constructor","inputs":[{"name":"stETH","type":"address","internalType":"address"},{"name":"accounting","type":"address","internalType":"address"},{"name":"oracle","type":"address","internalType":"address"}],"stateMutability":"nonpayable"},{"type":"function","name":"ACCOUNTING","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"DEFAULT_ADMIN_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"ORACLE","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"RECOVERER_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"STETH","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IStETH"}],"stateMutability":"view"},{"type":"function","name":"distributeFees","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"shares","type":"uint256","internalType":"uint256"},{"name":"proof","type":"bytes32[]","internalType":"bytes32[]"}],"outputs":[{"name":"sharesToDistribute","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"distributedShares","inputs":[{"name":"","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"distributionDataHistoryCount","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"finalizeUpgradeV2","inputs":[{"name":"_rebateRecipient","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"getFeesToDistribute","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"shares","type":"uint256","internalType":"uint256"},{"name":"proof","type":"bytes32[]","internalType":"bytes32[]"}],"outputs":[{"name":"sharesToDistribute","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getHistoricalDistributionData","inputs":[{"name":"index","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"tuple","internalType":"struct ICSFeeDistributor.DistributionData","components":[{"name":"refSlot","type":"uint256","internalType":"uint256"},{"name":"treeRoot","type":"bytes32","internalType":"bytes32"},{"name":"treeCid","type":"string","internalType":"string"},{"name":"logCid","type":"string","internalType":"string"},{"name":"distributed","type":"uint256","internalType":"uint256"},{"name":"rebate","type":"uint256","internalType":"uint256"}]}],"stateMutability":"view"},{"type":"function","name":"getInitializedVersion","inputs":[],"outputs":[{"name":"","type":"uint64","internalType":"uint64"}],"stateMutability":"view"},{"type":"function","name":"getRoleAdmin","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"getRoleMember","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"index","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"getRoleMemberCount","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"grantRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"hasRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"hashLeaf","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"shares","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"pure"},{"type":"function","name":"initialize","inputs":[{"name":"admin","type":"address","internalType":"address"},{"name":"_rebateRecipient","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"logCid","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"type":"function","name":"pendingSharesToDistribute","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"processOracleReport","inputs":[{"name":"_treeRoot","type":"bytes32","internalType":"bytes32"},{"name":"_treeCid","type":"string","internalType":"string"},{"name":"_logCid","type":"string","internalType":"string"},{"name":"distributed","type":"uint256","internalType":"uint256"},{"name":"rebate","type":"uint256","internalType":"uint256"},{"name":"refSlot","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"rebateRecipient","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"recoverERC1155","inputs":[{"name":"token","type":"address","internalType":"address"},{"name":"tokenId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"recoverERC20","inputs":[{"name":"token","type":"address","internalType":"address"},{"name":"amount","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"recoverERC721","inputs":[{"name":"token","type":"address","internalType":"address"},{"name":"tokenId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"recoverEther","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"renounceRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"callerConfirmation","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"revokeRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setRebateRecipient","inputs":[{"name":"_rebateRecipient","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"supportsInterface","inputs":[{"name":"interfaceId","type":"bytes4","internalType":"bytes4"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"totalClaimableShares","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"treeCid","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"type":"function","name":"treeRoot","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"event","name":"DistributionDataUpdated","inputs":[{"name":"totalClaimableShares","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"treeRoot","type":"bytes32","indexed":false,"internalType":"bytes32"},{"name":"treeCid","type":"string","indexed":false,"internalType":"string"}],"anonymous":false},{"type":"event","name":"DistributionLogUpdated","inputs":[{"name":"logCid","type":"string","indexed":false,"internalType":"string"}],"anonymous":false},{"type":"event","name":"ERC1155Recovered","inputs":[{"name":"token","type":"address","indexed":true,"internalType":"address"},{"name":"tokenId","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"recipient","type":"address","indexed":true,"internalType":"address"},{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ERC20Recovered","inputs":[{"name":"token","type":"address","indexed":true,"internalType":"address"},{"name":"recipient","type":"address","indexed":true,"internalType":"address"},{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ERC721Recovered","inputs":[{"name":"token","type":"address","indexed":true,"internalType":"address"},{"name":"tokenId","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"recipient","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"EtherRecovered","inputs":[{"name":"recipient","type":"address","indexed":true,"internalType":"address"},{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"Initialized","inputs":[{"name":"version","type":"uint64","indexed":false,"internalType":"uint64"}],"anonymous":false},{"type":"event","name":"ModuleFeeDistributed","inputs":[{"name":"shares","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"OperatorFeeDistributed","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"shares","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"RebateRecipientSet","inputs":[{"name":"recipient","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"RebateTransferred","inputs":[{"name":"shares","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"RoleAdminChanged","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"previousAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"newAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"}],"anonymous":false},{"type":"event","name":"RoleGranted","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"RoleRevoked","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"StETHSharesRecovered","inputs":[{"name":"recipient","type":"address","indexed":true,"internalType":"address"},{"name":"shares","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"error","name":"AccessControlBadConfirmation","inputs":[]},{"type":"error","name":"AccessControlUnauthorizedAccount","inputs":[{"name":"account","type":"address","internalType":"address"},{"name":"neededRole","type":"bytes32","internalType":"bytes32"}]},{"type":"error","name":"FailedToSendEther","inputs":[]},{"type":"error","name":"FeeSharesDecrease","inputs":[]},{"type":"error","name":"InvalidInitialization","inputs":[]},{"type":"error","name":"InvalidLogCID","inputs":[]},{"type":"error","name":"InvalidProof","inputs":[]},{"type":"error","name":"InvalidReportData","inputs":[]},{"type":"error","name":"InvalidShares","inputs":[]},{"type":"error","name":"InvalidTreeCid","inputs":[]},{"type":"error","name":"InvalidTreeRoot","inputs":[]},{"type":"error","name":"NotAccounting","inputs":[]},{"type":"error","name":"NotAllowedToRecover","inputs":[]},{"type":"error","name":"NotEnoughShares","inputs":[]},{"type":"error","name":"NotInitializing","inputs":[]},{"type":"error","name":"NotOracle","inputs":[]},{"type":"error","name":"ZeroAccountingAddress","inputs":[]},{"type":"error","name":"ZeroAdminAddress","inputs":[]},{"type":"error","name":"ZeroOracleAddress","inputs":[]},{"type":"error","name":"ZeroRebateRecipientAddress","inputs":[]},{"type":"error","name":"ZeroStEthAddress","inputs":[]}] diff --git a/interfaces/CSFeeOracle.json b/interfaces/CSFeeOracle.json new file mode 100644 index 000000000..6d13c0c2c --- /dev/null +++ b/interfaces/CSFeeOracle.json @@ -0,0 +1 @@ +[{"type":"constructor","inputs":[{"name":"feeDistributor","type":"address","internalType":"address"},{"name":"strikes","type":"address","internalType":"address"},{"name":"secondsPerSlot","type":"uint256","internalType":"uint256"},{"name":"genesisTime","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"DEFAULT_ADMIN_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"FEE_DISTRIBUTOR","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ICSFeeDistributor"}],"stateMutability":"view"},{"type":"function","name":"GENESIS_TIME","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"MANAGE_CONSENSUS_CONTRACT_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"MANAGE_CONSENSUS_VERSION_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"PAUSE_INFINITELY","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"PAUSE_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"RECOVERER_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"RESUME_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"SECONDS_PER_SLOT","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"STRIKES","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ICSStrikes"}],"stateMutability":"view"},{"type":"function","name":"SUBMIT_DATA_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"discardConsensusReport","inputs":[{"name":"refSlot","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"finalizeUpgradeV2","inputs":[{"name":"consensusVersion","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"getConsensusContract","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"getConsensusReport","inputs":[],"outputs":[{"name":"hash","type":"bytes32","internalType":"bytes32"},{"name":"refSlot","type":"uint256","internalType":"uint256"},{"name":"processingDeadlineTime","type":"uint256","internalType":"uint256"},{"name":"processingStarted","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"getConsensusVersion","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getContractVersion","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getLastProcessingRefSlot","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getResumeSinceTimestamp","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getRoleAdmin","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"getRoleMember","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"index","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"getRoleMemberCount","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"grantRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"hasRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"initialize","inputs":[{"name":"admin","type":"address","internalType":"address"},{"name":"consensusContract","type":"address","internalType":"address"},{"name":"consensusVersion","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"isPaused","inputs":[],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"pauseFor","inputs":[{"name":"duration","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"pauseUntil","inputs":[{"name":"pauseUntilInclusive","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"recoverERC1155","inputs":[{"name":"token","type":"address","internalType":"address"},{"name":"tokenId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"recoverERC20","inputs":[{"name":"token","type":"address","internalType":"address"},{"name":"amount","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"recoverERC721","inputs":[{"name":"token","type":"address","internalType":"address"},{"name":"tokenId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"recoverEther","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"renounceRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"callerConfirmation","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"resume","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"revokeRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setConsensusContract","inputs":[{"name":"addr","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setConsensusVersion","inputs":[{"name":"version","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"submitConsensusReport","inputs":[{"name":"reportHash","type":"bytes32","internalType":"bytes32"},{"name":"refSlot","type":"uint256","internalType":"uint256"},{"name":"deadline","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"submitReportData","inputs":[{"name":"data","type":"tuple","internalType":"struct ICSFeeOracle.ReportData","components":[{"name":"consensusVersion","type":"uint256","internalType":"uint256"},{"name":"refSlot","type":"uint256","internalType":"uint256"},{"name":"treeRoot","type":"bytes32","internalType":"bytes32"},{"name":"treeCid","type":"string","internalType":"string"},{"name":"logCid","type":"string","internalType":"string"},{"name":"distributed","type":"uint256","internalType":"uint256"},{"name":"rebate","type":"uint256","internalType":"uint256"},{"name":"strikesTreeRoot","type":"bytes32","internalType":"bytes32"},{"name":"strikesTreeCid","type":"string","internalType":"string"}]},{"name":"contractVersion","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"supportsInterface","inputs":[{"name":"interfaceId","type":"bytes4","internalType":"bytes4"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"event","name":"ConsensusHashContractSet","inputs":[{"name":"addr","type":"address","indexed":true,"internalType":"address"},{"name":"prevAddr","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"ConsensusVersionSet","inputs":[{"name":"version","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"prevVersion","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ContractVersionSet","inputs":[{"name":"version","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ERC1155Recovered","inputs":[{"name":"token","type":"address","indexed":true,"internalType":"address"},{"name":"tokenId","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"recipient","type":"address","indexed":true,"internalType":"address"},{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ERC20Recovered","inputs":[{"name":"token","type":"address","indexed":true,"internalType":"address"},{"name":"recipient","type":"address","indexed":true,"internalType":"address"},{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ERC721Recovered","inputs":[{"name":"token","type":"address","indexed":true,"internalType":"address"},{"name":"tokenId","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"recipient","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"EtherRecovered","inputs":[{"name":"recipient","type":"address","indexed":true,"internalType":"address"},{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"Initialized","inputs":[{"name":"version","type":"uint64","indexed":false,"internalType":"uint64"}],"anonymous":false},{"type":"event","name":"Paused","inputs":[{"name":"duration","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ProcessingStarted","inputs":[{"name":"refSlot","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"hash","type":"bytes32","indexed":false,"internalType":"bytes32"}],"anonymous":false},{"type":"event","name":"ReportDiscarded","inputs":[{"name":"refSlot","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"hash","type":"bytes32","indexed":false,"internalType":"bytes32"}],"anonymous":false},{"type":"event","name":"ReportSubmitted","inputs":[{"name":"refSlot","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"hash","type":"bytes32","indexed":false,"internalType":"bytes32"},{"name":"processingDeadlineTime","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"Resumed","inputs":[],"anonymous":false},{"type":"event","name":"RoleAdminChanged","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"previousAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"newAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"}],"anonymous":false},{"type":"event","name":"RoleGranted","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"RoleRevoked","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"StETHSharesRecovered","inputs":[{"name":"recipient","type":"address","indexed":true,"internalType":"address"},{"name":"shares","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"WarnProcessingMissed","inputs":[{"name":"refSlot","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"type":"error","name":"AccessControlBadConfirmation","inputs":[]},{"type":"error","name":"AccessControlUnauthorizedAccount","inputs":[{"name":"account","type":"address","internalType":"address"},{"name":"neededRole","type":"bytes32","internalType":"bytes32"}]},{"type":"error","name":"AddressCannotBeSame","inputs":[]},{"type":"error","name":"AddressCannotBeZero","inputs":[]},{"type":"error","name":"FailedToSendEther","inputs":[]},{"type":"error","name":"HashCannotBeZero","inputs":[]},{"type":"error","name":"InitialRefSlotCannotBeLessThanProcessingOne","inputs":[{"name":"initialRefSlot","type":"uint256","internalType":"uint256"},{"name":"processingRefSlot","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"InvalidContractVersion","inputs":[]},{"type":"error","name":"InvalidContractVersionIncrement","inputs":[]},{"type":"error","name":"InvalidInitialization","inputs":[]},{"type":"error","name":"NoConsensusReportToProcess","inputs":[]},{"type":"error","name":"NonZeroContractVersionOnInit","inputs":[]},{"type":"error","name":"NotAllowedToRecover","inputs":[]},{"type":"error","name":"NotInitializing","inputs":[]},{"type":"error","name":"PauseUntilMustBeInFuture","inputs":[]},{"type":"error","name":"PausedExpected","inputs":[]},{"type":"error","name":"ProcessingDeadlineMissed","inputs":[{"name":"deadline","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"RefSlotAlreadyProcessing","inputs":[]},{"type":"error","name":"RefSlotCannotDecrease","inputs":[{"name":"refSlot","type":"uint256","internalType":"uint256"},{"name":"prevRefSlot","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"RefSlotMustBeGreaterThanProcessingOne","inputs":[{"name":"refSlot","type":"uint256","internalType":"uint256"},{"name":"processingRefSlot","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"ResumedExpected","inputs":[]},{"type":"error","name":"SafeCastOverflowedUintDowncast","inputs":[{"name":"bits","type":"uint8","internalType":"uint8"},{"name":"value","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"SecondsPerSlotCannotBeZero","inputs":[]},{"type":"error","name":"SenderIsNotTheConsensusContract","inputs":[]},{"type":"error","name":"SenderNotAllowed","inputs":[]},{"type":"error","name":"UnexpectedChainConfig","inputs":[]},{"type":"error","name":"UnexpectedConsensusVersion","inputs":[{"name":"expectedVersion","type":"uint256","internalType":"uint256"},{"name":"receivedVersion","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"UnexpectedContractVersion","inputs":[{"name":"expected","type":"uint256","internalType":"uint256"},{"name":"received","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"UnexpectedDataHash","inputs":[{"name":"consensusHash","type":"bytes32","internalType":"bytes32"},{"name":"receivedHash","type":"bytes32","internalType":"bytes32"}]},{"type":"error","name":"UnexpectedRefSlot","inputs":[{"name":"consensusRefSlot","type":"uint256","internalType":"uint256"},{"name":"dataRefSlot","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"VersionCannotBeSame","inputs":[]},{"type":"error","name":"VersionCannotBeZero","inputs":[]},{"type":"error","name":"ZeroAdminAddress","inputs":[]},{"type":"error","name":"ZeroFeeDistributorAddress","inputs":[]},{"type":"error","name":"ZeroPauseDuration","inputs":[]},{"type":"error","name":"ZeroStrikesAddress","inputs":[]}] diff --git a/interfaces/CSHashConsensus.json b/interfaces/CSHashConsensus.json new file mode 100644 index 000000000..bb18bbdca --- /dev/null +++ b/interfaces/CSHashConsensus.json @@ -0,0 +1 @@ +[{"type":"constructor","inputs":[{"name":"slotsPerEpoch","type":"uint256","internalType":"uint256"},{"name":"secondsPerSlot","type":"uint256","internalType":"uint256"},{"name":"genesisTime","type":"uint256","internalType":"uint256"},{"name":"epochsPerFrame","type":"uint256","internalType":"uint256"},{"name":"fastLaneLengthSlots","type":"uint256","internalType":"uint256"},{"name":"admin","type":"address","internalType":"address"},{"name":"reportProcessor","type":"address","internalType":"address"}],"stateMutability":"nonpayable"},{"type":"function","name":"DEFAULT_ADMIN_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"DISABLE_CONSENSUS_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"MANAGE_FAST_LANE_CONFIG_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"MANAGE_FRAME_CONFIG_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"MANAGE_MEMBERS_AND_QUORUM_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"MANAGE_REPORT_PROCESSOR_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"addMember","inputs":[{"name":"addr","type":"address","internalType":"address"},{"name":"quorum","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"disableConsensus","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"getChainConfig","inputs":[],"outputs":[{"name":"slotsPerEpoch","type":"uint256","internalType":"uint256"},{"name":"secondsPerSlot","type":"uint256","internalType":"uint256"},{"name":"genesisTime","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getConsensusState","inputs":[],"outputs":[{"name":"refSlot","type":"uint256","internalType":"uint256"},{"name":"consensusReport","type":"bytes32","internalType":"bytes32"},{"name":"isReportProcessing","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"getConsensusStateForMember","inputs":[{"name":"addr","type":"address","internalType":"address"}],"outputs":[{"name":"result","type":"tuple","internalType":"struct HashConsensus.MemberConsensusState","components":[{"name":"currentFrameRefSlot","type":"uint256","internalType":"uint256"},{"name":"currentFrameConsensusReport","type":"bytes32","internalType":"bytes32"},{"name":"isMember","type":"bool","internalType":"bool"},{"name":"isFastLane","type":"bool","internalType":"bool"},{"name":"canReport","type":"bool","internalType":"bool"},{"name":"lastMemberReportRefSlot","type":"uint256","internalType":"uint256"},{"name":"currentFrameMemberReport","type":"bytes32","internalType":"bytes32"}]}],"stateMutability":"view"},{"type":"function","name":"getCurrentFrame","inputs":[],"outputs":[{"name":"refSlot","type":"uint256","internalType":"uint256"},{"name":"reportProcessingDeadlineSlot","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getFastLaneMembers","inputs":[],"outputs":[{"name":"addresses","type":"address[]","internalType":"address[]"},{"name":"lastReportedRefSlots","type":"uint256[]","internalType":"uint256[]"}],"stateMutability":"view"},{"type":"function","name":"getFrameConfig","inputs":[],"outputs":[{"name":"initialEpoch","type":"uint256","internalType":"uint256"},{"name":"epochsPerFrame","type":"uint256","internalType":"uint256"},{"name":"fastLaneLengthSlots","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getInitialRefSlot","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getIsFastLaneMember","inputs":[{"name":"addr","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"getIsMember","inputs":[{"name":"addr","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"getMembers","inputs":[],"outputs":[{"name":"addresses","type":"address[]","internalType":"address[]"},{"name":"lastReportedRefSlots","type":"uint256[]","internalType":"uint256[]"}],"stateMutability":"view"},{"type":"function","name":"getQuorum","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getReportProcessor","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"getReportVariants","inputs":[],"outputs":[{"name":"variants","type":"bytes32[]","internalType":"bytes32[]"},{"name":"support","type":"uint256[]","internalType":"uint256[]"}],"stateMutability":"view"},{"type":"function","name":"getRoleAdmin","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"getRoleMember","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"index","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"getRoleMemberCount","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"grantRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"hasRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"removeMember","inputs":[{"name":"addr","type":"address","internalType":"address"},{"name":"quorum","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"renounceRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"callerConfirmation","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"revokeRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setFastLaneLengthSlots","inputs":[{"name":"fastLaneLengthSlots","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setFrameConfig","inputs":[{"name":"epochsPerFrame","type":"uint256","internalType":"uint256"},{"name":"fastLaneLengthSlots","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setQuorum","inputs":[{"name":"quorum","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setReportProcessor","inputs":[{"name":"newProcessor","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"submitReport","inputs":[{"name":"slot","type":"uint256","internalType":"uint256"},{"name":"report","type":"bytes32","internalType":"bytes32"},{"name":"consensusVersion","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"supportsInterface","inputs":[{"name":"interfaceId","type":"bytes4","internalType":"bytes4"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"updateInitialEpoch","inputs":[{"name":"initialEpoch","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"event","name":"ConsensusLost","inputs":[{"name":"refSlot","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ConsensusReached","inputs":[{"name":"refSlot","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"report","type":"bytes32","indexed":false,"internalType":"bytes32"},{"name":"support","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"FastLaneConfigSet","inputs":[{"name":"fastLaneLengthSlots","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"FrameConfigSet","inputs":[{"name":"newInitialEpoch","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"newEpochsPerFrame","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"Initialized","inputs":[{"name":"version","type":"uint64","indexed":false,"internalType":"uint64"}],"anonymous":false},{"type":"event","name":"MemberAdded","inputs":[{"name":"addr","type":"address","indexed":true,"internalType":"address"},{"name":"newTotalMembers","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"newQuorum","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"MemberRemoved","inputs":[{"name":"addr","type":"address","indexed":true,"internalType":"address"},{"name":"newTotalMembers","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"newQuorum","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"QuorumSet","inputs":[{"name":"newQuorum","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"totalMembers","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"prevQuorum","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ReportProcessorSet","inputs":[{"name":"processor","type":"address","indexed":true,"internalType":"address"},{"name":"prevProcessor","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"ReportReceived","inputs":[{"name":"refSlot","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"member","type":"address","indexed":true,"internalType":"address"},{"name":"report","type":"bytes32","indexed":false,"internalType":"bytes32"}],"anonymous":false},{"type":"event","name":"RoleAdminChanged","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"previousAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"newAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"}],"anonymous":false},{"type":"event","name":"RoleGranted","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"RoleRevoked","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"error","name":"AccessControlBadConfirmation","inputs":[]},{"type":"error","name":"AccessControlUnauthorizedAccount","inputs":[{"name":"account","type":"address","internalType":"address"},{"name":"neededRole","type":"bytes32","internalType":"bytes32"}]},{"type":"error","name":"AddressCannotBeZero","inputs":[]},{"type":"error","name":"AdminCannotBeZero","inputs":[]},{"type":"error","name":"ConsensusReportAlreadyProcessing","inputs":[]},{"type":"error","name":"DuplicateMember","inputs":[]},{"type":"error","name":"DuplicateReport","inputs":[]},{"type":"error","name":"EmptyReport","inputs":[]},{"type":"error","name":"EpochsPerFrameCannotBeZero","inputs":[]},{"type":"error","name":"FastLanePeriodCannotBeLongerThanFrame","inputs":[]},{"type":"error","name":"InitialEpochAlreadyArrived","inputs":[]},{"type":"error","name":"InitialEpochIsYetToArrive","inputs":[]},{"type":"error","name":"InitialEpochRefSlotCannotBeEarlierThanProcessingSlot","inputs":[]},{"type":"error","name":"InvalidChainConfig","inputs":[]},{"type":"error","name":"InvalidInitialization","inputs":[]},{"type":"error","name":"InvalidSlot","inputs":[]},{"type":"error","name":"NewProcessorCannotBeTheSame","inputs":[]},{"type":"error","name":"NonFastLaneMemberCannotReportWithinFastLaneInterval","inputs":[]},{"type":"error","name":"NonMember","inputs":[]},{"type":"error","name":"NotInitializing","inputs":[]},{"type":"error","name":"NumericOverflow","inputs":[]},{"type":"error","name":"QuorumTooSmall","inputs":[{"name":"minQuorum","type":"uint256","internalType":"uint256"},{"name":"receivedQuorum","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"ReportProcessorCannotBeZero","inputs":[]},{"type":"error","name":"SafeCastOverflowedUintDowncast","inputs":[{"name":"bits","type":"uint8","internalType":"uint8"},{"name":"value","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"StaleReport","inputs":[]},{"type":"error","name":"UnexpectedConsensusVersion","inputs":[{"name":"expected","type":"uint256","internalType":"uint256"},{"name":"received","type":"uint256","internalType":"uint256"}]}] diff --git a/interfaces/CSModule.json b/interfaces/CSModule.json new file mode 100644 index 000000000..67ac8332a --- /dev/null +++ b/interfaces/CSModule.json @@ -0,0 +1 @@ +[{"type":"constructor","inputs":[{"name":"moduleType","type":"bytes32","internalType":"bytes32"},{"name":"lidoLocator","type":"address","internalType":"address"},{"name":"parametersRegistry","type":"address","internalType":"address"},{"name":"_accounting","type":"address","internalType":"address"},{"name":"exitPenalties","type":"address","internalType":"address"}],"stateMutability":"nonpayable"},{"type":"function","name":"ACCOUNTING","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ICSAccounting"}],"stateMutability":"view"},{"type":"function","name":"CREATE_NODE_OPERATOR_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"DEFAULT_ADMIN_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"DEPOSIT_SIZE","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"EXIT_PENALTIES","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ICSExitPenalties"}],"stateMutability":"view"},{"type":"function","name":"LIDO_LOCATOR","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ILidoLocator"}],"stateMutability":"view"},{"type":"function","name":"PARAMETERS_REGISTRY","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ICSParametersRegistry"}],"stateMutability":"view"},{"type":"function","name":"PAUSE_INFINITELY","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"PAUSE_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"QUEUE_LEGACY_PRIORITY","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"QUEUE_LOWEST_PRIORITY","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"RECOVERER_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"REPORT_EL_REWARDS_STEALING_PENALTY_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"RESUME_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"SETTLE_EL_REWARDS_STEALING_PENALTY_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"STAKING_ROUTER_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"STETH","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IStETH"}],"stateMutability":"view"},{"type":"function","name":"VERIFIER_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"accounting","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ICSAccounting"}],"stateMutability":"view"},{"type":"function","name":"addValidatorKeysETH","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"keysCount","type":"uint256","internalType":"uint256"},{"name":"publicKeys","type":"bytes","internalType":"bytes"},{"name":"signatures","type":"bytes","internalType":"bytes"}],"outputs":[],"stateMutability":"payable"},{"type":"function","name":"addValidatorKeysStETH","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"keysCount","type":"uint256","internalType":"uint256"},{"name":"publicKeys","type":"bytes","internalType":"bytes"},{"name":"signatures","type":"bytes","internalType":"bytes"},{"name":"permit","type":"tuple","internalType":"struct ICSAccounting.PermitInput","components":[{"name":"value","type":"uint256","internalType":"uint256"},{"name":"deadline","type":"uint256","internalType":"uint256"},{"name":"v","type":"uint8","internalType":"uint8"},{"name":"r","type":"bytes32","internalType":"bytes32"},{"name":"s","type":"bytes32","internalType":"bytes32"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"addValidatorKeysWstETH","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"keysCount","type":"uint256","internalType":"uint256"},{"name":"publicKeys","type":"bytes","internalType":"bytes"},{"name":"signatures","type":"bytes","internalType":"bytes"},{"name":"permit","type":"tuple","internalType":"struct ICSAccounting.PermitInput","components":[{"name":"value","type":"uint256","internalType":"uint256"},{"name":"deadline","type":"uint256","internalType":"uint256"},{"name":"v","type":"uint8","internalType":"uint8"},{"name":"r","type":"bytes32","internalType":"bytes32"},{"name":"s","type":"bytes32","internalType":"bytes32"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"cancelELRewardsStealingPenalty","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"amount","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"changeNodeOperatorRewardAddress","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"newAddress","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"cleanDepositQueue","inputs":[{"name":"maxItems","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"removed","type":"uint256","internalType":"uint256"},{"name":"lastRemovedAtDepth","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"compensateELRewardsStealingPenalty","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"payable"},{"type":"function","name":"confirmNodeOperatorManagerAddressChange","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"confirmNodeOperatorRewardAddressChange","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"createNodeOperator","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"managementProperties","type":"tuple","internalType":"struct NodeOperatorManagementProperties","components":[{"name":"managerAddress","type":"address","internalType":"address"},{"name":"rewardAddress","type":"address","internalType":"address"},{"name":"extendedManagerPermissions","type":"bool","internalType":"bool"}]},{"name":"referrer","type":"address","internalType":"address"}],"outputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"decreaseVettedSigningKeysCount","inputs":[{"name":"nodeOperatorIds","type":"bytes","internalType":"bytes"},{"name":"vettedSigningKeysCounts","type":"bytes","internalType":"bytes"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"depositQueueItem","inputs":[{"name":"queuePriority","type":"uint256","internalType":"uint256"},{"name":"index","type":"uint128","internalType":"uint128"}],"outputs":[{"name":"","type":"uint256","internalType":"Batch"}],"stateMutability":"view"},{"type":"function","name":"depositQueuePointers","inputs":[{"name":"queuePriority","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"head","type":"uint128","internalType":"uint128"},{"name":"tail","type":"uint128","internalType":"uint128"}],"stateMutability":"view"},{"type":"function","name":"exitDeadlineThreshold","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"finalizeUpgradeV2","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"getActiveNodeOperatorsCount","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getInitializedVersion","inputs":[],"outputs":[{"name":"","type":"uint64","internalType":"uint64"}],"stateMutability":"view"},{"type":"function","name":"getNodeOperator","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"tuple","internalType":"struct NodeOperator","components":[{"name":"totalAddedKeys","type":"uint32","internalType":"uint32"},{"name":"totalWithdrawnKeys","type":"uint32","internalType":"uint32"},{"name":"totalDepositedKeys","type":"uint32","internalType":"uint32"},{"name":"totalVettedKeys","type":"uint32","internalType":"uint32"},{"name":"stuckValidatorsCount","type":"uint32","internalType":"uint32"},{"name":"depositableValidatorsCount","type":"uint32","internalType":"uint32"},{"name":"targetLimit","type":"uint32","internalType":"uint32"},{"name":"targetLimitMode","type":"uint8","internalType":"uint8"},{"name":"totalExitedKeys","type":"uint32","internalType":"uint32"},{"name":"enqueuedCount","type":"uint32","internalType":"uint32"},{"name":"managerAddress","type":"address","internalType":"address"},{"name":"proposedManagerAddress","type":"address","internalType":"address"},{"name":"rewardAddress","type":"address","internalType":"address"},{"name":"proposedRewardAddress","type":"address","internalType":"address"},{"name":"extendedManagerPermissions","type":"bool","internalType":"bool"},{"name":"usedPriorityQueue","type":"bool","internalType":"bool"}]}],"stateMutability":"view"},{"type":"function","name":"getNodeOperatorIds","inputs":[{"name":"offset","type":"uint256","internalType":"uint256"},{"name":"limit","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"nodeOperatorIds","type":"uint256[]","internalType":"uint256[]"}],"stateMutability":"view"},{"type":"function","name":"getNodeOperatorIsActive","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"getNodeOperatorManagementProperties","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"tuple","internalType":"struct NodeOperatorManagementProperties","components":[{"name":"managerAddress","type":"address","internalType":"address"},{"name":"rewardAddress","type":"address","internalType":"address"},{"name":"extendedManagerPermissions","type":"bool","internalType":"bool"}]}],"stateMutability":"view"},{"type":"function","name":"getNodeOperatorNonWithdrawnKeys","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getNodeOperatorSummary","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"targetLimitMode","type":"uint256","internalType":"uint256"},{"name":"targetValidatorsCount","type":"uint256","internalType":"uint256"},{"name":"stuckValidatorsCount","type":"uint256","internalType":"uint256"},{"name":"refundedValidatorsCount","type":"uint256","internalType":"uint256"},{"name":"stuckPenaltyEndTimestamp","type":"uint256","internalType":"uint256"},{"name":"totalExitedValidators","type":"uint256","internalType":"uint256"},{"name":"totalDepositedValidators","type":"uint256","internalType":"uint256"},{"name":"depositableValidatorsCount","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getNodeOperatorTotalDepositedKeys","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"totalDepositedKeys","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getNodeOperatorsCount","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getNonce","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getResumeSinceTimestamp","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getRoleAdmin","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"getRoleMember","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"index","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"getRoleMemberCount","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getSigningKeys","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"startIndex","type":"uint256","internalType":"uint256"},{"name":"keysCount","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bytes","internalType":"bytes"}],"stateMutability":"view"},{"type":"function","name":"getSigningKeysWithSignatures","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"startIndex","type":"uint256","internalType":"uint256"},{"name":"keysCount","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"keys","type":"bytes","internalType":"bytes"},{"name":"signatures","type":"bytes","internalType":"bytes"}],"stateMutability":"view"},{"type":"function","name":"getStakingModuleSummary","inputs":[],"outputs":[{"name":"totalExitedValidators","type":"uint256","internalType":"uint256"},{"name":"totalDepositedValidators","type":"uint256","internalType":"uint256"},{"name":"depositableValidatorsCount","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getType","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"grantRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"hasRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"initialize","inputs":[{"name":"admin","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"isPaused","inputs":[],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"isValidatorExitDelayPenaltyApplicable","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"","type":"uint256","internalType":"uint256"},{"name":"publicKey","type":"bytes","internalType":"bytes"},{"name":"eligibleToExitInSec","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"isValidatorWithdrawn","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"keyIndex","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"legacyQueue","inputs":[],"outputs":[{"name":"head","type":"uint128","internalType":"uint128"},{"name":"tail","type":"uint128","internalType":"uint128"}],"stateMutability":"view"},{"type":"function","name":"migrateToPriorityQueue","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"obtainDepositData","inputs":[{"name":"depositsCount","type":"uint256","internalType":"uint256"},{"name":"","type":"bytes","internalType":"bytes"}],"outputs":[{"name":"publicKeys","type":"bytes","internalType":"bytes"},{"name":"signatures","type":"bytes","internalType":"bytes"}],"stateMutability":"nonpayable"},{"type":"function","name":"onExitedAndStuckValidatorsCountsUpdated","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"onRewardsMinted","inputs":[{"name":"totalShares","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"onValidatorExitTriggered","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"publicKey","type":"bytes","internalType":"bytes"},{"name":"withdrawalRequestPaidFee","type":"uint256","internalType":"uint256"},{"name":"exitType","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"onWithdrawalCredentialsChanged","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"pauseFor","inputs":[{"name":"duration","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"proposeNodeOperatorManagerAddressChange","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"proposedAddress","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"proposeNodeOperatorRewardAddressChange","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"proposedAddress","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"recoverERC1155","inputs":[{"name":"token","type":"address","internalType":"address"},{"name":"tokenId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"recoverERC20","inputs":[{"name":"token","type":"address","internalType":"address"},{"name":"amount","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"recoverERC721","inputs":[{"name":"token","type":"address","internalType":"address"},{"name":"tokenId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"recoverEther","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"removeKeys","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"startIndex","type":"uint256","internalType":"uint256"},{"name":"keysCount","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"renounceRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"callerConfirmation","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"reportELRewardsStealingPenalty","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"blockHash","type":"bytes32","internalType":"bytes32"},{"name":"amount","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"reportValidatorExitDelay","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"","type":"uint256","internalType":"uint256"},{"name":"publicKey","type":"bytes","internalType":"bytes"},{"name":"eligibleToExitInSec","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"resetNodeOperatorManagerAddress","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"resume","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"revokeRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"settleELRewardsStealingPenalty","inputs":[{"name":"nodeOperatorIds","type":"uint256[]","internalType":"uint256[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"submitWithdrawals","inputs":[{"name":"withdrawalsInfo","type":"tuple[]","internalType":"struct ValidatorWithdrawalInfo[]","components":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"keyIndex","type":"uint256","internalType":"uint256"},{"name":"amount","type":"uint256","internalType":"uint256"},{"name":"isSlashed","type":"bool","internalType":"bool"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"supportsInterface","inputs":[{"name":"interfaceId","type":"bytes4","internalType":"bytes4"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"unsafeUpdateValidatorsCount","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"exitedValidatorsKeysCount","type":"uint256","internalType":"uint256"},{"name":"stuckValidatorsKeysCount","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateDepositableValidatorsCount","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateExitedValidatorsCount","inputs":[{"name":"nodeOperatorIds","type":"bytes","internalType":"bytes"},{"name":"exitedValidatorsCounts","type":"bytes","internalType":"bytes"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateTargetValidatorsLimits","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"targetLimitMode","type":"uint256","internalType":"uint256"},{"name":"targetLimit","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"event","name":"BatchEnqueued","inputs":[{"name":"queuePriority","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"count","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"DelayedValidatorExitPenalized","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"penaltyValue","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"DepositableSigningKeysCountChanged","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"depositableKeysCount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"DepositedSigningKeysCountChanged","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"depositedKeysCount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ELRewardsStealingPenaltyCancelled","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ELRewardsStealingPenaltyCompensated","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ELRewardsStealingPenaltyReported","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"proposedBlockHash","type":"bytes32","indexed":false,"internalType":"bytes32"},{"name":"stolenAmount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ELRewardsStealingPenaltySettled","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ERC1155Recovered","inputs":[{"name":"token","type":"address","indexed":true,"internalType":"address"},{"name":"tokenId","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"recipient","type":"address","indexed":true,"internalType":"address"},{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ERC20Recovered","inputs":[{"name":"token","type":"address","indexed":true,"internalType":"address"},{"name":"recipient","type":"address","indexed":true,"internalType":"address"},{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ERC721Recovered","inputs":[{"name":"token","type":"address","indexed":true,"internalType":"address"},{"name":"tokenId","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"recipient","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"EtherRecovered","inputs":[{"name":"recipient","type":"address","indexed":true,"internalType":"address"},{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ExitedSigningKeysCountChanged","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"exitedKeysCount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"Initialized","inputs":[{"name":"version","type":"uint64","indexed":false,"internalType":"uint64"}],"anonymous":false},{"type":"event","name":"KeyRemovalChargeApplied","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"NodeOperatorAdded","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"managerAddress","type":"address","indexed":true,"internalType":"address"},{"name":"rewardAddress","type":"address","indexed":true,"internalType":"address"},{"name":"extendedManagerPermissions","type":"bool","indexed":false,"internalType":"bool"}],"anonymous":false},{"type":"event","name":"NodeOperatorManagerAddressChangeProposed","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"oldProposedAddress","type":"address","indexed":true,"internalType":"address"},{"name":"newProposedAddress","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"NodeOperatorManagerAddressChanged","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"oldAddress","type":"address","indexed":true,"internalType":"address"},{"name":"newAddress","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"NodeOperatorRewardAddressChangeProposed","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"oldProposedAddress","type":"address","indexed":true,"internalType":"address"},{"name":"newProposedAddress","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"NodeOperatorRewardAddressChanged","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"oldAddress","type":"address","indexed":true,"internalType":"address"},{"name":"newAddress","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"NonceChanged","inputs":[{"name":"nonce","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"Paused","inputs":[{"name":"duration","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ReferrerSet","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"referrer","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"Resumed","inputs":[],"anonymous":false},{"type":"event","name":"RoleAdminChanged","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"previousAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"newAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"}],"anonymous":false},{"type":"event","name":"RoleGranted","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"RoleRevoked","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"SigningKeyAdded","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"pubkey","type":"bytes","indexed":false,"internalType":"bytes"}],"anonymous":false},{"type":"event","name":"SigningKeyRemoved","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"pubkey","type":"bytes","indexed":false,"internalType":"bytes"}],"anonymous":false},{"type":"event","name":"StETHSharesRecovered","inputs":[{"name":"recipient","type":"address","indexed":true,"internalType":"address"},{"name":"shares","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"TargetValidatorsCountChanged","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"targetLimitMode","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"targetValidatorsCount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"TotalSigningKeysCountChanged","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"totalKeysCount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"VettedSigningKeysCountChanged","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"vettedKeysCount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"VettedSigningKeysCountDecreased","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"WithdrawalSubmitted","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"keyIndex","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"pubkey","type":"bytes","indexed":false,"internalType":"bytes"}],"anonymous":false},{"type":"error","name":"AccessControlBadConfirmation","inputs":[]},{"type":"error","name":"AccessControlUnauthorizedAccount","inputs":[{"name":"account","type":"address","internalType":"address"},{"name":"neededRole","type":"bytes32","internalType":"bytes32"}]},{"type":"error","name":"AlreadyProposed","inputs":[]},{"type":"error","name":"AlreadyWithdrawn","inputs":[]},{"type":"error","name":"CannotAddKeys","inputs":[]},{"type":"error","name":"EmptyKey","inputs":[]},{"type":"error","name":"ExitedKeysDecrease","inputs":[]},{"type":"error","name":"ExitedKeysHigherThanTotalDeposited","inputs":[]},{"type":"error","name":"FailedToSendEther","inputs":[]},{"type":"error","name":"InvalidAmount","inputs":[]},{"type":"error","name":"InvalidInitialization","inputs":[]},{"type":"error","name":"InvalidInput","inputs":[]},{"type":"error","name":"InvalidKeysCount","inputs":[]},{"type":"error","name":"InvalidLength","inputs":[]},{"type":"error","name":"InvalidReportData","inputs":[]},{"type":"error","name":"InvalidVetKeysPointer","inputs":[]},{"type":"error","name":"KeysLimitExceeded","inputs":[]},{"type":"error","name":"MethodCallIsNotAllowed","inputs":[]},{"type":"error","name":"NodeOperatorDoesNotExist","inputs":[]},{"type":"error","name":"NotAllowedToRecover","inputs":[]},{"type":"error","name":"NotEnoughKeys","inputs":[]},{"type":"error","name":"NotInitializing","inputs":[]},{"type":"error","name":"PauseUntilMustBeInFuture","inputs":[]},{"type":"error","name":"PausedExpected","inputs":[]},{"type":"error","name":"PriorityQueueAlreadyUsed","inputs":[]},{"type":"error","name":"QueueIsEmpty","inputs":[]},{"type":"error","name":"QueueLookupNoLimit","inputs":[]},{"type":"error","name":"ResumedExpected","inputs":[]},{"type":"error","name":"SameAddress","inputs":[]},{"type":"error","name":"SenderIsNotEligible","inputs":[]},{"type":"error","name":"SenderIsNotManagerAddress","inputs":[]},{"type":"error","name":"SenderIsNotProposedAddress","inputs":[]},{"type":"error","name":"SenderIsNotRewardAddress","inputs":[]},{"type":"error","name":"SigningKeysInvalidOffset","inputs":[]},{"type":"error","name":"ZeroAccountingAddress","inputs":[]},{"type":"error","name":"ZeroAdminAddress","inputs":[]},{"type":"error","name":"ZeroExitPenaltiesAddress","inputs":[]},{"type":"error","name":"ZeroLocatorAddress","inputs":[]},{"type":"error","name":"ZeroParametersRegistryAddress","inputs":[]},{"type":"error","name":"ZeroPauseDuration","inputs":[]},{"type":"error","name":"ZeroRewardAddress","inputs":[]},{"type":"error","name":"ZeroSenderAddress","inputs":[]}] diff --git a/interfaces/CSPermissionlessGate.json b/interfaces/CSPermissionlessGate.json new file mode 100644 index 000000000..bda444b61 --- /dev/null +++ b/interfaces/CSPermissionlessGate.json @@ -0,0 +1 @@ +[{"type":"constructor","inputs":[{"name":"module","type":"address","internalType":"address"}],"stateMutability":"nonpayable"},{"type":"function","name":"CURVE_ID","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"MODULE","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ICSModule"}],"stateMutability":"view"},{"type":"function","name":"addNodeOperatorETH","inputs":[{"name":"keysCount","type":"uint256","internalType":"uint256"},{"name":"publicKeys","type":"bytes","internalType":"bytes"},{"name":"signatures","type":"bytes","internalType":"bytes"},{"name":"managementProperties","type":"tuple","internalType":"struct NodeOperatorManagementProperties","components":[{"name":"managerAddress","type":"address","internalType":"address"},{"name":"rewardAddress","type":"address","internalType":"address"},{"name":"extendedManagerPermissions","type":"bool","internalType":"bool"}]},{"name":"referrer","type":"address","internalType":"address"}],"outputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"stateMutability":"payable"},{"type":"function","name":"addNodeOperatorStETH","inputs":[{"name":"keysCount","type":"uint256","internalType":"uint256"},{"name":"publicKeys","type":"bytes","internalType":"bytes"},{"name":"signatures","type":"bytes","internalType":"bytes"},{"name":"managementProperties","type":"tuple","internalType":"struct NodeOperatorManagementProperties","components":[{"name":"managerAddress","type":"address","internalType":"address"},{"name":"rewardAddress","type":"address","internalType":"address"},{"name":"extendedManagerPermissions","type":"bool","internalType":"bool"}]},{"name":"permit","type":"tuple","internalType":"struct ICSAccounting.PermitInput","components":[{"name":"value","type":"uint256","internalType":"uint256"},{"name":"deadline","type":"uint256","internalType":"uint256"},{"name":"v","type":"uint8","internalType":"uint8"},{"name":"r","type":"bytes32","internalType":"bytes32"},{"name":"s","type":"bytes32","internalType":"bytes32"}]},{"name":"referrer","type":"address","internalType":"address"}],"outputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"addNodeOperatorWstETH","inputs":[{"name":"keysCount","type":"uint256","internalType":"uint256"},{"name":"publicKeys","type":"bytes","internalType":"bytes"},{"name":"signatures","type":"bytes","internalType":"bytes"},{"name":"managementProperties","type":"tuple","internalType":"struct NodeOperatorManagementProperties","components":[{"name":"managerAddress","type":"address","internalType":"address"},{"name":"rewardAddress","type":"address","internalType":"address"},{"name":"extendedManagerPermissions","type":"bool","internalType":"bool"}]},{"name":"permit","type":"tuple","internalType":"struct ICSAccounting.PermitInput","components":[{"name":"value","type":"uint256","internalType":"uint256"},{"name":"deadline","type":"uint256","internalType":"uint256"},{"name":"v","type":"uint8","internalType":"uint8"},{"name":"r","type":"bytes32","internalType":"bytes32"},{"name":"s","type":"bytes32","internalType":"bytes32"}]},{"name":"referrer","type":"address","internalType":"address"}],"outputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"error","name":"ZeroModuleAddress","inputs":[]}] diff --git a/interfaces/CSStrikes.json b/interfaces/CSStrikes.json new file mode 100644 index 000000000..6ccc28dd3 --- /dev/null +++ b/interfaces/CSStrikes.json @@ -0,0 +1 @@ +[{"type":"constructor","inputs":[{"name":"module","type":"address","internalType":"address"},{"name":"oracle","type":"address","internalType":"address"},{"name":"exitPenalties","type":"address","internalType":"address"}],"stateMutability":"nonpayable"},{"type":"function","name":"ACCOUNTING","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ICSAccounting"}],"stateMutability":"view"},{"type":"function","name":"DEFAULT_ADMIN_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"EXIT_PENALTIES","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ICSExitPenalties"}],"stateMutability":"view"},{"type":"function","name":"MODULE","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ICSModule"}],"stateMutability":"view"},{"type":"function","name":"ORACLE","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"PARAMETERS_REGISTRY","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ICSParametersRegistry"}],"stateMutability":"view"},{"type":"function","name":"ejector","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ICSEjector"}],"stateMutability":"view"},{"type":"function","name":"getInitializedVersion","inputs":[],"outputs":[{"name":"","type":"uint64","internalType":"uint64"}],"stateMutability":"view"},{"type":"function","name":"getRoleAdmin","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"getRoleMember","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"index","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"getRoleMemberCount","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"grantRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"hasRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"hashLeaf","inputs":[{"name":"keyStrikes","type":"tuple","internalType":"struct ICSStrikes.ModuleKeyStrikes","components":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"keyIndex","type":"uint256","internalType":"uint256"},{"name":"data","type":"uint256[]","internalType":"uint256[]"}]},{"name":"pubkey","type":"bytes","internalType":"bytes"}],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"pure"},{"type":"function","name":"initialize","inputs":[{"name":"admin","type":"address","internalType":"address"},{"name":"_ejector","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"processBadPerformanceProof","inputs":[{"name":"keyStrikesList","type":"tuple[]","internalType":"struct ICSStrikes.ModuleKeyStrikes[]","components":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"keyIndex","type":"uint256","internalType":"uint256"},{"name":"data","type":"uint256[]","internalType":"uint256[]"}]},{"name":"proof","type":"bytes32[]","internalType":"bytes32[]"},{"name":"proofFlags","type":"bool[]","internalType":"bool[]"},{"name":"refundRecipient","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"processOracleReport","inputs":[{"name":"_treeRoot","type":"bytes32","internalType":"bytes32"},{"name":"_treeCid","type":"string","internalType":"string"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"renounceRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"callerConfirmation","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"revokeRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setEjector","inputs":[{"name":"_ejector","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"supportsInterface","inputs":[{"name":"interfaceId","type":"bytes4","internalType":"bytes4"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"treeCid","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"type":"function","name":"treeRoot","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"verifyProof","inputs":[{"name":"keyStrikesList","type":"tuple[]","internalType":"struct ICSStrikes.ModuleKeyStrikes[]","components":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"keyIndex","type":"uint256","internalType":"uint256"},{"name":"data","type":"uint256[]","internalType":"uint256[]"}]},{"name":"pubkeys","type":"bytes[]","internalType":"bytes[]"},{"name":"proof","type":"bytes32[]","internalType":"bytes32[]"},{"name":"proofFlags","type":"bool[]","internalType":"bool[]"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"event","name":"EjectorSet","inputs":[{"name":"ejector","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"Initialized","inputs":[{"name":"version","type":"uint64","indexed":false,"internalType":"uint64"}],"anonymous":false},{"type":"event","name":"RoleAdminChanged","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"previousAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"newAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"}],"anonymous":false},{"type":"event","name":"RoleGranted","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"RoleRevoked","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"StrikesDataUpdated","inputs":[{"name":"treeRoot","type":"bytes32","indexed":false,"internalType":"bytes32"},{"name":"treeCid","type":"string","indexed":false,"internalType":"string"}],"anonymous":false},{"type":"event","name":"StrikesDataWiped","inputs":[],"anonymous":false},{"type":"error","name":"AccessControlBadConfirmation","inputs":[]},{"type":"error","name":"AccessControlUnauthorizedAccount","inputs":[{"name":"account","type":"address","internalType":"address"},{"name":"neededRole","type":"bytes32","internalType":"bytes32"}]},{"type":"error","name":"InvalidInitialization","inputs":[]},{"type":"error","name":"InvalidProof","inputs":[]},{"type":"error","name":"InvalidReportData","inputs":[]},{"type":"error","name":"MerkleProofInvalidMultiproof","inputs":[]},{"type":"error","name":"NotEnoughStrikesToEject","inputs":[]},{"type":"error","name":"NotInitializing","inputs":[]},{"type":"error","name":"NotOracle","inputs":[]},{"type":"error","name":"ZeroAdminAddress","inputs":[]},{"type":"error","name":"ZeroBadPerformancePenaltyAmount","inputs":[]},{"type":"error","name":"ZeroEjectionFeeAmount","inputs":[]},{"type":"error","name":"ZeroEjectorAddress","inputs":[]},{"type":"error","name":"ZeroExitPenaltiesAddress","inputs":[]},{"type":"error","name":"ZeroModuleAddress","inputs":[]},{"type":"error","name":"ZeroOracleAddress","inputs":[]}] diff --git a/interfaces/csm/CSVerifier.json b/interfaces/CSVerifier.json similarity index 100% rename from interfaces/csm/CSVerifier.json rename to interfaces/CSVerifier.json diff --git a/interfaces/CSVerifierV2.json b/interfaces/CSVerifierV2.json new file mode 100644 index 000000000..267204b21 --- /dev/null +++ b/interfaces/CSVerifierV2.json @@ -0,0 +1 @@ +[{"type":"constructor","inputs":[{"name":"withdrawalAddress","type":"address","internalType":"address"},{"name":"module","type":"address","internalType":"address"},{"name":"slotsPerEpoch","type":"uint64","internalType":"uint64"},{"name":"gindices","type":"tuple","internalType":"struct ICSVerifier.GIndices","components":[{"name":"gIFirstWithdrawalPrev","type":"bytes32","internalType":"GIndex"},{"name":"gIFirstWithdrawalCurr","type":"bytes32","internalType":"GIndex"},{"name":"gIFirstValidatorPrev","type":"bytes32","internalType":"GIndex"},{"name":"gIFirstValidatorCurr","type":"bytes32","internalType":"GIndex"},{"name":"gIHistoricalSummariesPrev","type":"bytes32","internalType":"GIndex"},{"name":"gIHistoricalSummariesCurr","type":"bytes32","internalType":"GIndex"}]},{"name":"firstSupportedSlot","type":"uint64","internalType":"Slot"},{"name":"pivotSlot","type":"uint64","internalType":"Slot"},{"name":"admin","type":"address","internalType":"address"}],"stateMutability":"nonpayable"},{"type":"function","name":"BEACON_ROOTS","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"DEFAULT_ADMIN_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"FIRST_SUPPORTED_SLOT","inputs":[],"outputs":[{"name":"","type":"uint64","internalType":"Slot"}],"stateMutability":"view"},{"type":"function","name":"GI_FIRST_VALIDATOR_CURR","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"GIndex"}],"stateMutability":"view"},{"type":"function","name":"GI_FIRST_VALIDATOR_PREV","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"GIndex"}],"stateMutability":"view"},{"type":"function","name":"GI_FIRST_WITHDRAWAL_CURR","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"GIndex"}],"stateMutability":"view"},{"type":"function","name":"GI_FIRST_WITHDRAWAL_PREV","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"GIndex"}],"stateMutability":"view"},{"type":"function","name":"GI_HISTORICAL_SUMMARIES_CURR","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"GIndex"}],"stateMutability":"view"},{"type":"function","name":"GI_HISTORICAL_SUMMARIES_PREV","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"GIndex"}],"stateMutability":"view"},{"type":"function","name":"MODULE","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ICSModule"}],"stateMutability":"view"},{"type":"function","name":"PAUSE_INFINITELY","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"PAUSE_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"PIVOT_SLOT","inputs":[],"outputs":[{"name":"","type":"uint64","internalType":"Slot"}],"stateMutability":"view"},{"type":"function","name":"RESUME_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"SLOTS_PER_EPOCH","inputs":[],"outputs":[{"name":"","type":"uint64","internalType":"uint64"}],"stateMutability":"view"},{"type":"function","name":"WITHDRAWAL_ADDRESS","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"getResumeSinceTimestamp","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getRoleAdmin","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"getRoleMember","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"index","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"getRoleMemberCount","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"grantRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"hasRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"isPaused","inputs":[],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"pauseFor","inputs":[{"name":"duration","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"processHistoricalWithdrawalProof","inputs":[{"name":"beaconBlock","type":"tuple","internalType":"struct ICSVerifier.ProvableBeaconBlockHeader","components":[{"name":"header","type":"tuple","internalType":"struct BeaconBlockHeader","components":[{"name":"slot","type":"uint64","internalType":"Slot"},{"name":"proposerIndex","type":"uint64","internalType":"uint64"},{"name":"parentRoot","type":"bytes32","internalType":"bytes32"},{"name":"stateRoot","type":"bytes32","internalType":"bytes32"},{"name":"bodyRoot","type":"bytes32","internalType":"bytes32"}]},{"name":"rootsTimestamp","type":"uint64","internalType":"uint64"}]},{"name":"oldBlock","type":"tuple","internalType":"struct ICSVerifier.HistoricalHeaderWitness","components":[{"name":"header","type":"tuple","internalType":"struct BeaconBlockHeader","components":[{"name":"slot","type":"uint64","internalType":"Slot"},{"name":"proposerIndex","type":"uint64","internalType":"uint64"},{"name":"parentRoot","type":"bytes32","internalType":"bytes32"},{"name":"stateRoot","type":"bytes32","internalType":"bytes32"},{"name":"bodyRoot","type":"bytes32","internalType":"bytes32"}]},{"name":"rootGIndex","type":"bytes32","internalType":"GIndex"},{"name":"proof","type":"bytes32[]","internalType":"bytes32[]"}]},{"name":"witness","type":"tuple","internalType":"struct ICSVerifier.WithdrawalWitness","components":[{"name":"withdrawalOffset","type":"uint8","internalType":"uint8"},{"name":"withdrawalIndex","type":"uint64","internalType":"uint64"},{"name":"validatorIndex","type":"uint64","internalType":"uint64"},{"name":"amount","type":"uint64","internalType":"uint64"},{"name":"withdrawalCredentials","type":"bytes32","internalType":"bytes32"},{"name":"effectiveBalance","type":"uint64","internalType":"uint64"},{"name":"slashed","type":"bool","internalType":"bool"},{"name":"activationEligibilityEpoch","type":"uint64","internalType":"uint64"},{"name":"activationEpoch","type":"uint64","internalType":"uint64"},{"name":"exitEpoch","type":"uint64","internalType":"uint64"},{"name":"withdrawableEpoch","type":"uint64","internalType":"uint64"},{"name":"withdrawalProof","type":"bytes32[]","internalType":"bytes32[]"},{"name":"validatorProof","type":"bytes32[]","internalType":"bytes32[]"}]},{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"keyIndex","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"processWithdrawalProof","inputs":[{"name":"beaconBlock","type":"tuple","internalType":"struct ICSVerifier.ProvableBeaconBlockHeader","components":[{"name":"header","type":"tuple","internalType":"struct BeaconBlockHeader","components":[{"name":"slot","type":"uint64","internalType":"Slot"},{"name":"proposerIndex","type":"uint64","internalType":"uint64"},{"name":"parentRoot","type":"bytes32","internalType":"bytes32"},{"name":"stateRoot","type":"bytes32","internalType":"bytes32"},{"name":"bodyRoot","type":"bytes32","internalType":"bytes32"}]},{"name":"rootsTimestamp","type":"uint64","internalType":"uint64"}]},{"name":"witness","type":"tuple","internalType":"struct ICSVerifier.WithdrawalWitness","components":[{"name":"withdrawalOffset","type":"uint8","internalType":"uint8"},{"name":"withdrawalIndex","type":"uint64","internalType":"uint64"},{"name":"validatorIndex","type":"uint64","internalType":"uint64"},{"name":"amount","type":"uint64","internalType":"uint64"},{"name":"withdrawalCredentials","type":"bytes32","internalType":"bytes32"},{"name":"effectiveBalance","type":"uint64","internalType":"uint64"},{"name":"slashed","type":"bool","internalType":"bool"},{"name":"activationEligibilityEpoch","type":"uint64","internalType":"uint64"},{"name":"activationEpoch","type":"uint64","internalType":"uint64"},{"name":"exitEpoch","type":"uint64","internalType":"uint64"},{"name":"withdrawableEpoch","type":"uint64","internalType":"uint64"},{"name":"withdrawalProof","type":"bytes32[]","internalType":"bytes32[]"},{"name":"validatorProof","type":"bytes32[]","internalType":"bytes32[]"}]},{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"keyIndex","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"renounceRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"callerConfirmation","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"resume","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"revokeRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"supportsInterface","inputs":[{"name":"interfaceId","type":"bytes4","internalType":"bytes4"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"event","name":"Paused","inputs":[{"name":"duration","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"Resumed","inputs":[],"anonymous":false},{"type":"event","name":"RoleAdminChanged","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"previousAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"newAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"}],"anonymous":false},{"type":"event","name":"RoleGranted","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"RoleRevoked","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"error","name":"AccessControlBadConfirmation","inputs":[]},{"type":"error","name":"AccessControlUnauthorizedAccount","inputs":[{"name":"account","type":"address","internalType":"address"},{"name":"neededRole","type":"bytes32","internalType":"bytes32"}]},{"type":"error","name":"IndexOutOfRange","inputs":[]},{"type":"error","name":"InvalidBlockHeader","inputs":[]},{"type":"error","name":"InvalidChainConfig","inputs":[]},{"type":"error","name":"InvalidGIndex","inputs":[]},{"type":"error","name":"InvalidPivotSlot","inputs":[]},{"type":"error","name":"InvalidWithdrawalAddress","inputs":[]},{"type":"error","name":"PartialWithdrawal","inputs":[]},{"type":"error","name":"PauseUntilMustBeInFuture","inputs":[]},{"type":"error","name":"PausedExpected","inputs":[]},{"type":"error","name":"ResumedExpected","inputs":[]},{"type":"error","name":"RootNotFound","inputs":[]},{"type":"error","name":"UnsupportedSlot","inputs":[{"name":"slot","type":"uint64","internalType":"Slot"}]},{"type":"error","name":"ValidatorNotWithdrawn","inputs":[]},{"type":"error","name":"ZeroAdminAddress","inputs":[]},{"type":"error","name":"ZeroModuleAddress","inputs":[]},{"type":"error","name":"ZeroPauseDuration","inputs":[]},{"type":"error","name":"ZeroWithdrawalAddress","inputs":[]}] diff --git a/interfaces/CSVettedGate.json b/interfaces/CSVettedGate.json new file mode 100644 index 000000000..5c966b2ae --- /dev/null +++ b/interfaces/CSVettedGate.json @@ -0,0 +1 @@ +[{"type":"constructor","inputs":[{"name":"module","type":"address","internalType":"address"}],"stateMutability":"nonpayable"},{"type":"function","name":"ACCOUNTING","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ICSAccounting"}],"stateMutability":"view"},{"type":"function","name":"DEFAULT_ADMIN_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"END_REFERRAL_SEASON_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"MODULE","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ICSModule"}],"stateMutability":"view"},{"type":"function","name":"PAUSE_INFINITELY","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"PAUSE_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"RESUME_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"SET_TREE_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"START_REFERRAL_SEASON_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"addNodeOperatorETH","inputs":[{"name":"keysCount","type":"uint256","internalType":"uint256"},{"name":"publicKeys","type":"bytes","internalType":"bytes"},{"name":"signatures","type":"bytes","internalType":"bytes"},{"name":"managementProperties","type":"tuple","internalType":"struct NodeOperatorManagementProperties","components":[{"name":"managerAddress","type":"address","internalType":"address"},{"name":"rewardAddress","type":"address","internalType":"address"},{"name":"extendedManagerPermissions","type":"bool","internalType":"bool"}]},{"name":"proof","type":"bytes32[]","internalType":"bytes32[]"},{"name":"referrer","type":"address","internalType":"address"}],"outputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"stateMutability":"payable"},{"type":"function","name":"addNodeOperatorStETH","inputs":[{"name":"keysCount","type":"uint256","internalType":"uint256"},{"name":"publicKeys","type":"bytes","internalType":"bytes"},{"name":"signatures","type":"bytes","internalType":"bytes"},{"name":"managementProperties","type":"tuple","internalType":"struct NodeOperatorManagementProperties","components":[{"name":"managerAddress","type":"address","internalType":"address"},{"name":"rewardAddress","type":"address","internalType":"address"},{"name":"extendedManagerPermissions","type":"bool","internalType":"bool"}]},{"name":"permit","type":"tuple","internalType":"struct ICSAccounting.PermitInput","components":[{"name":"value","type":"uint256","internalType":"uint256"},{"name":"deadline","type":"uint256","internalType":"uint256"},{"name":"v","type":"uint8","internalType":"uint8"},{"name":"r","type":"bytes32","internalType":"bytes32"},{"name":"s","type":"bytes32","internalType":"bytes32"}]},{"name":"proof","type":"bytes32[]","internalType":"bytes32[]"},{"name":"referrer","type":"address","internalType":"address"}],"outputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"addNodeOperatorWstETH","inputs":[{"name":"keysCount","type":"uint256","internalType":"uint256"},{"name":"publicKeys","type":"bytes","internalType":"bytes"},{"name":"signatures","type":"bytes","internalType":"bytes"},{"name":"managementProperties","type":"tuple","internalType":"struct NodeOperatorManagementProperties","components":[{"name":"managerAddress","type":"address","internalType":"address"},{"name":"rewardAddress","type":"address","internalType":"address"},{"name":"extendedManagerPermissions","type":"bool","internalType":"bool"}]},{"name":"permit","type":"tuple","internalType":"struct ICSAccounting.PermitInput","components":[{"name":"value","type":"uint256","internalType":"uint256"},{"name":"deadline","type":"uint256","internalType":"uint256"},{"name":"v","type":"uint8","internalType":"uint8"},{"name":"r","type":"bytes32","internalType":"bytes32"},{"name":"s","type":"bytes32","internalType":"bytes32"}]},{"name":"proof","type":"bytes32[]","internalType":"bytes32[]"},{"name":"referrer","type":"address","internalType":"address"}],"outputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"claimBondCurve","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"proof","type":"bytes32[]","internalType":"bytes32[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"claimReferrerBondCurve","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"proof","type":"bytes32[]","internalType":"bytes32[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"curveId","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"endCurrentReferralProgramSeason","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"getInitializedVersion","inputs":[],"outputs":[{"name":"","type":"uint64","internalType":"uint64"}],"stateMutability":"view"},{"type":"function","name":"getReferralsCount","inputs":[{"name":"referrer","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getResumeSinceTimestamp","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getRoleAdmin","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"getRoleMember","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"index","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"getRoleMemberCount","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"grantRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"hasRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"hashLeaf","inputs":[{"name":"member","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"pure"},{"type":"function","name":"initialize","inputs":[{"name":"_curveId","type":"uint256","internalType":"uint256"},{"name":"_treeRoot","type":"bytes32","internalType":"bytes32"},{"name":"_treeCid","type":"string","internalType":"string"},{"name":"admin","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"isConsumed","inputs":[{"name":"member","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"isPaused","inputs":[],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"isReferralProgramSeasonActive","inputs":[],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"isReferrerConsumed","inputs":[{"name":"referrer","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"pauseFor","inputs":[{"name":"duration","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"referralCounts","inputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"referralCurveId","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"referralProgramSeasonNumber","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"referralsThreshold","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"renounceRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"callerConfirmation","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"resume","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"revokeRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setTreeParams","inputs":[{"name":"_treeRoot","type":"bytes32","internalType":"bytes32"},{"name":"_treeCid","type":"string","internalType":"string"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"startNewReferralProgramSeason","inputs":[{"name":"_referralCurveId","type":"uint256","internalType":"uint256"},{"name":"_referralsThreshold","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"supportsInterface","inputs":[{"name":"interfaceId","type":"bytes4","internalType":"bytes4"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"treeCid","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"type":"function","name":"treeRoot","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"verifyProof","inputs":[{"name":"member","type":"address","internalType":"address"},{"name":"proof","type":"bytes32[]","internalType":"bytes32[]"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"event","name":"Consumed","inputs":[{"name":"member","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"Initialized","inputs":[{"name":"version","type":"uint64","indexed":false,"internalType":"uint64"}],"anonymous":false},{"type":"event","name":"Paused","inputs":[{"name":"duration","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ReferralProgramSeasonEnded","inputs":[{"name":"season","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ReferralProgramSeasonStarted","inputs":[{"name":"season","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"referralCurveId","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"referralsThreshold","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ReferrerConsumed","inputs":[{"name":"referrer","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"Resumed","inputs":[],"anonymous":false},{"type":"event","name":"RoleAdminChanged","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"previousAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"newAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"}],"anonymous":false},{"type":"event","name":"RoleGranted","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"RoleRevoked","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"TreeSet","inputs":[{"name":"treeRoot","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"treeCid","type":"string","indexed":false,"internalType":"string"}],"anonymous":false},{"type":"error","name":"AccessControlBadConfirmation","inputs":[]},{"type":"error","name":"AccessControlUnauthorizedAccount","inputs":[{"name":"account","type":"address","internalType":"address"},{"name":"neededRole","type":"bytes32","internalType":"bytes32"}]},{"type":"error","name":"AlreadyConsumed","inputs":[]},{"type":"error","name":"InvalidCurveId","inputs":[]},{"type":"error","name":"InvalidInitialization","inputs":[]},{"type":"error","name":"InvalidProof","inputs":[]},{"type":"error","name":"InvalidReferralsThreshold","inputs":[]},{"type":"error","name":"InvalidTreeCid","inputs":[]},{"type":"error","name":"InvalidTreeRoot","inputs":[]},{"type":"error","name":"NotAllowedToClaim","inputs":[]},{"type":"error","name":"NotEnoughReferrals","inputs":[]},{"type":"error","name":"NotInitializing","inputs":[]},{"type":"error","name":"PauseUntilMustBeInFuture","inputs":[]},{"type":"error","name":"PausedExpected","inputs":[]},{"type":"error","name":"ReferralProgramIsActive","inputs":[]},{"type":"error","name":"ReferralProgramIsNotActive","inputs":[]},{"type":"error","name":"ResumedExpected","inputs":[]},{"type":"error","name":"ZeroAdminAddress","inputs":[]},{"type":"error","name":"ZeroModuleAddress","inputs":[]},{"type":"error","name":"ZeroPauseDuration","inputs":[]}] diff --git a/interfaces/NodeOperatorsRegistry.json b/interfaces/NodeOperatorsRegistry.json index 4e15f855d..835d9c9fa 100644 --- a/interfaces/NodeOperatorsRegistry.json +++ b/interfaces/NodeOperatorsRegistry.json @@ -79,15 +79,15 @@ "constant": true, "inputs": [ { - "name": "_script", - "type": "bytes" + "name": "", + "type": "uint256" } ], - "name": "getEVMScriptExecutor", + "name": "exitDeadlineThreshold", "outputs": [ { "name": "", - "type": "address" + "type": "uint256" } ], "payable": false, @@ -95,22 +95,22 @@ "type": "function" }, { - "constant": false, + "constant": true, "inputs": [ { - "name": "_nodeOperatorId", - "type": "uint256" + "name": "_script", + "type": "bytes" } ], - "name": "clearNodeOperatorPenalty", + "name": "getEVMScriptExecutor", "outputs": [ { "name": "", - "type": "bool" + "type": "address" } ], "payable": false, - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { @@ -150,6 +150,32 @@ "stateMutability": "view", "type": "function" }, + { + "constant": false, + "inputs": [ + { + "name": "_nodeOperatorId", + "type": "uint256" + }, + { + "name": "_proofSlotTimestamp", + "type": "uint256" + }, + { + "name": "_publicKey", + "type": "bytes" + }, + { + "name": "_eligibleToExitInSec", + "type": "uint256" + } + ], + "name": "reportValidatorExitDelay", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, { "constant": true, "inputs": [ @@ -301,7 +327,7 @@ "type": "bytes32" }, { - "name": "_stuckPenaltyDelay", + "name": "_exitDeadlineThresholdInSeconds", "type": "uint256" } ], @@ -315,20 +341,23 @@ "constant": false, "inputs": [ { - "name": "_delay", + "name": "_nodeOperatorId", + "type": "uint256" + }, + { + "name": "_publicKey", + "type": "bytes" + }, + { + "name": "_withdrawalRequestPaidFee", + "type": "uint256" + }, + { + "name": "_exitType", "type": "uint256" } ], - "name": "setStuckPenaltyDelay", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "finalizeUpgrade_v3", + "name": "onValidatorExitTriggered", "outputs": [], "payable": false, "stateMutability": "nonpayable", @@ -345,7 +374,7 @@ } ], "payable": false, - "stateMutability": "view", + "stateMutability": "pure", "type": "function" }, { @@ -406,7 +435,7 @@ "constant": true, "inputs": [ { - "name": "_nodeOperatorId", + "name": "", "type": "uint256" } ], @@ -418,7 +447,7 @@ } ], "payable": false, - "stateMutability": "view", + "stateMutability": "pure", "type": "function" }, { @@ -508,6 +537,37 @@ "stateMutability": "view", "type": "function" }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "_proofSlotTimestamp", + "type": "uint256" + }, + { + "name": "_publicKey", + "type": "bytes" + }, + { + "name": "_eligibleToExitInSec", + "type": "uint256" + } + ], + "name": "isValidatorExitDelayPenaltyApplicable", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, { "constant": true, "inputs": [], @@ -620,6 +680,20 @@ "stateMutability": "view", "type": "function" }, + { + "constant": false, + "inputs": [ + { + "name": "_exitDeadlineThresholdInSeconds", + "type": "uint256" + } + ], + "name": "finalizeUpgrade_v4", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, { "constant": false, "inputs": [], @@ -652,6 +726,24 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "constant": false, + "inputs": [ + { + "name": "_nodeOperatorId", + "type": "uint256" + }, + { + "name": "_exitedValidatorsCount", + "type": "uint256" + } + ], + "name": "unsafeUpdateValidatorsCount", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, { "constant": false, "inputs": [ @@ -717,28 +809,6 @@ "stateMutability": "view", "type": "function" }, - { - "constant": false, - "inputs": [ - { - "name": "_locator", - "type": "address" - }, - { - "name": "_type", - "type": "bytes32" - }, - { - "name": "_stuckPenaltyDelay", - "type": "uint256" - } - ], - "name": "finalizeUpgrade_v2", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, { "constant": true, "inputs": [], @@ -779,24 +849,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "constant": false, - "inputs": [ - { - "name": "_nodeOperatorIds", - "type": "bytes" - }, - { - "name": "_stuckValidatorsCounts", - "type": "bytes" - } - ], - "name": "updateStuckValidatorsCount", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, { "constant": false, "inputs": [ @@ -838,24 +890,6 @@ "stateMutability": "view", "type": "function" }, - { - "constant": false, - "inputs": [ - { - "name": "_nodeOperatorId", - "type": "uint256" - }, - { - "name": "_refundedValidatorsCount", - "type": "uint256" - } - ], - "name": "updateRefundedValidatorsCount", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, { "constant": true, "inputs": [], @@ -1034,6 +1068,43 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "constant": true, + "inputs": [ + { + "name": "_publicKey", + "type": "bytes" + } + ], + "name": "isValidatorExitingKeyReported", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_threshold", + "type": "uint256" + }, + { + "name": "_lateReportingWindow", + "type": "uint256" + } + ], + "name": "setExitDeadlineThreshold", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, { "constant": false, "inputs": [ @@ -1061,6 +1132,20 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "constant": true, + "inputs": [], + "name": "exitPenaltyCutoffTimestamp", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, { "constant": true, "inputs": [], @@ -1219,28 +1304,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "constant": false, - "inputs": [ - { - "name": "_nodeOperatorId", - "type": "uint256" - }, - { - "name": "_exitedValidatorsCount", - "type": "uint256" - }, - { - "name": "_stuckValidatorsCount", - "type": "uint256" - } - ], - "name": "unsafeUpdateValidatorsCount", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, { "constant": true, "inputs": [], @@ -1259,7 +1322,7 @@ "constant": true, "inputs": [ { - "name": "_nodeOperatorId", + "name": "", "type": "uint256" } ], @@ -1271,7 +1334,7 @@ } ], "payable": false, - "stateMutability": "view", + "stateMutability": "pure", "type": "function" }, { @@ -1517,13 +1580,23 @@ { "anonymous": false, "inputs": [ + { + "indexed": true, + "name": "nodeOperatorId", + "type": "uint256" + }, + { + "indexed": false, + "name": "targetValidatorsCount", + "type": "uint256" + }, { "indexed": false, - "name": "stuckPenaltyDelay", + "name": "targetLimitMode", "type": "uint256" } ], - "name": "StuckPenaltyDelayChanged", + "name": "TargetValidatorsCountChanged", "type": "event" }, { @@ -1536,21 +1609,21 @@ }, { "indexed": false, - "name": "stuckValidatorsCount", - "type": "uint256" + "name": "publicKey", + "type": "bytes" }, { "indexed": false, - "name": "refundedValidatorsCount", + "name": "eligibleToExitInSec", "type": "uint256" }, { "indexed": false, - "name": "stuckPenaltyEndTimestamp", + "name": "proofSlotTimestamp", "type": "uint256" } ], - "name": "StuckPenaltyStateChanged", + "name": "ValidatorExitStatusUpdated", "type": "event" }, { @@ -1563,33 +1636,38 @@ }, { "indexed": false, - "name": "targetValidatorsCount", + "name": "publicKey", + "type": "bytes" + }, + { + "indexed": false, + "name": "withdrawalRequestPaidFee", "type": "uint256" }, { "indexed": false, - "name": "targetLimitMode", + "name": "exitType", "type": "uint256" } ], - "name": "TargetValidatorsCountChanged", + "name": "ValidatorExitTriggered", "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": true, - "name": "recipientAddress", - "type": "address" + "indexed": false, + "name": "threshold", + "type": "uint256" }, { "indexed": false, - "name": "sharesPenalizedAmount", + "name": "reportingWindow", "type": "uint256" } ], - "name": "NodeOperatorPenalized", + "name": "ExitDeadlineThresholdChanged", "type": "event" }, { diff --git a/interfaces/Sandbox.json b/interfaces/Sandbox.json index 632231338..e42569137 100644 --- a/interfaces/Sandbox.json +++ b/interfaces/Sandbox.json @@ -1 +1,1734 @@ -[{"constant":true,"inputs":[],"name":"hasInitialized","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_keysCount","type":"uint256"},{"name":"_publicKeys","type":"bytes"},{"name":"_signatures","type":"bytes"}],"name":"addSigningKeys","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getType","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_script","type":"bytes"}],"name":"getEVMScriptExecutor","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"}],"name":"clearNodeOperatorPenalty","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getRecoveryVault","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_offset","type":"uint256"},{"name":"_limit","type":"uint256"}],"name":"getNodeOperatorIds","outputs":[{"name":"nodeOperatorIds","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_offset","type":"uint256"},{"name":"_limit","type":"uint256"}],"name":"getSigningKeys","outputs":[{"name":"pubkeys","type":"bytes"},{"name":"signatures","type":"bytes"},{"name":"used","type":"bool[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_fromIndex","type":"uint256"},{"name":"_keysCount","type":"uint256"}],"name":"removeSigningKeysOperatorBH","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_nodeOperatorId","type":"uint256"}],"name":"getNodeOperatorIsActive","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_name","type":"string"}],"name":"setNodeOperatorName","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_totalRewardShares","type":"uint256"}],"name":"getRewardsDistribution","outputs":[{"name":"recipients","type":"address[]"},{"name":"shares","type":"uint256[]"},{"name":"penalized","type":"bool[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_indexFrom","type":"uint256"},{"name":"_indexTo","type":"uint256"}],"name":"invalidateReadyToDepositKeysRange","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_locator","type":"address"},{"name":"_type","type":"bytes32"},{"name":"_stuckPenaltyDelay","type":"uint256"}],"name":"initialize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_delay","type":"uint256"}],"name":"setStuckPenaltyDelay","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getStuckPenaltyDelay","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_index","type":"uint256"}],"name":"removeSigningKey","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_fromIndex","type":"uint256"},{"name":"_keysCount","type":"uint256"}],"name":"removeSigningKeys","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_nodeOperatorId","type":"uint256"}],"name":"isOperatorPenalized","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"}],"name":"deactivateNodeOperator","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"token","type":"address"}],"name":"allowRecoverability","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"STAKING_ROUTER_ROLE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_keysCount","type":"uint256"},{"name":"_publicKeys","type":"bytes"},{"name":"_signatures","type":"bytes"}],"name":"addSigningKeysOperatorBH","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"appId","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getActiveNodeOperatorsCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"string"},{"name":"_rewardAddress","type":"address"}],"name":"addNodeOperator","outputs":[{"name":"id","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getContractVersion","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getInitializationBlock","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_nodeOperatorId","type":"uint256"}],"name":"getUnusedSigningKeyCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"onRewardsMinted","outputs":[],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"MANAGE_NODE_OPERATOR_ROLE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"onWithdrawalCredentialsChanged","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"}],"name":"activateNodeOperator","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_rewardAddress","type":"address"}],"name":"setNodeOperatorRewardAddress","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_fullInfo","type":"bool"}],"name":"getNodeOperator","outputs":[{"name":"active","type":"bool"},{"name":"name","type":"string"},{"name":"rewardAddress","type":"address"},{"name":"totalVettedValidators","type":"uint64"},{"name":"totalExitedValidators","type":"uint64"},{"name":"totalAddedValidators","type":"uint64"},{"name":"totalDepositedValidators","type":"uint64"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_locator","type":"address"},{"name":"_type","type":"bytes32"},{"name":"_stuckPenaltyDelay","type":"uint256"}],"name":"finalizeUpgrade_v2","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getStakingModuleSummary","outputs":[{"name":"totalExitedValidators","type":"uint256"},{"name":"totalDepositedValidators","type":"uint256"},{"name":"depositableValidatorsCount","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorIds","type":"bytes"},{"name":"_exitedValidatorsCounts","type":"bytes"}],"name":"updateExitedValidatorsCount","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorIds","type":"bytes"},{"name":"_stuckValidatorsCounts","type":"bytes"}],"name":"updateStuckValidatorsCount","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_token","type":"address"}],"name":"transferToVault","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_sender","type":"address"},{"name":"_role","type":"bytes32"},{"name":"_params","type":"uint256[]"}],"name":"canPerform","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_refundedValidatorsCount","type":"uint256"}],"name":"updateRefundedValidatorsCount","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getEVMScriptRegistry","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getNodeOperatorsCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_isTargetLimitActive","type":"bool"},{"name":"_targetLimit","type":"uint256"}],"name":"updateTargetValidatorsLimits","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_vettedSigningKeysCount","type":"uint64"}],"name":"setNodeOperatorStakingLimit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_nodeOperatorId","type":"uint256"}],"name":"getNodeOperatorSummary","outputs":[{"name":"isTargetLimitActive","type":"bool"},{"name":"targetValidatorsCount","type":"uint256"},{"name":"stuckValidatorsCount","type":"uint256"},{"name":"refundedValidatorsCount","type":"uint256"},{"name":"stuckPenaltyEndTimestamp","type":"uint256"},{"name":"totalExitedValidators","type":"uint256"},{"name":"totalDepositedValidators","type":"uint256"},{"name":"depositableValidatorsCount","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_index","type":"uint256"}],"name":"getSigningKey","outputs":[{"name":"key","type":"bytes"},{"name":"depositSignature","type":"bytes"},{"name":"used","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"MAX_NODE_OPERATOR_NAME_LENGTH","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_depositsCount","type":"uint256"},{"name":"","type":"bytes"}],"name":"obtainDepositData","outputs":[{"name":"publicKeys","type":"bytes"},{"name":"signatures","type":"bytes"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getKeysOpIndex","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getNonce","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"kernel","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getLocator","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"SET_NODE_OPERATOR_LIMIT_ROLE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_nodeOperatorId","type":"uint256"}],"name":"getTotalSigningKeyCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isPetrified","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"MAX_STUCK_PENALTY_DELAY","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"onExitedAndStuckValidatorsCountsUpdated","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"MAX_NODE_OPERATORS_COUNT","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_index","type":"uint256"}],"name":"removeSigningKeyOperatorBH","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_exitedValidatorsCount","type":"uint256"},{"name":"_stuckValidatorsCount","type":"uint256"}],"name":"unsafeUpdateValidatorsCount","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"MANAGE_SIGNING_KEYS","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_nodeOperatorId","type":"uint256"}],"name":"isOperatorPenaltyCleared","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"name","type":"string"},{"indexed":false,"name":"rewardAddress","type":"address"},{"indexed":false,"name":"stakingLimit","type":"uint64"}],"name":"NodeOperatorAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"active","type":"bool"}],"name":"NodeOperatorActiveSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"name","type":"string"}],"name":"NodeOperatorNameSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"rewardAddress","type":"address"}],"name":"NodeOperatorRewardAddressSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"totalKeysTrimmed","type":"uint64"}],"name":"NodeOperatorTotalKeysTrimmed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"keysOpIndex","type":"uint256"}],"name":"KeysOpIndexSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"moduleType","type":"bytes32"}],"name":"StakingModuleTypeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"rewardAddress","type":"address"},{"indexed":false,"name":"sharesAmount","type":"uint256"}],"name":"RewardsDistributed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"locatorAddress","type":"address"}],"name":"LocatorContractSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"approvedValidatorsCount","type":"uint256"}],"name":"VettedSigningKeysCountChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"depositedValidatorsCount","type":"uint256"}],"name":"DepositedSigningKeysCountChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"exitedValidatorsCount","type":"uint256"}],"name":"ExitedSigningKeysCountChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"totalValidatorsCount","type":"uint256"}],"name":"TotalSigningKeysCountChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"nonce","type":"uint256"}],"name":"NonceChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"stuckPenaltyDelay","type":"uint256"}],"name":"StuckPenaltyDelayChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"stuckValidatorsCount","type":"uint256"},{"indexed":false,"name":"refundedValidatorsCount","type":"uint256"},{"indexed":false,"name":"stuckPenaltyEndTimestamp","type":"uint256"}],"name":"StuckPenaltyStateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"targetValidatorsCount","type":"uint256"}],"name":"TargetValidatorsCountChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"recipientAddress","type":"address"},{"indexed":false,"name":"sharesPenalizedAmount","type":"uint256"}],"name":"NodeOperatorPenalized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"version","type":"uint256"}],"name":"ContractVersionSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"executor","type":"address"},{"indexed":false,"name":"script","type":"bytes"},{"indexed":false,"name":"input","type":"bytes"},{"indexed":false,"name":"returnData","type":"bytes"}],"name":"ScriptResult","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"vault","type":"address"},{"indexed":true,"name":"token","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"RecoverToVault","type":"event"}] \ No newline at end of file +[ + { + "constant": true, + "inputs": [], + "name": "hasInitialized", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_nodeOperatorId", + "type": "uint256" + }, + { + "name": "_targetLimitMode", + "type": "uint256" + }, + { + "name": "_targetLimit", + "type": "uint256" + } + ], + "name": "updateTargetValidatorsLimits", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_nodeOperatorId", + "type": "uint256" + }, + { + "name": "_keysCount", + "type": "uint256" + }, + { + "name": "_publicKeys", + "type": "bytes" + }, + { + "name": "_signatures", + "type": "bytes" + } + ], + "name": "addSigningKeys", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getType", + "outputs": [ + { + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "uint256" + } + ], + "name": "exitDeadlineThreshold", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_script", + "type": "bytes" + } + ], + "name": "getEVMScriptExecutor", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getRecoveryVault", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_offset", + "type": "uint256" + }, + { + "name": "_limit", + "type": "uint256" + } + ], + "name": "getNodeOperatorIds", + "outputs": [ + { + "name": "nodeOperatorIds", + "type": "uint256[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_nodeOperatorId", + "type": "uint256" + }, + { + "name": "_proofSlotTimestamp", + "type": "uint256" + }, + { + "name": "_publicKey", + "type": "bytes" + }, + { + "name": "_eligibleToExitInSec", + "type": "uint256" + } + ], + "name": "reportValidatorExitDelay", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_nodeOperatorId", + "type": "uint256" + }, + { + "name": "_offset", + "type": "uint256" + }, + { + "name": "_limit", + "type": "uint256" + } + ], + "name": "getSigningKeys", + "outputs": [ + { + "name": "pubkeys", + "type": "bytes" + }, + { + "name": "signatures", + "type": "bytes" + }, + { + "name": "used", + "type": "bool[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_nodeOperatorId", + "type": "uint256" + }, + { + "name": "_fromIndex", + "type": "uint256" + }, + { + "name": "_keysCount", + "type": "uint256" + } + ], + "name": "removeSigningKeysOperatorBH", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_nodeOperatorId", + "type": "uint256" + } + ], + "name": "getNodeOperatorIsActive", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_nodeOperatorId", + "type": "uint256" + }, + { + "name": "_name", + "type": "string" + } + ], + "name": "setNodeOperatorName", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_totalRewardShares", + "type": "uint256" + } + ], + "name": "getRewardsDistribution", + "outputs": [ + { + "name": "recipients", + "type": "address[]" + }, + { + "name": "shares", + "type": "uint256[]" + }, + { + "name": "penalized", + "type": "bool[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_indexFrom", + "type": "uint256" + }, + { + "name": "_indexTo", + "type": "uint256" + } + ], + "name": "invalidateReadyToDepositKeysRange", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_locator", + "type": "address" + }, + { + "name": "_type", + "type": "bytes32" + }, + { + "name": "_exitDeadlineThresholdInSeconds", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_nodeOperatorId", + "type": "uint256" + }, + { + "name": "_publicKey", + "type": "bytes" + }, + { + "name": "_withdrawalRequestPaidFee", + "type": "uint256" + }, + { + "name": "_exitType", + "type": "uint256" + } + ], + "name": "onValidatorExitTriggered", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getStuckPenaltyDelay", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_nodeOperatorId", + "type": "uint256" + }, + { + "name": "_index", + "type": "uint256" + } + ], + "name": "removeSigningKey", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getRewardDistributionState", + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_nodeOperatorId", + "type": "uint256" + }, + { + "name": "_fromIndex", + "type": "uint256" + }, + { + "name": "_keysCount", + "type": "uint256" + } + ], + "name": "removeSigningKeys", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "uint256" + } + ], + "name": "isOperatorPenalized", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_nodeOperatorId", + "type": "uint256" + } + ], + "name": "deactivateNodeOperator", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "token", + "type": "address" + } + ], + "name": "allowRecoverability", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "STAKING_ROUTER_ROLE", + "outputs": [ + { + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_nodeOperatorId", + "type": "uint256" + }, + { + "name": "_keysCount", + "type": "uint256" + }, + { + "name": "_publicKeys", + "type": "bytes" + }, + { + "name": "_signatures", + "type": "bytes" + } + ], + "name": "addSigningKeysOperatorBH", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "appId", + "outputs": [ + { + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "_proofSlotTimestamp", + "type": "uint256" + }, + { + "name": "_publicKey", + "type": "bytes" + }, + { + "name": "_eligibleToExitInSec", + "type": "uint256" + } + ], + "name": "isValidatorExitDelayPenaltyApplicable", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getActiveNodeOperatorsCount", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_name", + "type": "string" + }, + { + "name": "_rewardAddress", + "type": "address" + } + ], + "name": "addNodeOperator", + "outputs": [ + { + "name": "id", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getContractVersion", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getInitializationBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_nodeOperatorId", + "type": "uint256" + } + ], + "name": "getUnusedSigningKeyCount", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "", + "type": "uint256" + } + ], + "name": "onRewardsMinted", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "MANAGE_NODE_OPERATOR_ROLE", + "outputs": [ + { + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_exitDeadlineThresholdInSeconds", + "type": "uint256" + } + ], + "name": "finalizeUpgrade_v4", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "distributeReward", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "onWithdrawalCredentialsChanged", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_nodeOperatorId", + "type": "uint256" + } + ], + "name": "activateNodeOperator", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_nodeOperatorId", + "type": "uint256" + }, + { + "name": "_exitedValidatorsCount", + "type": "uint256" + } + ], + "name": "unsafeUpdateValidatorsCount", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_nodeOperatorId", + "type": "uint256" + }, + { + "name": "_rewardAddress", + "type": "address" + } + ], + "name": "setNodeOperatorRewardAddress", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_nodeOperatorId", + "type": "uint256" + }, + { + "name": "_fullInfo", + "type": "bool" + } + ], + "name": "getNodeOperator", + "outputs": [ + { + "name": "active", + "type": "bool" + }, + { + "name": "name", + "type": "string" + }, + { + "name": "rewardAddress", + "type": "address" + }, + { + "name": "totalVettedValidators", + "type": "uint64" + }, + { + "name": "totalExitedValidators", + "type": "uint64" + }, + { + "name": "totalAddedValidators", + "type": "uint64" + }, + { + "name": "totalDepositedValidators", + "type": "uint64" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getStakingModuleSummary", + "outputs": [ + { + "name": "totalExitedValidators", + "type": "uint256" + }, + { + "name": "totalDepositedValidators", + "type": "uint256" + }, + { + "name": "depositableValidatorsCount", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_nodeOperatorIds", + "type": "bytes" + }, + { + "name": "_exitedValidatorsCounts", + "type": "bytes" + } + ], + "name": "updateExitedValidatorsCount", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_token", + "type": "address" + } + ], + "name": "transferToVault", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_sender", + "type": "address" + }, + { + "name": "_role", + "type": "bytes32" + }, + { + "name": "_params", + "type": "uint256[]" + } + ], + "name": "canPerform", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getEVMScriptRegistry", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getNodeOperatorsCount", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_nodeOperatorId", + "type": "uint256" + }, + { + "name": "_isTargetLimitActive", + "type": "bool" + }, + { + "name": "_targetLimit", + "type": "uint256" + } + ], + "name": "updateTargetValidatorsLimits", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_nodeOperatorId", + "type": "uint256" + }, + { + "name": "_vettedSigningKeysCount", + "type": "uint64" + } + ], + "name": "setNodeOperatorStakingLimit", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_nodeOperatorId", + "type": "uint256" + } + ], + "name": "getNodeOperatorSummary", + "outputs": [ + { + "name": "targetLimitMode", + "type": "uint256" + }, + { + "name": "targetValidatorsCount", + "type": "uint256" + }, + { + "name": "stuckValidatorsCount", + "type": "uint256" + }, + { + "name": "refundedValidatorsCount", + "type": "uint256" + }, + { + "name": "stuckPenaltyEndTimestamp", + "type": "uint256" + }, + { + "name": "totalExitedValidators", + "type": "uint256" + }, + { + "name": "totalDepositedValidators", + "type": "uint256" + }, + { + "name": "depositableValidatorsCount", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_nodeOperatorId", + "type": "uint256" + }, + { + "name": "_index", + "type": "uint256" + } + ], + "name": "getSigningKey", + "outputs": [ + { + "name": "key", + "type": "bytes" + }, + { + "name": "depositSignature", + "type": "bytes" + }, + { + "name": "used", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "MAX_NODE_OPERATOR_NAME_LENGTH", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_nodeOperatorIds", + "type": "bytes" + }, + { + "name": "_vettedSigningKeysCounts", + "type": "bytes" + } + ], + "name": "decreaseVettedSigningKeysCount", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_publicKey", + "type": "bytes" + } + ], + "name": "isValidatorExitingKeyReported", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_threshold", + "type": "uint256" + }, + { + "name": "_lateReportingWindow", + "type": "uint256" + } + ], + "name": "setExitDeadlineThreshold", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_depositsCount", + "type": "uint256" + }, + { + "name": "", + "type": "bytes" + } + ], + "name": "obtainDepositData", + "outputs": [ + { + "name": "publicKeys", + "type": "bytes" + }, + { + "name": "signatures", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exitPenaltyCutoffTimestamp", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getKeysOpIndex", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getNonce", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "kernel", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getLocator", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "SET_NODE_OPERATOR_LIMIT_ROLE", + "outputs": [ + { + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_nodeOperatorId", + "type": "uint256" + } + ], + "name": "getTotalSigningKeyCount", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isPetrified", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "MAX_STUCK_PENALTY_DELAY", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "onExitedAndStuckValidatorsCountsUpdated", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "MAX_NODE_OPERATORS_COUNT", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_nodeOperatorId", + "type": "uint256" + }, + { + "name": "_index", + "type": "uint256" + } + ], + "name": "removeSigningKeyOperatorBH", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "MANAGE_SIGNING_KEYS", + "outputs": [ + { + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "uint256" + } + ], + "name": "isOperatorPenaltyCleared", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "nodeOperatorId", + "type": "uint256" + }, + { + "indexed": false, + "name": "name", + "type": "string" + }, + { + "indexed": false, + "name": "rewardAddress", + "type": "address" + }, + { + "indexed": false, + "name": "stakingLimit", + "type": "uint64" + } + ], + "name": "NodeOperatorAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "nodeOperatorId", + "type": "uint256" + }, + { + "indexed": false, + "name": "active", + "type": "bool" + } + ], + "name": "NodeOperatorActiveSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "nodeOperatorId", + "type": "uint256" + }, + { + "indexed": false, + "name": "name", + "type": "string" + } + ], + "name": "NodeOperatorNameSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "nodeOperatorId", + "type": "uint256" + }, + { + "indexed": false, + "name": "rewardAddress", + "type": "address" + } + ], + "name": "NodeOperatorRewardAddressSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "nodeOperatorId", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalKeysTrimmed", + "type": "uint64" + } + ], + "name": "NodeOperatorTotalKeysTrimmed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "keysOpIndex", + "type": "uint256" + } + ], + "name": "KeysOpIndexSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "moduleType", + "type": "bytes32" + } + ], + "name": "StakingModuleTypeSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "rewardAddress", + "type": "address" + }, + { + "indexed": false, + "name": "sharesAmount", + "type": "uint256" + } + ], + "name": "RewardsDistributed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "state", + "type": "uint8" + } + ], + "name": "RewardDistributionStateChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "locatorAddress", + "type": "address" + } + ], + "name": "LocatorContractSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "nodeOperatorId", + "type": "uint256" + }, + { + "indexed": false, + "name": "approvedValidatorsCount", + "type": "uint256" + } + ], + "name": "VettedSigningKeysCountChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "nodeOperatorId", + "type": "uint256" + }, + { + "indexed": false, + "name": "depositedValidatorsCount", + "type": "uint256" + } + ], + "name": "DepositedSigningKeysCountChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "nodeOperatorId", + "type": "uint256" + }, + { + "indexed": false, + "name": "exitedValidatorsCount", + "type": "uint256" + } + ], + "name": "ExitedSigningKeysCountChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "nodeOperatorId", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalValidatorsCount", + "type": "uint256" + } + ], + "name": "TotalSigningKeysCountChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "nonce", + "type": "uint256" + } + ], + "name": "NonceChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "nodeOperatorId", + "type": "uint256" + }, + { + "indexed": false, + "name": "targetValidatorsCount", + "type": "uint256" + }, + { + "indexed": false, + "name": "targetLimitMode", + "type": "uint256" + } + ], + "name": "TargetValidatorsCountChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "nodeOperatorId", + "type": "uint256" + }, + { + "indexed": false, + "name": "publicKey", + "type": "bytes" + }, + { + "indexed": false, + "name": "eligibleToExitInSec", + "type": "uint256" + }, + { + "indexed": false, + "name": "proofSlotTimestamp", + "type": "uint256" + } + ], + "name": "ValidatorExitStatusUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "nodeOperatorId", + "type": "uint256" + }, + { + "indexed": false, + "name": "publicKey", + "type": "bytes" + }, + { + "indexed": false, + "name": "withdrawalRequestPaidFee", + "type": "uint256" + }, + { + "indexed": false, + "name": "exitType", + "type": "uint256" + } + ], + "name": "ValidatorExitTriggered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "threshold", + "type": "uint256" + }, + { + "indexed": false, + "name": "reportingWindow", + "type": "uint256" + } + ], + "name": "ExitDeadlineThresholdChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "version", + "type": "uint256" + } + ], + "name": "ContractVersionSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "executor", + "type": "address" + }, + { + "indexed": false, + "name": "script", + "type": "bytes" + }, + { + "indexed": false, + "name": "input", + "type": "bytes" + }, + { + "indexed": false, + "name": "returnData", + "type": "bytes" + } + ], + "name": "ScriptResult", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "vault", + "type": "address" + }, + { + "indexed": true, + "name": "token", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "RecoverToVault", + "type": "event" + } + ] diff --git a/interfaces/SimpleDVT.json b/interfaces/SimpleDVT.json index 4e15f855d..835d9c9fa 100644 --- a/interfaces/SimpleDVT.json +++ b/interfaces/SimpleDVT.json @@ -79,15 +79,15 @@ "constant": true, "inputs": [ { - "name": "_script", - "type": "bytes" + "name": "", + "type": "uint256" } ], - "name": "getEVMScriptExecutor", + "name": "exitDeadlineThreshold", "outputs": [ { "name": "", - "type": "address" + "type": "uint256" } ], "payable": false, @@ -95,22 +95,22 @@ "type": "function" }, { - "constant": false, + "constant": true, "inputs": [ { - "name": "_nodeOperatorId", - "type": "uint256" + "name": "_script", + "type": "bytes" } ], - "name": "clearNodeOperatorPenalty", + "name": "getEVMScriptExecutor", "outputs": [ { "name": "", - "type": "bool" + "type": "address" } ], "payable": false, - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { @@ -150,6 +150,32 @@ "stateMutability": "view", "type": "function" }, + { + "constant": false, + "inputs": [ + { + "name": "_nodeOperatorId", + "type": "uint256" + }, + { + "name": "_proofSlotTimestamp", + "type": "uint256" + }, + { + "name": "_publicKey", + "type": "bytes" + }, + { + "name": "_eligibleToExitInSec", + "type": "uint256" + } + ], + "name": "reportValidatorExitDelay", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, { "constant": true, "inputs": [ @@ -301,7 +327,7 @@ "type": "bytes32" }, { - "name": "_stuckPenaltyDelay", + "name": "_exitDeadlineThresholdInSeconds", "type": "uint256" } ], @@ -315,20 +341,23 @@ "constant": false, "inputs": [ { - "name": "_delay", + "name": "_nodeOperatorId", + "type": "uint256" + }, + { + "name": "_publicKey", + "type": "bytes" + }, + { + "name": "_withdrawalRequestPaidFee", + "type": "uint256" + }, + { + "name": "_exitType", "type": "uint256" } ], - "name": "setStuckPenaltyDelay", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "finalizeUpgrade_v3", + "name": "onValidatorExitTriggered", "outputs": [], "payable": false, "stateMutability": "nonpayable", @@ -345,7 +374,7 @@ } ], "payable": false, - "stateMutability": "view", + "stateMutability": "pure", "type": "function" }, { @@ -406,7 +435,7 @@ "constant": true, "inputs": [ { - "name": "_nodeOperatorId", + "name": "", "type": "uint256" } ], @@ -418,7 +447,7 @@ } ], "payable": false, - "stateMutability": "view", + "stateMutability": "pure", "type": "function" }, { @@ -508,6 +537,37 @@ "stateMutability": "view", "type": "function" }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "_proofSlotTimestamp", + "type": "uint256" + }, + { + "name": "_publicKey", + "type": "bytes" + }, + { + "name": "_eligibleToExitInSec", + "type": "uint256" + } + ], + "name": "isValidatorExitDelayPenaltyApplicable", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, { "constant": true, "inputs": [], @@ -620,6 +680,20 @@ "stateMutability": "view", "type": "function" }, + { + "constant": false, + "inputs": [ + { + "name": "_exitDeadlineThresholdInSeconds", + "type": "uint256" + } + ], + "name": "finalizeUpgrade_v4", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, { "constant": false, "inputs": [], @@ -652,6 +726,24 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "constant": false, + "inputs": [ + { + "name": "_nodeOperatorId", + "type": "uint256" + }, + { + "name": "_exitedValidatorsCount", + "type": "uint256" + } + ], + "name": "unsafeUpdateValidatorsCount", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, { "constant": false, "inputs": [ @@ -717,28 +809,6 @@ "stateMutability": "view", "type": "function" }, - { - "constant": false, - "inputs": [ - { - "name": "_locator", - "type": "address" - }, - { - "name": "_type", - "type": "bytes32" - }, - { - "name": "_stuckPenaltyDelay", - "type": "uint256" - } - ], - "name": "finalizeUpgrade_v2", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, { "constant": true, "inputs": [], @@ -779,24 +849,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "constant": false, - "inputs": [ - { - "name": "_nodeOperatorIds", - "type": "bytes" - }, - { - "name": "_stuckValidatorsCounts", - "type": "bytes" - } - ], - "name": "updateStuckValidatorsCount", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, { "constant": false, "inputs": [ @@ -838,24 +890,6 @@ "stateMutability": "view", "type": "function" }, - { - "constant": false, - "inputs": [ - { - "name": "_nodeOperatorId", - "type": "uint256" - }, - { - "name": "_refundedValidatorsCount", - "type": "uint256" - } - ], - "name": "updateRefundedValidatorsCount", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, { "constant": true, "inputs": [], @@ -1034,6 +1068,43 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "constant": true, + "inputs": [ + { + "name": "_publicKey", + "type": "bytes" + } + ], + "name": "isValidatorExitingKeyReported", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_threshold", + "type": "uint256" + }, + { + "name": "_lateReportingWindow", + "type": "uint256" + } + ], + "name": "setExitDeadlineThreshold", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, { "constant": false, "inputs": [ @@ -1061,6 +1132,20 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "constant": true, + "inputs": [], + "name": "exitPenaltyCutoffTimestamp", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, { "constant": true, "inputs": [], @@ -1219,28 +1304,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "constant": false, - "inputs": [ - { - "name": "_nodeOperatorId", - "type": "uint256" - }, - { - "name": "_exitedValidatorsCount", - "type": "uint256" - }, - { - "name": "_stuckValidatorsCount", - "type": "uint256" - } - ], - "name": "unsafeUpdateValidatorsCount", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, { "constant": true, "inputs": [], @@ -1259,7 +1322,7 @@ "constant": true, "inputs": [ { - "name": "_nodeOperatorId", + "name": "", "type": "uint256" } ], @@ -1271,7 +1334,7 @@ } ], "payable": false, - "stateMutability": "view", + "stateMutability": "pure", "type": "function" }, { @@ -1517,13 +1580,23 @@ { "anonymous": false, "inputs": [ + { + "indexed": true, + "name": "nodeOperatorId", + "type": "uint256" + }, + { + "indexed": false, + "name": "targetValidatorsCount", + "type": "uint256" + }, { "indexed": false, - "name": "stuckPenaltyDelay", + "name": "targetLimitMode", "type": "uint256" } ], - "name": "StuckPenaltyDelayChanged", + "name": "TargetValidatorsCountChanged", "type": "event" }, { @@ -1536,21 +1609,21 @@ }, { "indexed": false, - "name": "stuckValidatorsCount", - "type": "uint256" + "name": "publicKey", + "type": "bytes" }, { "indexed": false, - "name": "refundedValidatorsCount", + "name": "eligibleToExitInSec", "type": "uint256" }, { "indexed": false, - "name": "stuckPenaltyEndTimestamp", + "name": "proofSlotTimestamp", "type": "uint256" } ], - "name": "StuckPenaltyStateChanged", + "name": "ValidatorExitStatusUpdated", "type": "event" }, { @@ -1563,33 +1636,38 @@ }, { "indexed": false, - "name": "targetValidatorsCount", + "name": "publicKey", + "type": "bytes" + }, + { + "indexed": false, + "name": "withdrawalRequestPaidFee", "type": "uint256" }, { "indexed": false, - "name": "targetLimitMode", + "name": "exitType", "type": "uint256" } ], - "name": "TargetValidatorsCountChanged", + "name": "ValidatorExitTriggered", "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": true, - "name": "recipientAddress", - "type": "address" + "indexed": false, + "name": "threshold", + "type": "uint256" }, { "indexed": false, - "name": "sharesPenalizedAmount", + "name": "reportingWindow", "type": "uint256" } ], - "name": "NodeOperatorPenalized", + "name": "ExitDeadlineThresholdChanged", "type": "event" }, { diff --git a/interfaces/StakingRouter.json b/interfaces/StakingRouter.json index dfd058948..63233f2d2 100644 --- a/interfaces/StakingRouter.json +++ b/interfaces/StakingRouter.json @@ -77,6 +77,11 @@ "name": "InvalidFeeSum", "type": "error" }, + { + "inputs": [], + "name": "InvalidMaxDepositPerBlockValue", + "type": "error" + }, { "inputs": [], "name": "InvalidMinDepositBlockDistance", @@ -213,14 +218,25 @@ "internalType": "uint256", "name": "currentNodeOpExitedValidatorsCount", "type": "uint256" + } + ], + "name": "UnexpectedCurrentValidatorsCount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newModuleTotalExitedValidatorsCount", + "type": "uint256" }, { "internalType": "uint256", - "name": "currentNodeOpStuckValidatorsCount", + "name": "newModuleTotalExitedValidatorsCountInStakingRouter", "type": "uint256" } ], - "name": "UnexpectedCurrentValidatorsCount", + "name": "UnexpectedFinalExitedValidatorsCount", "type": "error" }, { @@ -717,6 +733,32 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "REPORT_VALIDATOR_EXITING_STATUS_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "STAKING_MODULE_MANAGE_ROLE", @@ -864,24 +906,8 @@ "type": "function" }, { - "inputs": [ - { - "internalType": "uint256[]", - "name": "_priorityExitShareThresholds", - "type": "uint256[]" - }, - { - "internalType": "uint256[]", - "name": "_maxDepositsPerBlock", - "type": "uint256[]" - }, - { - "internalType": "uint256[]", - "name": "_minDepositBlockDistances", - "type": "uint256[]" - } - ], - "name": "finalizeUpgrade_v2", + "inputs": [], + "name": "finalizeUpgrade_v3", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -2164,6 +2190,39 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_stakingModuleId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_nodeOperatorId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_publicKey", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "_withdrawalRequestPaidFee", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_exitType", + "type": "uint256" + } + ], + "name": "onValidatorExitTriggered", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [], "name": "onValidatorsCountsByNodeOperatorReportingFinished", @@ -2238,17 +2297,27 @@ "type": "uint256" }, { - "internalType": "bytes", - "name": "_nodeOperatorIds", - "type": "bytes" + "internalType": "uint256", + "name": "_nodeOperatorId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_proofSlotTimestamp", + "type": "uint256" }, { "internalType": "bytes", - "name": "_stuckValidatorsCounts", + "name": "_publicKey", "type": "bytes" + }, + { + "internalType": "uint256", + "name": "_eligibleToExitInSec", + "type": "uint256" } ], - "name": "reportStakingModuleStuckValidatorsCountByNodeOperator", + "name": "reportValidatorExitDelay", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -2350,11 +2419,6 @@ "name": "currentNodeOperatorExitedValidatorsCount", "type": "uint256" }, - { - "internalType": "uint256", - "name": "currentNodeOperatorStuckValidatorsCount", - "type": "uint256" - }, { "internalType": "uint256", "name": "newModuleExitedValidatorsCount", @@ -2364,11 +2428,6 @@ "internalType": "uint256", "name": "newNodeOperatorExitedValidatorsCount", "type": "uint256" - }, - { - "internalType": "uint256", - "name": "newNodeOperatorStuckValidatorsCount", - "type": "uint256" } ], "internalType": "struct StakingRouter.ValidatorsCountsCorrection", diff --git a/interfaces/TriggerableWithdrawalsGateway.json b/interfaces/TriggerableWithdrawalsGateway.json new file mode 100644 index 000000000..f46463094 --- /dev/null +++ b/interfaces/TriggerableWithdrawalsGateway.json @@ -0,0 +1,703 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "address", + "name": "lidoLocator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "maxExitRequestsLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "exitsPerFrame", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "frameDurationInSec", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "AdminCannotBeZero", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requestsCount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "remainingLimit", + "type": "uint256" + } + ], + "name": "ExitRequestsLimitExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "FeeRefundFailed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "feeRequired", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "passedValue", + "type": "uint256" + } + ], + "name": "InsufficientFee", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRequestsDataLength", + "type": "error" + }, + { + "inputs": [], + "name": "LimitExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "PauseUntilMustBeInFuture", + "type": "error" + }, + { + "inputs": [], + "name": "PausedExpected", + "type": "error" + }, + { + "inputs": [], + "name": "ResumedExpected", + "type": "error" + }, + { + "inputs": [], + "name": "TooLargeExitsPerFrame", + "type": "error" + }, + { + "inputs": [], + "name": "TooLargeFrameDuration", + "type": "error" + }, + { + "inputs": [], + "name": "TooLargeMaxExitRequestsLimit", + "type": "error" + }, + { + "inputs": [], + "name": "UnrecoverableModuleError", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + } + ], + "name": "ZeroArgument", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroFrameDuration", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroPauseDuration", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "maxExitRequestsLimit", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "exitsPerFrame", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "frameDurationInSec", + "type": "uint256" + } + ], + "name": "ExitRequestsLimitSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "duration", + "type": "uint256" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "Resumed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "stakingModuleId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "nodeOperatorId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "validatorPubkey", + "type": "bytes" + } + ], + "name": "StakingModuleExitNotificationFailed", + "type": "event" + }, + { + "inputs": [], + "name": "ADD_FULL_WITHDRAWAL_REQUEST_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PAUSE_INFINITELY", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PAUSE_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "RESUME_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TWR_LIMIT_POSITION", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TW_EXIT_LIMIT_MANAGER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "VERSION", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getExitRequestLimitFullInfo", + "outputs": [ + { + "internalType": "uint256", + "name": "maxExitRequestsLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "exitsPerFrame", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "frameDurationInSec", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "prevExitRequestsLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "currentExitRequestsLimit", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getResumeSinceTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getRoleMember", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleMemberCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_duration", + "type": "uint256" + } + ], + "name": "pauseFor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_pauseUntilInclusive", + "type": "uint256" + } + ], + "name": "pauseUntil", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resume", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "maxExitRequestsLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "exitsPerFrame", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "frameDurationInSec", + "type": "uint256" + } + ], + "name": "setExitRequestLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "stakingModuleId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "nodeOperatorId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "pubkey", + "type": "bytes" + } + ], + "internalType": "struct TriggerableWithdrawalsGateway.ValidatorData[]", + "name": "validatorsData", + "type": "tuple[]" + }, + { + "internalType": "address", + "name": "refundRecipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "exitType", + "type": "uint256" + } + ], + "name": "triggerFullWithdrawals", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/interfaces/ValidatorExitVerifier.json b/interfaces/ValidatorExitVerifier.json new file mode 100644 index 000000000..39e5cc8aa --- /dev/null +++ b/interfaces/ValidatorExitVerifier.json @@ -0,0 +1 @@ +[{"inputs":[{"internalType":"address","name":"lidoLocator","type":"address"},{"internalType":"GIndex","name":"gIFirstValidatorPrev","type":"bytes32"},{"internalType":"GIndex","name":"gIFirstValidatorCurr","type":"bytes32"},{"internalType":"GIndex","name":"gIHistoricalSummariesPrev","type":"bytes32"},{"internalType":"GIndex","name":"gIHistoricalSummariesCurr","type":"bytes32"},{"internalType":"uint64","name":"firstSupportedSlot","type":"uint64"},{"internalType":"uint64","name":"pivotSlot","type":"uint64"},{"internalType":"uint32","name":"slotsPerEpoch","type":"uint32"},{"internalType":"uint32","name":"secondsPerSlot","type":"uint32"},{"internalType":"uint64","name":"genesisTime","type":"uint64"},{"internalType":"uint32","name":"shardCommitteePeriodInSeconds","type":"uint32"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint64","name":"provableBeaconBlockTimestamp","type":"uint64"},{"internalType":"uint64","name":"eligibleExitRequestTimestamp","type":"uint64"}],"name":"ExitRequestNotEligibleOnProvableBeaconBlock","type":"error"},{"inputs":[],"name":"IndexOutOfRange","type":"error"},{"inputs":[],"name":"InvalidBlockHeader","type":"error"},{"inputs":[],"name":"InvalidGIndex","type":"error"},{"inputs":[],"name":"InvalidPivotSlot","type":"error"},{"inputs":[{"internalType":"uint256","name":"keyIndex","type":"uint256"},{"internalType":"uint256","name":"totalItemsCount","type":"uint256"}],"name":"KeyIndexOutOfRange","type":"error"},{"inputs":[{"internalType":"uint256","name":"keyIndex","type":"uint256"},{"internalType":"uint256","name":"lastUnpackedKeyIndex","type":"uint256"}],"name":"KeyWasNotUnpacked","type":"error"},{"inputs":[],"name":"RootNotFound","type":"error"},{"inputs":[{"internalType":"uint64","name":"slot","type":"uint64"}],"name":"UnsupportedSlot","type":"error"},{"inputs":[],"name":"ZeroLidoLocatorAddress","type":"error"},{"inputs":[],"name":"BEACON_ROOTS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FIRST_SUPPORTED_SLOT","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GENESIS_TIME","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GI_FIRST_VALIDATOR_CURR","outputs":[{"internalType":"GIndex","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GI_FIRST_VALIDATOR_PREV","outputs":[{"internalType":"GIndex","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GI_HISTORICAL_SUMMARIES_CURR","outputs":[{"internalType":"GIndex","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GI_HISTORICAL_SUMMARIES_PREV","outputs":[{"internalType":"GIndex","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LOCATOR","outputs":[{"internalType":"contract ILidoLocator","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PIVOT_SLOT","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SECONDS_PER_SLOT","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SHARD_COMMITTEE_PERIOD_IN_SECONDS","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SLOTS_PER_EPOCH","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"uint64","name":"slot","type":"uint64"},{"internalType":"uint64","name":"proposerIndex","type":"uint64"},{"internalType":"bytes32","name":"parentRoot","type":"bytes32"},{"internalType":"bytes32","name":"stateRoot","type":"bytes32"},{"internalType":"bytes32","name":"bodyRoot","type":"bytes32"}],"internalType":"struct BeaconBlockHeader","name":"header","type":"tuple"},{"internalType":"uint64","name":"rootsTimestamp","type":"uint64"}],"internalType":"struct ProvableBeaconBlockHeader","name":"beaconBlock","type":"tuple"},{"components":[{"internalType":"uint32","name":"exitRequestIndex","type":"uint32"},{"internalType":"bytes32","name":"withdrawalCredentials","type":"bytes32"},{"internalType":"uint64","name":"effectiveBalance","type":"uint64"},{"internalType":"bool","name":"slashed","type":"bool"},{"internalType":"uint64","name":"activationEligibilityEpoch","type":"uint64"},{"internalType":"uint64","name":"activationEpoch","type":"uint64"},{"internalType":"uint64","name":"withdrawableEpoch","type":"uint64"},{"internalType":"bytes32[]","name":"validatorProof","type":"bytes32[]"}],"internalType":"struct ValidatorWitness[]","name":"validatorWitnesses","type":"tuple[]"},{"components":[{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"dataFormat","type":"uint256"}],"internalType":"struct ExitRequestData","name":"exitRequests","type":"tuple"}],"name":"verifyActiveValidatorsAfterExitRequest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"uint64","name":"slot","type":"uint64"},{"internalType":"uint64","name":"proposerIndex","type":"uint64"},{"internalType":"bytes32","name":"parentRoot","type":"bytes32"},{"internalType":"bytes32","name":"stateRoot","type":"bytes32"},{"internalType":"bytes32","name":"bodyRoot","type":"bytes32"}],"internalType":"struct BeaconBlockHeader","name":"header","type":"tuple"},{"internalType":"uint64","name":"rootsTimestamp","type":"uint64"}],"internalType":"struct ProvableBeaconBlockHeader","name":"beaconBlock","type":"tuple"},{"components":[{"components":[{"internalType":"uint64","name":"slot","type":"uint64"},{"internalType":"uint64","name":"proposerIndex","type":"uint64"},{"internalType":"bytes32","name":"parentRoot","type":"bytes32"},{"internalType":"bytes32","name":"stateRoot","type":"bytes32"},{"internalType":"bytes32","name":"bodyRoot","type":"bytes32"}],"internalType":"struct BeaconBlockHeader","name":"header","type":"tuple"},{"internalType":"GIndex","name":"rootGIndex","type":"bytes32"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"internalType":"struct HistoricalHeaderWitness","name":"oldBlock","type":"tuple"},{"components":[{"internalType":"uint32","name":"exitRequestIndex","type":"uint32"},{"internalType":"bytes32","name":"withdrawalCredentials","type":"bytes32"},{"internalType":"uint64","name":"effectiveBalance","type":"uint64"},{"internalType":"bool","name":"slashed","type":"bool"},{"internalType":"uint64","name":"activationEligibilityEpoch","type":"uint64"},{"internalType":"uint64","name":"activationEpoch","type":"uint64"},{"internalType":"uint64","name":"withdrawableEpoch","type":"uint64"},{"internalType":"bytes32[]","name":"validatorProof","type":"bytes32[]"}],"internalType":"struct ValidatorWitness[]","name":"validatorWitnesses","type":"tuple[]"},{"components":[{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"dataFormat","type":"uint256"}],"internalType":"struct ExitRequestData","name":"exitRequests","type":"tuple"}],"name":"verifyHistoricalActiveValidatorsAfterExitRequest","outputs":[],"stateMutability":"nonpayable","type":"function"}] diff --git a/interfaces/ValidatorsExitBusOracle.json b/interfaces/ValidatorsExitBusOracle.json index 9c30845be..837da4724 100644 --- a/interfaces/ValidatorsExitBusOracle.json +++ b/interfaces/ValidatorsExitBusOracle.json @@ -1 +1,1641 @@ -[{"inputs":[{"internalType":"uint256","name":"secondsPerSlot","type":"uint256"},{"internalType":"uint256","name":"genesisTime","type":"uint256"},{"internalType":"address","name":"lidoLocator","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AddressCannotBeSame","type":"error"},{"inputs":[],"name":"AddressCannotBeZero","type":"error"},{"inputs":[],"name":"AdminCannotBeZero","type":"error"},{"inputs":[],"name":"ArgumentOutOfBounds","type":"error"},{"inputs":[],"name":"HashCannotBeZero","type":"error"},{"inputs":[{"internalType":"uint256","name":"initialRefSlot","type":"uint256"},{"internalType":"uint256","name":"processingRefSlot","type":"uint256"}],"name":"InitialRefSlotCannotBeLessThanProcessingOne","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[],"name":"InvalidRequestsData","type":"error"},{"inputs":[],"name":"InvalidRequestsDataLength","type":"error"},{"inputs":[],"name":"InvalidRequestsDataSortOrder","type":"error"},{"inputs":[],"name":"NoConsensusReportToProcess","type":"error"},{"inputs":[{"internalType":"uint256","name":"moduleId","type":"uint256"},{"internalType":"uint256","name":"nodeOpId","type":"uint256"},{"internalType":"uint256","name":"prevRequestedValidatorIndex","type":"uint256"},{"internalType":"uint256","name":"requestedValidatorIndex","type":"uint256"}],"name":"NodeOpValidatorIndexMustIncrease","type":"error"},{"inputs":[],"name":"NonZeroContractVersionOnInit","type":"error"},{"inputs":[],"name":"PauseUntilMustBeInFuture","type":"error"},{"inputs":[],"name":"PausedExpected","type":"error"},{"inputs":[{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"ProcessingDeadlineMissed","type":"error"},{"inputs":[],"name":"RefSlotAlreadyProcessing","type":"error"},{"inputs":[{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"prevRefSlot","type":"uint256"}],"name":"RefSlotCannotDecrease","type":"error"},{"inputs":[{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"processingRefSlot","type":"uint256"}],"name":"RefSlotMustBeGreaterThanProcessingOne","type":"error"},{"inputs":[],"name":"ResumedExpected","type":"error"},{"inputs":[],"name":"SecondsPerSlotCannotBeZero","type":"error"},{"inputs":[],"name":"SenderIsNotTheConsensusContract","type":"error"},{"inputs":[],"name":"SenderNotAllowed","type":"error"},{"inputs":[],"name":"UnexpectedChainConfig","type":"error"},{"inputs":[{"internalType":"uint256","name":"expectedVersion","type":"uint256"},{"internalType":"uint256","name":"receivedVersion","type":"uint256"}],"name":"UnexpectedConsensusVersion","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[{"internalType":"bytes32","name":"consensusHash","type":"bytes32"},{"internalType":"bytes32","name":"receivedHash","type":"bytes32"}],"name":"UnexpectedDataHash","type":"error"},{"inputs":[{"internalType":"uint256","name":"consensusRefSlot","type":"uint256"},{"internalType":"uint256","name":"dataRefSlot","type":"uint256"}],"name":"UnexpectedRefSlot","type":"error"},{"inputs":[],"name":"UnexpectedRequestsDataLength","type":"error"},{"inputs":[{"internalType":"uint256","name":"format","type":"uint256"}],"name":"UnsupportedRequestsDataFormat","type":"error"},{"inputs":[],"name":"VersionCannotBeSame","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"addr","type":"address"},{"indexed":true,"internalType":"address","name":"prevAddr","type":"address"}],"name":"ConsensusHashContractSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"version","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"prevVersion","type":"uint256"}],"name":"ConsensusVersionSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"version","type":"uint256"}],"name":"ContractVersionSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"duration","type":"uint256"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"hash","type":"bytes32"}],"name":"ProcessingStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"hash","type":"bytes32"}],"name":"ReportDiscarded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"hash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"processingDeadlineTime","type":"uint256"}],"name":"ReportSubmitted","type":"event"},{"anonymous":false,"inputs":[],"name":"Resumed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"nodeOperatorId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"validatorIndex","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"validatorPubkey","type":"bytes"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"ValidatorExitRequest","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"requestsProcessed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"requestsCount","type":"uint256"}],"name":"WarnDataIncompleteProcessing","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"}],"name":"WarnProcessingMissed","type":"event"},{"inputs":[],"name":"DATA_FORMAT_LIST","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GENESIS_TIME","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_CONSENSUS_CONTRACT_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_CONSENSUS_VERSION_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAUSE_INFINITELY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAUSE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RESUME_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SECONDS_PER_SLOT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SUBMIT_DATA_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"refSlot","type":"uint256"}],"name":"discardConsensusReport","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getConsensusContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConsensusReport","outputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"},{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"processingDeadlineTime","type":"uint256"},{"internalType":"bool","name":"processingStarted","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConsensusVersion","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getContractVersion","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLastProcessingRefSlot","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"moduleId","type":"uint256"},{"internalType":"uint256[]","name":"nodeOpIds","type":"uint256[]"}],"name":"getLastRequestedValidatorIndices","outputs":[{"internalType":"int256[]","name":"","type":"int256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getProcessingState","outputs":[{"components":[{"internalType":"uint256","name":"currentFrameRefSlot","type":"uint256"},{"internalType":"uint256","name":"processingDeadlineTime","type":"uint256"},{"internalType":"bytes32","name":"dataHash","type":"bytes32"},{"internalType":"bool","name":"dataSubmitted","type":"bool"},{"internalType":"uint256","name":"dataFormat","type":"uint256"},{"internalType":"uint256","name":"requestsCount","type":"uint256"},{"internalType":"uint256","name":"requestsSubmitted","type":"uint256"}],"internalType":"struct ValidatorsExitBusOracle.ProcessingState","name":"result","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getResumeSinceTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalRequestsProcessed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"address","name":"consensusContract","type":"address"},{"internalType":"uint256","name":"consensusVersion","type":"uint256"},{"internalType":"uint256","name":"lastProcessingRefSlot","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_duration","type":"uint256"}],"name":"pauseFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pauseUntilInclusive","type":"uint256"}],"name":"pauseUntil","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"resume","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"setConsensusContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"version","type":"uint256"}],"name":"setConsensusVersion","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"reportHash","type":"bytes32"},{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"submitConsensusReport","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"consensusVersion","type":"uint256"},{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"requestsCount","type":"uint256"},{"internalType":"uint256","name":"dataFormat","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct ValidatorsExitBusOracle.ReportData","name":"data","type":"tuple"},{"internalType":"uint256","name":"contractVersion","type":"uint256"}],"name":"submitReportData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}] \ No newline at end of file +[ + { + "inputs": [ + { + "internalType": "uint256", + "name": "secondsPerSlot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "genesisTime", + "type": "uint256" + }, + { + "internalType": "address", + "name": "lidoLocator", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "AddressCannotBeSame", + "type": "error" + }, + { + "inputs": [], + "name": "AddressCannotBeZero", + "type": "error" + }, + { + "inputs": [], + "name": "AdminCannotBeZero", + "type": "error" + }, + { + "inputs": [], + "name": "ArgumentOutOfBounds", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "exitDataIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requestsCount", + "type": "uint256" + } + ], + "name": "ExitDataIndexOutOfRange", + "type": "error" + }, + { + "inputs": [], + "name": "ExitHashAlreadySubmitted", + "type": "error" + }, + { + "inputs": [], + "name": "ExitHashNotSubmitted", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requestsCount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "remainingLimit", + "type": "uint256" + } + ], + "name": "ExitRequestsLimitExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "HashCannotBeZero", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "initialRefSlot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "processingRefSlot", + "type": "uint256" + } + ], + "name": "InitialRefSlotCannotBeLessThanProcessingOne", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidContractVersionIncrement", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidExitDataIndexSortOrder", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidModuleId", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRequestsDataLength", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRequestsDataSortOrder", + "type": "error" + }, + { + "inputs": [], + "name": "LimitExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "NoConsensusReportToProcess", + "type": "error" + }, + { + "inputs": [], + "name": "NonZeroContractVersionOnInit", + "type": "error" + }, + { + "inputs": [], + "name": "PauseUntilMustBeInFuture", + "type": "error" + }, + { + "inputs": [], + "name": "PausedExpected", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "ProcessingDeadlineMissed", + "type": "error" + }, + { + "inputs": [], + "name": "RefSlotAlreadyProcessing", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "refSlot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "prevRefSlot", + "type": "uint256" + } + ], + "name": "RefSlotCannotDecrease", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "refSlot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "processingRefSlot", + "type": "uint256" + } + ], + "name": "RefSlotMustBeGreaterThanProcessingOne", + "type": "error" + }, + { + "inputs": [], + "name": "RequestsAlreadyDelivered", + "type": "error" + }, + { + "inputs": [], + "name": "RequestsNotDelivered", + "type": "error" + }, + { + "inputs": [], + "name": "ResumedExpected", + "type": "error" + }, + { + "inputs": [], + "name": "SecondsPerSlotCannotBeZero", + "type": "error" + }, + { + "inputs": [], + "name": "SenderIsNotTheConsensusContract", + "type": "error" + }, + { + "inputs": [], + "name": "SenderNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "TooLargeExitsPerFrame", + "type": "error" + }, + { + "inputs": [], + "name": "TooLargeFrameDuration", + "type": "error" + }, + { + "inputs": [], + "name": "TooLargeMaxExitRequestsLimit", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requestsCount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxRequestsPerReport", + "type": "uint256" + } + ], + "name": "TooManyExitRequestsInReport", + "type": "error" + }, + { + "inputs": [], + "name": "UnexpectedChainConfig", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "expectedVersion", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "receivedVersion", + "type": "uint256" + } + ], + "name": "UnexpectedConsensusVersion", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "expected", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "received", + "type": "uint256" + } + ], + "name": "UnexpectedContractVersion", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "consensusHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "receivedHash", + "type": "bytes32" + } + ], + "name": "UnexpectedDataHash", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "consensusRefSlot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "dataRefSlot", + "type": "uint256" + } + ], + "name": "UnexpectedRefSlot", + "type": "error" + }, + { + "inputs": [], + "name": "UnexpectedRequestsDataLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "format", + "type": "uint256" + } + ], + "name": "UnsupportedRequestsDataFormat", + "type": "error" + }, + { + "inputs": [], + "name": "VersionCannotBeSame", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + } + ], + "name": "ZeroArgument", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroFrameDuration", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroPauseDuration", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "prevAddr", + "type": "address" + } + ], + "name": "ConsensusHashContractSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "version", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "prevVersion", + "type": "uint256" + } + ], + "name": "ConsensusVersionSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "version", + "type": "uint256" + } + ], + "name": "ContractVersionSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "exitRequestsHash", + "type": "bytes32" + } + ], + "name": "ExitDataProcessing", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "maxExitRequestsLimit", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "exitsPerFrame", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "frameDurationInSec", + "type": "uint256" + } + ], + "name": "ExitRequestsLimitSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "duration", + "type": "uint256" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "refSlot", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ], + "name": "ProcessingStarted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "refSlot", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ], + "name": "ReportDiscarded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "refSlot", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "processingDeadlineTime", + "type": "uint256" + } + ], + "name": "ReportSubmitted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "exitRequestsHash", + "type": "bytes32" + } + ], + "name": "RequestsHashSubmitted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "Resumed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "stakingModuleId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "nodeOperatorId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "validatorIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "validatorPubkey", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "name": "ValidatorExitRequest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "refSlot", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "requestsProcessed", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "requestsCount", + "type": "uint256" + } + ], + "name": "WarnDataIncompleteProcessing", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "refSlot", + "type": "uint256" + } + ], + "name": "WarnProcessingMissed", + "type": "event" + }, + { + "inputs": [], + "name": "DATA_FORMAT_LIST", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "EXIT_REQUEST_LIMIT_MANAGER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "EXIT_TYPE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "GENESIS_TIME", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MANAGE_CONSENSUS_CONTRACT_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MANAGE_CONSENSUS_VERSION_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PAUSE_INFINITELY", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PAUSE_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "RESUME_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SECONDS_PER_SLOT", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SUBMIT_DATA_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SUBMIT_REPORT_HASH_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "refSlot", + "type": "uint256" + } + ], + "name": "discardConsensusReport", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "maxValidatorsPerReport", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxExitRequestsLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "exitsPerFrame", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "frameDurationInSec", + "type": "uint256" + } + ], + "name": "finalizeUpgrade_v2", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getConsensusContract", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getConsensusReport", + "outputs": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "refSlot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "processingDeadlineTime", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "processingStarted", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getConsensusVersion", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getContractVersion", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "exitRequestsHash", + "type": "bytes32" + } + ], + "name": "getDeliveryTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "deliveryDateTimestamp", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getExitRequestLimitFullInfo", + "outputs": [ + { + "internalType": "uint256", + "name": "maxExitRequestsLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "exitsPerFrame", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "frameDurationInSec", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "prevExitRequestsLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "currentExitRequestsLimit", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLastProcessingRefSlot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getMaxValidatorsPerReport", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getProcessingState", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "currentFrameRefSlot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "processingDeadlineTime", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "dataHash", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "dataSubmitted", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "dataFormat", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requestsCount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requestsSubmitted", + "type": "uint256" + } + ], + "internalType": "struct ValidatorsExitBusOracle.ProcessingState", + "name": "result", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getResumeSinceTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getRoleMember", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleMemberCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTotalRequestsProcessed", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "address", + "name": "consensusContract", + "type": "address" + }, + { + "internalType": "uint256", + "name": "consensusVersion", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lastProcessingRefSlot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxValidatorsPerRequest", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxExitRequestsLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "exitsPerFrame", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "frameDurationInSec", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "isPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_duration", + "type": "uint256" + } + ], + "name": "pauseFor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_pauseUntilInclusive", + "type": "uint256" + } + ], + "name": "pauseUntil", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resume", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "setConsensusContract", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "version", + "type": "uint256" + } + ], + "name": "setConsensusVersion", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "maxExitRequestsLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "exitsPerFrame", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "frameDurationInSec", + "type": "uint256" + } + ], + "name": "setExitRequestLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "maxRequests", + "type": "uint256" + } + ], + "name": "setMaxValidatorsPerReport", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "reportHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "refSlot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "submitConsensusReport", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "dataFormat", + "type": "uint256" + } + ], + "internalType": "struct ValidatorsExitBus.ExitRequestsData", + "name": "request", + "type": "tuple" + } + ], + "name": "submitExitRequestsData", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "exitRequestsHash", + "type": "bytes32" + } + ], + "name": "submitExitRequestsHash", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "consensusVersion", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "refSlot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requestsCount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "dataFormat", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "internalType": "struct ValidatorsExitBusOracle.ReportData", + "name": "data", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "contractVersion", + "type": "uint256" + } + ], + "name": "submitReportData", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "dataFormat", + "type": "uint256" + } + ], + "internalType": "struct ValidatorsExitBus.ExitRequestsData", + "name": "exitsData", + "type": "tuple" + }, + { + "internalType": "uint256[]", + "name": "exitDataIndexes", + "type": "uint256[]" + }, + { + "internalType": "address", + "name": "refundRecipient", + "type": "address" + } + ], + "name": "triggerExits", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "exitRequests", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "dataFormat", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "unpackExitRequest", + "outputs": [ + { + "internalType": "bytes", + "name": "pubkey", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "nodeOpId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "moduleId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "valIndex", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/interfaces/WithdrawalVault.json b/interfaces/WithdrawalVault.json index cf8287e26..4d6c2157a 100644 --- a/interfaces/WithdrawalVault.json +++ b/interfaces/WithdrawalVault.json @@ -1 +1,371 @@ -[{"inputs":[{"internalType":"contract ILido","name":"_lido","type":"address"},{"internalType":"address","name":"_treasury","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[],"name":"LidoZeroAddress","type":"error"},{"inputs":[],"name":"NonZeroContractVersionOnInit","type":"error"},{"inputs":[{"internalType":"uint256","name":"requested","type":"uint256"},{"internalType":"uint256","name":"balance","type":"uint256"}],"name":"NotEnoughEther","type":"error"},{"inputs":[],"name":"NotLido","type":"error"},{"inputs":[],"name":"TreasuryZeroAddress","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[],"name":"ZeroAmount","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"version","type":"uint256"}],"name":"ContractVersionSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"requestedBy","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ERC20Recovered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"requestedBy","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721Recovered","type":"event"},{"inputs":[],"name":"LIDO","outputs":[{"internalType":"contract ILido","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TREASURY","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getContractVersion","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"recoverERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC721","name":"_token","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"recoverERC721","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"}] \ No newline at end of file +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_lido", + "type": "address" + }, + { + "internalType": "address", + "name": "_treasury", + "type": "address" + }, + { + "internalType": "address", + "name": "_triggerableWithdrawalsGateway", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "firstArrayLength", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "secondArrayLength", + "type": "uint256" + } + ], + "name": "ArraysLengthMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "FeeInvalidData", + "type": "error" + }, + { + "inputs": [], + "name": "FeeReadFailed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "providedFee", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requiredFee", + "type": "uint256" + } + ], + "name": "IncorrectFee", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidContractVersionIncrement", + "type": "error" + }, + { + "inputs": [], + "name": "NonZeroContractVersionOnInit", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requested", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + } + ], + "name": "NotEnoughEther", + "type": "error" + }, + { + "inputs": [], + "name": "NotLido", + "type": "error" + }, + { + "inputs": [], + "name": "NotTriggerableWithdrawalsGateway", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + } + ], + "name": "RequestAdditionFailed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "expected", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "received", + "type": "uint256" + } + ], + "name": "UnexpectedContractVersion", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAmount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + } + ], + "name": "ZeroArgument", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "version", + "type": "uint256" + } + ], + "name": "ContractVersionSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "requestedBy", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "ERC20Recovered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "requestedBy", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ERC721Recovered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes", + "name": "request", + "type": "bytes" + } + ], + "name": "WithdrawalRequestAdded", + "type": "event" + }, + { + "inputs": [], + "name": "LIDO", + "outputs": [ + { + "internalType": "contract ILido", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TREASURY", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TRIGGERABLE_WITHDRAWALS_GATEWAY", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "pubkeys", + "type": "bytes[]" + }, + { + "internalType": "uint64[]", + "name": "amounts", + "type": "uint64[]" + } + ], + "name": "addWithdrawalRequests", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "finalizeUpgrade_v2", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getContractVersion", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getWithdrawalRequestFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "_token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "recoverERC20", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC721", + "name": "_token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "recoverERC721", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "withdrawWithdrawals", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/interfaces/WithdrawalsManagerProxy.json b/interfaces/WithdrawalsManagerProxy.json new file mode 100644 index 000000000..92f4356bb --- /dev/null +++ b/interfaces/WithdrawalsManagerProxy.json @@ -0,0 +1,81 @@ +[ + { "inputs": [], "stateMutability": "nonpayable", "type": "constructor" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { "stateMutability": "payable", "type": "fallback" }, + { + "inputs": [], + "name": "implementation", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "newAdmin", "type": "address" } + ], + "name": "proxy_changeAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "proxy_getAdmin", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxy_getIsOssified", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { "internalType": "bytes", "name": "setupCalldata", "type": "bytes" } + ], + "name": "proxy_upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { "stateMutability": "payable", "type": "receive" } +] diff --git a/interfaces/csm/CSAccounting.json b/interfaces/csm/CSAccounting.json deleted file mode 100644 index 8dc94bed9..000000000 --- a/interfaces/csm/CSAccounting.json +++ /dev/null @@ -1,2299 +0,0 @@ -[ - { - "type": "constructor", - "inputs": [ - { - "name": "lidoLocator", - "type": "address", - "internalType": "address" - }, - { - "name": "communityStakingModule", - "type": "address", - "internalType": "address" - }, - { - "name": "maxCurveLength", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "minBondLockRetentionPeriod", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "maxBondLockRetentionPeriod", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "ACCOUNTING_MANAGER_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "CSM", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address", - "internalType": "contract ICSModule" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "DEFAULT_ADMIN_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "DEFAULT_BOND_CURVE_ID", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "LIDO", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address", - "internalType": "contract ILido" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "LIDO_LOCATOR", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address", - "internalType": "contract ILidoLocator" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "MANAGE_BOND_CURVES_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "MAX_BOND_LOCK_RETENTION_PERIOD", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "MAX_CURVE_LENGTH", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "MIN_BOND_LOCK_RETENTION_PERIOD", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "MIN_CURVE_LENGTH", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "PAUSE_INFINITELY", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "PAUSE_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "RECOVERER_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "RESET_BOND_CURVE_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "RESUME_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "SET_BOND_CURVE_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "WITHDRAWAL_QUEUE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address", - "internalType": "contract IWithdrawalQueue" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "WSTETH", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address", - "internalType": "contract IWstETH" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "addBondCurve", - "inputs": [ - { - "name": "bondCurve", - "type": "uint256[]", - "internalType": "uint256[]" - } - ], - "outputs": [ - { - "name": "id", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "chargeFee", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "amount", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "chargePenaltyRecipient", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address", - "internalType": "address" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "claimRewardsStETH", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "stETHAmount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "rewardAddress", - "type": "address", - "internalType": "address" - }, - { - "name": "cumulativeFeeShares", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "rewardsProof", - "type": "bytes32[]", - "internalType": "bytes32[]" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "claimRewardsUnstETH", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "stEthAmount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "rewardAddress", - "type": "address", - "internalType": "address" - }, - { - "name": "cumulativeFeeShares", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "rewardsProof", - "type": "bytes32[]", - "internalType": "bytes32[]" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "claimRewardsWstETH", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "wstETHAmount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "rewardAddress", - "type": "address", - "internalType": "address" - }, - { - "name": "cumulativeFeeShares", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "rewardsProof", - "type": "bytes32[]", - "internalType": "bytes32[]" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "compensateLockedBondETH", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "payable" - }, - { - "type": "function", - "name": "depositETH", - "inputs": [ - { - "name": "from", - "type": "address", - "internalType": "address" - }, - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "payable" - }, - { - "type": "function", - "name": "depositStETH", - "inputs": [ - { - "name": "from", - "type": "address", - "internalType": "address" - }, - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "stETHAmount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "permit", - "type": "tuple", - "internalType": "struct ICSAccounting.PermitInput", - "components": [ - { - "name": "value", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "deadline", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "v", - "type": "uint8", - "internalType": "uint8" - }, - { - "name": "r", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "s", - "type": "bytes32", - "internalType": "bytes32" - } - ] - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "depositWstETH", - "inputs": [ - { - "name": "from", - "type": "address", - "internalType": "address" - }, - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "wstETHAmount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "permit", - "type": "tuple", - "internalType": "struct ICSAccounting.PermitInput", - "components": [ - { - "name": "value", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "deadline", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "v", - "type": "uint8", - "internalType": "uint8" - }, - { - "name": "r", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "s", - "type": "bytes32", - "internalType": "bytes32" - } - ] - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "feeDistributor", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address", - "internalType": "contract ICSFeeDistributor" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getActualLockedBond", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getBond", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getBondAmountByKeysCount", - "inputs": [ - { - "name": "keys", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "curve", - "type": "tuple", - "internalType": "struct ICSBondCurve.BondCurve", - "components": [ - { - "name": "points", - "type": "uint256[]", - "internalType": "uint256[]" - }, - { - "name": "trend", - "type": "uint256", - "internalType": "uint256" - } - ] - } - ], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "pure" - }, - { - "type": "function", - "name": "getBondAmountByKeysCount", - "inputs": [ - { - "name": "keys", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "curveId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getBondAmountByKeysCountWstETH", - "inputs": [ - { - "name": "keysCount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "curveId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getBondAmountByKeysCountWstETH", - "inputs": [ - { - "name": "keysCount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "curve", - "type": "tuple", - "internalType": "struct ICSBondCurve.BondCurve", - "components": [ - { - "name": "points", - "type": "uint256[]", - "internalType": "uint256[]" - }, - { - "name": "trend", - "type": "uint256", - "internalType": "uint256" - } - ] - } - ], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getBondCurve", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "tuple", - "internalType": "struct ICSBondCurve.BondCurve", - "components": [ - { - "name": "points", - "type": "uint256[]", - "internalType": "uint256[]" - }, - { - "name": "trend", - "type": "uint256", - "internalType": "uint256" - } - ] - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getBondCurveId", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getBondLockRetentionPeriod", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getBondShares", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getBondSummary", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "current", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "required", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getBondSummaryShares", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "current", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "required", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getCurveInfo", - "inputs": [ - { - "name": "curveId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "tuple", - "internalType": "struct ICSBondCurve.BondCurve", - "components": [ - { - "name": "points", - "type": "uint256[]", - "internalType": "uint256[]" - }, - { - "name": "trend", - "type": "uint256", - "internalType": "uint256" - } - ] - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getKeysCountByBondAmount", - "inputs": [ - { - "name": "amount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "curve", - "type": "tuple", - "internalType": "struct ICSBondCurve.BondCurve", - "components": [ - { - "name": "points", - "type": "uint256[]", - "internalType": "uint256[]" - }, - { - "name": "trend", - "type": "uint256", - "internalType": "uint256" - } - ] - } - ], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "pure" - }, - { - "type": "function", - "name": "getKeysCountByBondAmount", - "inputs": [ - { - "name": "amount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "curveId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getLockedBondInfo", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "tuple", - "internalType": "struct ICSBondLock.BondLock", - "components": [ - { - "name": "amount", - "type": "uint128", - "internalType": "uint128" - }, - { - "name": "retentionUntil", - "type": "uint128", - "internalType": "uint128" - } - ] - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getRequiredBondForNextKeys", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "additionalKeys", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getRequiredBondForNextKeysWstETH", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "additionalKeys", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getResumeSinceTimestamp", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getRoleAdmin", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getRoleMember", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "index", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "address", - "internalType": "address" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getRoleMemberCount", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getUnbondedKeysCount", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getUnbondedKeysCountToEject", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "grantRole", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "account", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "hasRole", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "account", - "type": "address", - "internalType": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "bool", - "internalType": "bool" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "initialize", - "inputs": [ - { - "name": "bondCurve", - "type": "uint256[]", - "internalType": "uint256[]" - }, - { - "name": "admin", - "type": "address", - "internalType": "address" - }, - { - "name": "_feeDistributor", - "type": "address", - "internalType": "address" - }, - { - "name": "bondLockRetentionPeriod", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "_chargePenaltyRecipient", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "isPaused", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bool", - "internalType": "bool" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "lockBondETH", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "amount", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "pauseFor", - "inputs": [ - { - "name": "duration", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "penalize", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "amount", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "pullFeeRewards", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "cumulativeFeeShares", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "rewardsProof", - "type": "bytes32[]", - "internalType": "bytes32[]" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "recoverERC1155", - "inputs": [ - { - "name": "token", - "type": "address", - "internalType": "address" - }, - { - "name": "tokenId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "recoverERC20", - "inputs": [ - { - "name": "token", - "type": "address", - "internalType": "address" - }, - { - "name": "amount", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "recoverERC721", - "inputs": [ - { - "name": "token", - "type": "address", - "internalType": "address" - }, - { - "name": "tokenId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "recoverEther", - "inputs": [], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "recoverStETHShares", - "inputs": [], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "releaseLockedBondETH", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "amount", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "renewBurnerAllowance", - "inputs": [], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "renounceRole", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "callerConfirmation", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "resetBondCurve", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "resume", - "inputs": [], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "revokeRole", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "account", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "setBondCurve", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "curveId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "setChargePenaltyRecipient", - "inputs": [ - { - "name": "_chargePenaltyRecipient", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "setLockedBondRetentionPeriod", - "inputs": [ - { - "name": "retention", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "settleLockedBondETH", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "settledAmount", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "supportsInterface", - "inputs": [ - { - "name": "interfaceId", - "type": "bytes4", - "internalType": "bytes4" - } - ], - "outputs": [ - { - "name": "", - "type": "bool", - "internalType": "bool" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "totalBondShares", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "updateBondCurve", - "inputs": [ - { - "name": "curveId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "bondCurve", - "type": "uint256[]", - "internalType": "uint256[]" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "event", - "name": "BondBurned", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "toBurnAmount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - }, - { - "name": "burnedAmount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "BondCharged", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "toChargeAmount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - }, - { - "name": "chargedAmount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "BondClaimedStETH", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "to", - "type": "address", - "indexed": false, - "internalType": "address" - }, - { - "name": "amount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "BondClaimedUnstETH", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "to", - "type": "address", - "indexed": false, - "internalType": "address" - }, - { - "name": "amount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - }, - { - "name": "requestId", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "BondClaimedWstETH", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "to", - "type": "address", - "indexed": false, - "internalType": "address" - }, - { - "name": "amount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "BondCurveAdded", - "inputs": [ - { - "name": "bondCurve", - "type": "uint256[]", - "indexed": false, - "internalType": "uint256[]" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "BondCurveSet", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "curveId", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "BondCurveUpdated", - "inputs": [ - { - "name": "curveId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "bondCurve", - "type": "uint256[]", - "indexed": false, - "internalType": "uint256[]" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "BondDepositedETH", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "from", - "type": "address", - "indexed": false, - "internalType": "address" - }, - { - "name": "amount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "BondDepositedStETH", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "from", - "type": "address", - "indexed": false, - "internalType": "address" - }, - { - "name": "amount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "BondDepositedWstETH", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "from", - "type": "address", - "indexed": false, - "internalType": "address" - }, - { - "name": "amount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "BondLockChanged", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "newAmount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - }, - { - "name": "retentionUntil", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "BondLockCompensated", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "amount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "BondLockRemoved", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "BondLockRetentionPeriodChanged", - "inputs": [ - { - "name": "retentionPeriod", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ChargePenaltyRecipientSet", - "inputs": [ - { - "name": "chargePenaltyRecipient", - "type": "address", - "indexed": false, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ERC1155Recovered", - "inputs": [ - { - "name": "token", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "tokenId", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - }, - { - "name": "recipient", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "amount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ERC20Recovered", - "inputs": [ - { - "name": "token", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "recipient", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "amount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ERC721Recovered", - "inputs": [ - { - "name": "token", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "tokenId", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - }, - { - "name": "recipient", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "EtherRecovered", - "inputs": [ - { - "name": "recipient", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "amount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "Initialized", - "inputs": [ - { - "name": "version", - "type": "uint64", - "indexed": false, - "internalType": "uint64" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "Paused", - "inputs": [ - { - "name": "duration", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "Resumed", - "inputs": [], - "anonymous": false - }, - { - "type": "event", - "name": "RoleAdminChanged", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - }, - { - "name": "previousAdminRole", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - }, - { - "name": "newAdminRole", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "RoleGranted", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - }, - { - "name": "account", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "sender", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "RoleRevoked", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - }, - { - "name": "account", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "sender", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "StETHSharesRecovered", - "inputs": [ - { - "name": "recipient", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "shares", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "error", - "name": "AccessControlBadConfirmation", - "inputs": [] - }, - { - "type": "error", - "name": "AccessControlUnauthorizedAccount", - "inputs": [ - { - "name": "account", - "type": "address", - "internalType": "address" - }, - { - "name": "neededRole", - "type": "bytes32", - "internalType": "bytes32" - } - ] - }, - { - "type": "error", - "name": "ElRewardsVaultReceiveFailed", - "inputs": [] - }, - { - "type": "error", - "name": "FailedToSendEther", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidBondCurveId", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidBondCurveLength", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidBondCurveMaxLength", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidBondCurveValues", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidBondLockAmount", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidBondLockRetentionPeriod", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidInitialisationCurveId", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidInitialization", - "inputs": [] - }, - { - "type": "error", - "name": "NodeOperatorDoesNotExist", - "inputs": [] - }, - { - "type": "error", - "name": "NotAllowedToRecover", - "inputs": [] - }, - { - "type": "error", - "name": "NotInitializing", - "inputs": [] - }, - { - "type": "error", - "name": "NothingToClaim", - "inputs": [] - }, - { - "type": "error", - "name": "PauseUntilMustBeInFuture", - "inputs": [] - }, - { - "type": "error", - "name": "PausedExpected", - "inputs": [] - }, - { - "type": "error", - "name": "ResumedExpected", - "inputs": [] - }, - { - "type": "error", - "name": "SafeCastOverflowedUintDowncast", - "inputs": [ - { - "name": "bits", - "type": "uint8", - "internalType": "uint8" - }, - { - "name": "value", - "type": "uint256", - "internalType": "uint256" - } - ] - }, - { - "type": "error", - "name": "SenderIsNotCSM", - "inputs": [] - }, - { - "type": "error", - "name": "ZeroAdminAddress", - "inputs": [] - }, - { - "type": "error", - "name": "ZeroChargePenaltyRecipientAddress", - "inputs": [] - }, - { - "type": "error", - "name": "ZeroFeeDistributorAddress", - "inputs": [] - }, - { - "type": "error", - "name": "ZeroLocatorAddress", - "inputs": [] - }, - { - "type": "error", - "name": "ZeroModuleAddress", - "inputs": [] - }, - { - "type": "error", - "name": "ZeroPauseDuration", - "inputs": [] - } - ] diff --git a/interfaces/csm/CSFeeDistributor.json b/interfaces/csm/CSFeeDistributor.json deleted file mode 100644 index 26a88ba29..000000000 --- a/interfaces/csm/CSFeeDistributor.json +++ /dev/null @@ -1,849 +0,0 @@ -[ - { - "type": "constructor", - "inputs": [ - { - "name": "stETH", - "type": "address", - "internalType": "address" - }, - { - "name": "accounting", - "type": "address", - "internalType": "address" - }, - { - "name": "oracle", - "type": "address", - "internalType": "address" - } - ], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "ACCOUNTING", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address", - "internalType": "address" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "DEFAULT_ADMIN_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "ORACLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address", - "internalType": "address" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "RECOVERER_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "STETH", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address", - "internalType": "contract IStETH" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "distributeFees", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "shares", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "proof", - "type": "bytes32[]", - "internalType": "bytes32[]" - } - ], - "outputs": [ - { - "name": "sharesToDistribute", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "distributedShares", - "inputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getFeesToDistribute", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "shares", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "proof", - "type": "bytes32[]", - "internalType": "bytes32[]" - } - ], - "outputs": [ - { - "name": "sharesToDistribute", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getRoleAdmin", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getRoleMember", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "index", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "address", - "internalType": "address" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getRoleMemberCount", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "grantRole", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "account", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "hasRole", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "account", - "type": "address", - "internalType": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "bool", - "internalType": "bool" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "hashLeaf", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "shares", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "pure" - }, - { - "type": "function", - "name": "initialize", - "inputs": [ - { - "name": "admin", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "pendingSharesToDistribute", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "processOracleReport", - "inputs": [ - { - "name": "_treeRoot", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "_treeCid", - "type": "string", - "internalType": "string" - }, - { - "name": "distributed", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "recoverERC1155", - "inputs": [ - { - "name": "token", - "type": "address", - "internalType": "address" - }, - { - "name": "tokenId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "recoverERC20", - "inputs": [ - { - "name": "token", - "type": "address", - "internalType": "address" - }, - { - "name": "amount", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "recoverERC721", - "inputs": [ - { - "name": "token", - "type": "address", - "internalType": "address" - }, - { - "name": "tokenId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "recoverEther", - "inputs": [], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "renounceRole", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "callerConfirmation", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "revokeRole", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "account", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "supportsInterface", - "inputs": [ - { - "name": "interfaceId", - "type": "bytes4", - "internalType": "bytes4" - } - ], - "outputs": [ - { - "name": "", - "type": "bool", - "internalType": "bool" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "totalClaimableShares", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "treeCid", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "string", - "internalType": "string" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "treeRoot", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "event", - "name": "DistributionDataUpdated", - "inputs": [ - { - "name": "totalClaimableShares", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - }, - { - "name": "treeRoot", - "type": "bytes32", - "indexed": false, - "internalType": "bytes32" - }, - { - "name": "treeCid", - "type": "string", - "indexed": false, - "internalType": "string" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ERC1155Recovered", - "inputs": [ - { - "name": "token", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "tokenId", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - }, - { - "name": "recipient", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "amount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ERC20Recovered", - "inputs": [ - { - "name": "token", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "recipient", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "amount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ERC721Recovered", - "inputs": [ - { - "name": "token", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "tokenId", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - }, - { - "name": "recipient", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "EtherRecovered", - "inputs": [ - { - "name": "recipient", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "amount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "FeeDistributed", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "shares", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "Initialized", - "inputs": [ - { - "name": "version", - "type": "uint64", - "indexed": false, - "internalType": "uint64" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "RoleAdminChanged", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - }, - { - "name": "previousAdminRole", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - }, - { - "name": "newAdminRole", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "RoleGranted", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - }, - { - "name": "account", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "sender", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "RoleRevoked", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - }, - { - "name": "account", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "sender", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "StETHSharesRecovered", - "inputs": [ - { - "name": "recipient", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "shares", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "error", - "name": "AccessControlBadConfirmation", - "inputs": [] - }, - { - "type": "error", - "name": "AccessControlUnauthorizedAccount", - "inputs": [ - { - "name": "account", - "type": "address", - "internalType": "address" - }, - { - "name": "neededRole", - "type": "bytes32", - "internalType": "bytes32" - } - ] - }, - { - "type": "error", - "name": "FailedToSendEther", - "inputs": [] - }, - { - "type": "error", - "name": "FeeSharesDecrease", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidInitialization", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidProof", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidShares", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidTreeCID", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidTreeRoot", - "inputs": [] - }, - { - "type": "error", - "name": "NotAccounting", - "inputs": [] - }, - { - "type": "error", - "name": "NotAllowedToRecover", - "inputs": [] - }, - { - "type": "error", - "name": "NotEnoughShares", - "inputs": [] - }, - { - "type": "error", - "name": "NotInitializing", - "inputs": [] - }, - { - "type": "error", - "name": "NotOracle", - "inputs": [] - }, - { - "type": "error", - "name": "ZeroAccountingAddress", - "inputs": [] - }, - { - "type": "error", - "name": "ZeroAdminAddress", - "inputs": [] - }, - { - "type": "error", - "name": "ZeroOracleAddress", - "inputs": [] - }, - { - "type": "error", - "name": "ZeroStEthAddress", - "inputs": [] - } - ] diff --git a/interfaces/csm/CSFeeOracle.json b/interfaces/csm/CSFeeOracle.json deleted file mode 100644 index d08f0a893..000000000 --- a/interfaces/csm/CSFeeOracle.json +++ /dev/null @@ -1,1381 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint256", - "name": "secondsPerSlot", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "genesisTime", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "AccessControlBadConfirmation", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "neededRole", - "type": "bytes32" - } - ], - "name": "AccessControlUnauthorizedAccount", - "type": "error" - }, - { - "inputs": [], - "name": "AddressCannotBeSame", - "type": "error" - }, - { - "inputs": [], - "name": "AddressCannotBeZero", - "type": "error" - }, - { - "inputs": [], - "name": "FailedToSendEther", - "type": "error" - }, - { - "inputs": [], - "name": "HashCannotBeZero", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "initialRefSlot", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "processingRefSlot", - "type": "uint256" - } - ], - "name": "InitialRefSlotCannotBeLessThanProcessingOne", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidContractVersion", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidContractVersionIncrement", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidInitialization", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidPerfLeeway", - "type": "error" - }, - { - "inputs": [], - "name": "NoConsensusReportToProcess", - "type": "error" - }, - { - "inputs": [], - "name": "NonZeroContractVersionOnInit", - "type": "error" - }, - { - "inputs": [], - "name": "NotAllowedToRecover", - "type": "error" - }, - { - "inputs": [], - "name": "NotInitializing", - "type": "error" - }, - { - "inputs": [], - "name": "PauseUntilMustBeInFuture", - "type": "error" - }, - { - "inputs": [], - "name": "PausedExpected", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - } - ], - "name": "ProcessingDeadlineMissed", - "type": "error" - }, - { - "inputs": [], - "name": "RefSlotAlreadyProcessing", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "refSlot", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "prevRefSlot", - "type": "uint256" - } - ], - "name": "RefSlotCannotDecrease", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "refSlot", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "processingRefSlot", - "type": "uint256" - } - ], - "name": "RefSlotMustBeGreaterThanProcessingOne", - "type": "error" - }, - { - "inputs": [], - "name": "ResumedExpected", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "bits", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "SafeCastOverflowedUintDowncast", - "type": "error" - }, - { - "inputs": [], - "name": "SecondsPerSlotCannotBeZero", - "type": "error" - }, - { - "inputs": [], - "name": "SenderIsNotTheConsensusContract", - "type": "error" - }, - { - "inputs": [], - "name": "SenderNotAllowed", - "type": "error" - }, - { - "inputs": [], - "name": "UnexpectedChainConfig", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "expectedVersion", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "receivedVersion", - "type": "uint256" - } - ], - "name": "UnexpectedConsensusVersion", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "expected", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "received", - "type": "uint256" - } - ], - "name": "UnexpectedContractVersion", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "consensusHash", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "receivedHash", - "type": "bytes32" - } - ], - "name": "UnexpectedDataHash", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "consensusRefSlot", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "dataRefSlot", - "type": "uint256" - } - ], - "name": "UnexpectedRefSlot", - "type": "error" - }, - { - "inputs": [], - "name": "VersionCannotBeSame", - "type": "error" - }, - { - "inputs": [], - "name": "VersionCannotBeZero", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAdminAddress", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroFeeDistributorAddress", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroPauseDuration", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "addr", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "prevAddr", - "type": "address" - } - ], - "name": "ConsensusHashContractSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "version", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "prevVersion", - "type": "uint256" - } - ], - "name": "ConsensusVersionSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "version", - "type": "uint256" - } - ], - "name": "ContractVersionSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "token", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "ERC1155Recovered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "token", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "ERC20Recovered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "token", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - } - ], - "name": "ERC721Recovered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "EtherRecovered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "feeDistributorContract", - "type": "address" - } - ], - "name": "FeeDistributorContractSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint64", - "name": "version", - "type": "uint64" - } - ], - "name": "Initialized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "duration", - "type": "uint256" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "valueBP", - "type": "uint256" - } - ], - "name": "PerfLeewaySet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "refSlot", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "hash", - "type": "bytes32" - } - ], - "name": "ProcessingStarted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "refSlot", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "hash", - "type": "bytes32" - } - ], - "name": "ReportDiscarded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "refSlot", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "hash", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "processingDeadlineTime", - "type": "uint256" - } - ], - "name": "ReportSubmitted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "Resumed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "previousAdminRole", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "newAdminRole", - "type": "bytes32" - } - ], - "name": "RoleAdminChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "RoleGranted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "RoleRevoked", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "shares", - "type": "uint256" - } - ], - "name": "StETHSharesRecovered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "refSlot", - "type": "uint256" - } - ], - "name": "WarnProcessingMissed", - "type": "event" - }, - { - "inputs": [], - "name": "CONTRACT_MANAGER_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "DEFAULT_ADMIN_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "GENESIS_TIME", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MANAGE_CONSENSUS_CONTRACT_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MANAGE_CONSENSUS_VERSION_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "PAUSE_INFINITELY", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "PAUSE_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "RECOVERER_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "RESUME_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "SECONDS_PER_SLOT", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "SUBMIT_DATA_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "avgPerfLeewayBP", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "refSlot", - "type": "uint256" - } - ], - "name": "discardConsensusReport", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "feeDistributor", - "outputs": [ - { - "internalType": "contract ICSFeeDistributor", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getConsensusContract", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getConsensusReport", - "outputs": [ - { - "internalType": "bytes32", - "name": "hash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "refSlot", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "processingDeadlineTime", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "processingStarted", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getConsensusVersion", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getContractVersion", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getLastProcessingRefSlot", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getResumeSinceTimestamp", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - } - ], - "name": "getRoleAdmin", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "index", - "type": "uint256" - } - ], - "name": "getRoleMember", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - } - ], - "name": "getRoleMemberCount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "grantRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "hasRole", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "address", - "name": "feeDistributorContract", - "type": "address" - }, - { - "internalType": "address", - "name": "consensusContract", - "type": "address" - }, - { - "internalType": "uint256", - "name": "consensusVersion", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_avgPerfLeewayBP", - "type": "uint256" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "isPaused", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "duration", - "type": "uint256" - } - ], - "name": "pauseFor", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "pauseUntilInclusive", - "type": "uint256" - } - ], - "name": "pauseUntil", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "token", - "type": "address" - }, - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "recoverERC1155", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "token", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "recoverERC20", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "token", - "type": "address" - }, - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "recoverERC721", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "recoverEther", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "callerConfirmation", - "type": "address" - } - ], - "name": "renounceRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "resume", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "revokeRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - } - ], - "name": "setConsensusContract", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "version", - "type": "uint256" - } - ], - "name": "setConsensusVersion", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "feeDistributorContract", - "type": "address" - } - ], - "name": "setFeeDistributorContract", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "valueBP", - "type": "uint256" - } - ], - "name": "setPerformanceLeeway", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "reportHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "refSlot", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - } - ], - "name": "submitConsensusReport", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "consensusVersion", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "refSlot", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "treeRoot", - "type": "bytes32" - }, - { - "internalType": "string", - "name": "treeCid", - "type": "string" - }, - { - "internalType": "string", - "name": "logCid", - "type": "string" - }, - { - "internalType": "uint256", - "name": "distributed", - "type": "uint256" - } - ], - "internalType": "struct CSFeeOracle.ReportData", - "name": "data", - "type": "tuple" - }, - { - "internalType": "uint256", - "name": "contractVersion", - "type": "uint256" - } - ], - "name": "submitReportData", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/interfaces/csm/CSHashConsensus.json b/interfaces/csm/CSHashConsensus.json deleted file mode 100644 index afa2ea3cf..000000000 --- a/interfaces/csm/CSHashConsensus.json +++ /dev/null @@ -1,1141 +0,0 @@ -[ - { - "type": "constructor", - "inputs": [ - { - "name": "slotsPerEpoch", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "secondsPerSlot", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "genesisTime", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "epochsPerFrame", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "fastLaneLengthSlots", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "admin", - "type": "address", - "internalType": "address" - }, - { - "name": "reportProcessor", - "type": "address", - "internalType": "address" - } - ], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "DEFAULT_ADMIN_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "DISABLE_CONSENSUS_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "MANAGE_FAST_LANE_CONFIG_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "MANAGE_FRAME_CONFIG_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "MANAGE_MEMBERS_AND_QUORUM_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "MANAGE_REPORT_PROCESSOR_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "addMember", - "inputs": [ - { - "name": "addr", - "type": "address", - "internalType": "address" - }, - { - "name": "quorum", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "disableConsensus", - "inputs": [], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "getChainConfig", - "inputs": [], - "outputs": [ - { - "name": "slotsPerEpoch", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "secondsPerSlot", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "genesisTime", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getConsensusState", - "inputs": [], - "outputs": [ - { - "name": "refSlot", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "consensusReport", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "isReportProcessing", - "type": "bool", - "internalType": "bool" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getConsensusStateForMember", - "inputs": [ - { - "name": "addr", - "type": "address", - "internalType": "address" - } - ], - "outputs": [ - { - "name": "result", - "type": "tuple", - "internalType": "struct HashConsensus.MemberConsensusState", - "components": [ - { - "name": "currentFrameRefSlot", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "currentFrameConsensusReport", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "isMember", - "type": "bool", - "internalType": "bool" - }, - { - "name": "isFastLane", - "type": "bool", - "internalType": "bool" - }, - { - "name": "canReport", - "type": "bool", - "internalType": "bool" - }, - { - "name": "lastMemberReportRefSlot", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "currentFrameMemberReport", - "type": "bytes32", - "internalType": "bytes32" - } - ] - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getCurrentFrame", - "inputs": [], - "outputs": [ - { - "name": "refSlot", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "reportProcessingDeadlineSlot", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getFastLaneMembers", - "inputs": [], - "outputs": [ - { - "name": "addresses", - "type": "address[]", - "internalType": "address[]" - }, - { - "name": "lastReportedRefSlots", - "type": "uint256[]", - "internalType": "uint256[]" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getFrameConfig", - "inputs": [], - "outputs": [ - { - "name": "initialEpoch", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "epochsPerFrame", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "fastLaneLengthSlots", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getInitialRefSlot", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getIsFastLaneMember", - "inputs": [ - { - "name": "addr", - "type": "address", - "internalType": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "bool", - "internalType": "bool" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getIsMember", - "inputs": [ - { - "name": "addr", - "type": "address", - "internalType": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "bool", - "internalType": "bool" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getMembers", - "inputs": [], - "outputs": [ - { - "name": "addresses", - "type": "address[]", - "internalType": "address[]" - }, - { - "name": "lastReportedRefSlots", - "type": "uint256[]", - "internalType": "uint256[]" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getQuorum", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getReportProcessor", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address", - "internalType": "address" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getReportVariants", - "inputs": [], - "outputs": [ - { - "name": "variants", - "type": "bytes32[]", - "internalType": "bytes32[]" - }, - { - "name": "support", - "type": "uint256[]", - "internalType": "uint256[]" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getRoleAdmin", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getRoleMember", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "index", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "address", - "internalType": "address" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getRoleMemberCount", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "grantRole", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "account", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "hasRole", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "account", - "type": "address", - "internalType": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "bool", - "internalType": "bool" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "removeMember", - "inputs": [ - { - "name": "addr", - "type": "address", - "internalType": "address" - }, - { - "name": "quorum", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "renounceRole", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "callerConfirmation", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "revokeRole", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "account", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "setFastLaneLengthSlots", - "inputs": [ - { - "name": "fastLaneLengthSlots", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "setFrameConfig", - "inputs": [ - { - "name": "epochsPerFrame", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "fastLaneLengthSlots", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "setQuorum", - "inputs": [ - { - "name": "quorum", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "setReportProcessor", - "inputs": [ - { - "name": "newProcessor", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "submitReport", - "inputs": [ - { - "name": "slot", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "report", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "consensusVersion", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "supportsInterface", - "inputs": [ - { - "name": "interfaceId", - "type": "bytes4", - "internalType": "bytes4" - } - ], - "outputs": [ - { - "name": "", - "type": "bool", - "internalType": "bool" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "updateInitialEpoch", - "inputs": [ - { - "name": "initialEpoch", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "event", - "name": "ConsensusLost", - "inputs": [ - { - "name": "refSlot", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ConsensusReached", - "inputs": [ - { - "name": "refSlot", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "report", - "type": "bytes32", - "indexed": false, - "internalType": "bytes32" - }, - { - "name": "support", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "FastLaneConfigSet", - "inputs": [ - { - "name": "fastLaneLengthSlots", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "FrameConfigSet", - "inputs": [ - { - "name": "newInitialEpoch", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - }, - { - "name": "newEpochsPerFrame", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "Initialized", - "inputs": [ - { - "name": "version", - "type": "uint64", - "indexed": false, - "internalType": "uint64" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "MemberAdded", - "inputs": [ - { - "name": "addr", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "newTotalMembers", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - }, - { - "name": "newQuorum", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "MemberRemoved", - "inputs": [ - { - "name": "addr", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "newTotalMembers", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - }, - { - "name": "newQuorum", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "QuorumSet", - "inputs": [ - { - "name": "newQuorum", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - }, - { - "name": "totalMembers", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - }, - { - "name": "prevQuorum", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ReportProcessorSet", - "inputs": [ - { - "name": "processor", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "prevProcessor", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ReportReceived", - "inputs": [ - { - "name": "refSlot", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "member", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "report", - "type": "bytes32", - "indexed": false, - "internalType": "bytes32" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "RoleAdminChanged", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - }, - { - "name": "previousAdminRole", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - }, - { - "name": "newAdminRole", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "RoleGranted", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - }, - { - "name": "account", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "sender", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "RoleRevoked", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - }, - { - "name": "account", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "sender", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "error", - "name": "AccessControlBadConfirmation", - "inputs": [] - }, - { - "type": "error", - "name": "AccessControlUnauthorizedAccount", - "inputs": [ - { - "name": "account", - "type": "address", - "internalType": "address" - }, - { - "name": "neededRole", - "type": "bytes32", - "internalType": "bytes32" - } - ] - }, - { - "type": "error", - "name": "AddressCannotBeZero", - "inputs": [] - }, - { - "type": "error", - "name": "AdminCannotBeZero", - "inputs": [] - }, - { - "type": "error", - "name": "ConsensusReportAlreadyProcessing", - "inputs": [] - }, - { - "type": "error", - "name": "DuplicateMember", - "inputs": [] - }, - { - "type": "error", - "name": "DuplicateReport", - "inputs": [] - }, - { - "type": "error", - "name": "EmptyReport", - "inputs": [] - }, - { - "type": "error", - "name": "EpochsPerFrameCannotBeZero", - "inputs": [] - }, - { - "type": "error", - "name": "FastLanePeriodCannotBeLongerThanFrame", - "inputs": [] - }, - { - "type": "error", - "name": "InitialEpochAlreadyArrived", - "inputs": [] - }, - { - "type": "error", - "name": "InitialEpochIsYetToArrive", - "inputs": [] - }, - { - "type": "error", - "name": "InitialEpochRefSlotCannotBeEarlierThanProcessingSlot", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidChainConfig", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidInitialization", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidSlot", - "inputs": [] - }, - { - "type": "error", - "name": "NewProcessorCannotBeTheSame", - "inputs": [] - }, - { - "type": "error", - "name": "NonFastLaneMemberCannotReportWithinFastLaneInterval", - "inputs": [] - }, - { - "type": "error", - "name": "NonMember", - "inputs": [] - }, - { - "type": "error", - "name": "NotInitializing", - "inputs": [] - }, - { - "type": "error", - "name": "NumericOverflow", - "inputs": [] - }, - { - "type": "error", - "name": "QuorumTooSmall", - "inputs": [ - { - "name": "minQuorum", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "receivedQuorum", - "type": "uint256", - "internalType": "uint256" - } - ] - }, - { - "type": "error", - "name": "ReportProcessorCannotBeZero", - "inputs": [] - }, - { - "type": "error", - "name": "SafeCastOverflowedUintDowncast", - "inputs": [ - { - "name": "bits", - "type": "uint8", - "internalType": "uint8" - }, - { - "name": "value", - "type": "uint256", - "internalType": "uint256" - } - ] - }, - { - "type": "error", - "name": "StaleReport", - "inputs": [] - }, - { - "type": "error", - "name": "UnexpectedConsensusVersion", - "inputs": [ - { - "name": "expected", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "received", - "type": "uint256", - "internalType": "uint256" - } - ] - } - ] diff --git a/interfaces/csm/CSModule.json b/interfaces/csm/CSModule.json deleted file mode 100644 index d2a5e9255..000000000 --- a/interfaces/csm/CSModule.json +++ /dev/null @@ -1,2986 +0,0 @@ -[ - { - "type": "constructor", - "inputs": [ - { - "name": "moduleType", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "minSlashingPenaltyQuotient", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "elRewardsStealingFine", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "maxKeysPerOperatorEA", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "lidoLocator", - "type": "address", - "internalType": "address" - } - ], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "DEFAULT_ADMIN_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "EL_REWARDS_STEALING_FINE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "INITIAL_SLASHING_PENALTY", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "LIDO_LOCATOR", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address", - "internalType": "contract ILidoLocator" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "MAX_SIGNING_KEYS_PER_OPERATOR_BEFORE_PUBLIC_RELEASE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "MODULE_MANAGER_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "PAUSE_INFINITELY", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "PAUSE_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "RECOVERER_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "REPORT_EL_REWARDS_STEALING_PENALTY_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "RESUME_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "SETTLE_EL_REWARDS_STEALING_PENALTY_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "STAKING_ROUTER_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "STETH", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address", - "internalType": "contract IStETH" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "VERIFIER_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "accounting", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address", - "internalType": "contract ICSAccounting" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "activatePublicRelease", - "inputs": [], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "addNodeOperatorETH", - "inputs": [ - { - "name": "keysCount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "publicKeys", - "type": "bytes", - "internalType": "bytes" - }, - { - "name": "signatures", - "type": "bytes", - "internalType": "bytes" - }, - { - "name": "managementProperties", - "type": "tuple", - "internalType": "struct NodeOperatorManagementProperties", - "components": [ - { - "name": "managerAddress", - "type": "address", - "internalType": "address" - }, - { - "name": "rewardAddress", - "type": "address", - "internalType": "address" - }, - { - "name": "extendedManagerPermissions", - "type": "bool", - "internalType": "bool" - } - ] - }, - { - "name": "eaProof", - "type": "bytes32[]", - "internalType": "bytes32[]" - }, - { - "name": "referrer", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "payable" - }, - { - "type": "function", - "name": "addNodeOperatorStETH", - "inputs": [ - { - "name": "keysCount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "publicKeys", - "type": "bytes", - "internalType": "bytes" - }, - { - "name": "signatures", - "type": "bytes", - "internalType": "bytes" - }, - { - "name": "managementProperties", - "type": "tuple", - "internalType": "struct NodeOperatorManagementProperties", - "components": [ - { - "name": "managerAddress", - "type": "address", - "internalType": "address" - }, - { - "name": "rewardAddress", - "type": "address", - "internalType": "address" - }, - { - "name": "extendedManagerPermissions", - "type": "bool", - "internalType": "bool" - } - ] - }, - { - "name": "permit", - "type": "tuple", - "internalType": "struct ICSAccounting.PermitInput", - "components": [ - { - "name": "value", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "deadline", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "v", - "type": "uint8", - "internalType": "uint8" - }, - { - "name": "r", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "s", - "type": "bytes32", - "internalType": "bytes32" - } - ] - }, - { - "name": "eaProof", - "type": "bytes32[]", - "internalType": "bytes32[]" - }, - { - "name": "referrer", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "addNodeOperatorWstETH", - "inputs": [ - { - "name": "keysCount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "publicKeys", - "type": "bytes", - "internalType": "bytes" - }, - { - "name": "signatures", - "type": "bytes", - "internalType": "bytes" - }, - { - "name": "managementProperties", - "type": "tuple", - "internalType": "struct NodeOperatorManagementProperties", - "components": [ - { - "name": "managerAddress", - "type": "address", - "internalType": "address" - }, - { - "name": "rewardAddress", - "type": "address", - "internalType": "address" - }, - { - "name": "extendedManagerPermissions", - "type": "bool", - "internalType": "bool" - } - ] - }, - { - "name": "permit", - "type": "tuple", - "internalType": "struct ICSAccounting.PermitInput", - "components": [ - { - "name": "value", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "deadline", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "v", - "type": "uint8", - "internalType": "uint8" - }, - { - "name": "r", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "s", - "type": "bytes32", - "internalType": "bytes32" - } - ] - }, - { - "name": "eaProof", - "type": "bytes32[]", - "internalType": "bytes32[]" - }, - { - "name": "referrer", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "addValidatorKeysETH", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "keysCount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "publicKeys", - "type": "bytes", - "internalType": "bytes" - }, - { - "name": "signatures", - "type": "bytes", - "internalType": "bytes" - } - ], - "outputs": [], - "stateMutability": "payable" - }, - { - "type": "function", - "name": "addValidatorKeysStETH", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "keysCount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "publicKeys", - "type": "bytes", - "internalType": "bytes" - }, - { - "name": "signatures", - "type": "bytes", - "internalType": "bytes" - }, - { - "name": "permit", - "type": "tuple", - "internalType": "struct ICSAccounting.PermitInput", - "components": [ - { - "name": "value", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "deadline", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "v", - "type": "uint8", - "internalType": "uint8" - }, - { - "name": "r", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "s", - "type": "bytes32", - "internalType": "bytes32" - } - ] - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "addValidatorKeysWstETH", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "keysCount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "publicKeys", - "type": "bytes", - "internalType": "bytes" - }, - { - "name": "signatures", - "type": "bytes", - "internalType": "bytes" - }, - { - "name": "permit", - "type": "tuple", - "internalType": "struct ICSAccounting.PermitInput", - "components": [ - { - "name": "value", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "deadline", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "v", - "type": "uint8", - "internalType": "uint8" - }, - { - "name": "r", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "s", - "type": "bytes32", - "internalType": "bytes32" - } - ] - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "cancelELRewardsStealingPenalty", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "amount", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "changeNodeOperatorRewardAddress", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "newAddress", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "claimRewardsStETH", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "stETHAmount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "cumulativeFeeShares", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "rewardsProof", - "type": "bytes32[]", - "internalType": "bytes32[]" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "claimRewardsUnstETH", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "stEthAmount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "cumulativeFeeShares", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "rewardsProof", - "type": "bytes32[]", - "internalType": "bytes32[]" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "claimRewardsWstETH", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "wstETHAmount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "cumulativeFeeShares", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "rewardsProof", - "type": "bytes32[]", - "internalType": "bytes32[]" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "cleanDepositQueue", - "inputs": [ - { - "name": "maxItems", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "compensateELRewardsStealingPenalty", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "payable" - }, - { - "type": "function", - "name": "confirmNodeOperatorManagerAddressChange", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "confirmNodeOperatorRewardAddressChange", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "decreaseVettedSigningKeysCount", - "inputs": [ - { - "name": "nodeOperatorIds", - "type": "bytes", - "internalType": "bytes" - }, - { - "name": "vettedSigningKeysCounts", - "type": "bytes", - "internalType": "bytes" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "depositETH", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "payable" - }, - { - "type": "function", - "name": "depositQueue", - "inputs": [], - "outputs": [ - { - "name": "head", - "type": "uint128", - "internalType": "uint128" - }, - { - "name": "tail", - "type": "uint128", - "internalType": "uint128" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "depositQueueItem", - "inputs": [ - { - "name": "index", - "type": "uint128", - "internalType": "uint128" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "Batch" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "depositStETH", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "stETHAmount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "permit", - "type": "tuple", - "internalType": "struct ICSAccounting.PermitInput", - "components": [ - { - "name": "value", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "deadline", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "v", - "type": "uint8", - "internalType": "uint8" - }, - { - "name": "r", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "s", - "type": "bytes32", - "internalType": "bytes32" - } - ] - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "depositWstETH", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "wstETHAmount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "permit", - "type": "tuple", - "internalType": "struct ICSAccounting.PermitInput", - "components": [ - { - "name": "value", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "deadline", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "v", - "type": "uint8", - "internalType": "uint8" - }, - { - "name": "r", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "s", - "type": "bytes32", - "internalType": "bytes32" - } - ] - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "earlyAdoption", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address", - "internalType": "contract ICSEarlyAdoption" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getActiveNodeOperatorsCount", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getNodeOperator", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "tuple", - "internalType": "struct NodeOperator", - "components": [ - { - "name": "totalAddedKeys", - "type": "uint32", - "internalType": "uint32" - }, - { - "name": "totalWithdrawnKeys", - "type": "uint32", - "internalType": "uint32" - }, - { - "name": "totalDepositedKeys", - "type": "uint32", - "internalType": "uint32" - }, - { - "name": "totalVettedKeys", - "type": "uint32", - "internalType": "uint32" - }, - { - "name": "stuckValidatorsCount", - "type": "uint32", - "internalType": "uint32" - }, - { - "name": "depositableValidatorsCount", - "type": "uint32", - "internalType": "uint32" - }, - { - "name": "targetLimit", - "type": "uint32", - "internalType": "uint32" - }, - { - "name": "targetLimitMode", - "type": "uint8", - "internalType": "uint8" - }, - { - "name": "totalExitedKeys", - "type": "uint32", - "internalType": "uint32" - }, - { - "name": "enqueuedCount", - "type": "uint32", - "internalType": "uint32" - }, - { - "name": "managerAddress", - "type": "address", - "internalType": "address" - }, - { - "name": "proposedManagerAddress", - "type": "address", - "internalType": "address" - }, - { - "name": "rewardAddress", - "type": "address", - "internalType": "address" - }, - { - "name": "proposedRewardAddress", - "type": "address", - "internalType": "address" - }, - { - "name": "extendedManagerPermissions", - "type": "bool", - "internalType": "bool" - } - ] - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getNodeOperatorIds", - "inputs": [ - { - "name": "offset", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "limit", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "nodeOperatorIds", - "type": "uint256[]", - "internalType": "uint256[]" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getNodeOperatorIsActive", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "bool", - "internalType": "bool" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getNodeOperatorNonWithdrawnKeys", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getNodeOperatorSummary", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "targetLimitMode", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "targetValidatorsCount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "stuckValidatorsCount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "refundedValidatorsCount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "stuckPenaltyEndTimestamp", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "totalExitedValidators", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "totalDepositedValidators", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "depositableValidatorsCount", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getNodeOperatorsCount", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getNonce", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getResumeSinceTimestamp", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getRoleAdmin", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getRoleMember", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "index", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "address", - "internalType": "address" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getRoleMemberCount", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getSigningKeys", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "startIndex", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "keysCount", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "bytes", - "internalType": "bytes" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getSigningKeysWithSignatures", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "startIndex", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "keysCount", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "keys", - "type": "bytes", - "internalType": "bytes" - }, - { - "name": "signatures", - "type": "bytes", - "internalType": "bytes" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getStakingModuleSummary", - "inputs": [], - "outputs": [ - { - "name": "totalExitedValidators", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "totalDepositedValidators", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "depositableValidatorsCount", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getType", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "grantRole", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "account", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "hasRole", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "account", - "type": "address", - "internalType": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "bool", - "internalType": "bool" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "initialize", - "inputs": [ - { - "name": "_accounting", - "type": "address", - "internalType": "address" - }, - { - "name": "_earlyAdoption", - "type": "address", - "internalType": "address" - }, - { - "name": "_keyRemovalCharge", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "admin", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "isPaused", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bool", - "internalType": "bool" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "isValidatorSlashed", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "keyIndex", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "bool", - "internalType": "bool" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "isValidatorWithdrawn", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "keyIndex", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "bool", - "internalType": "bool" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "keyRemovalCharge", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "normalizeQueue", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "obtainDepositData", - "inputs": [ - { - "name": "depositsCount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "", - "type": "bytes", - "internalType": "bytes" - } - ], - "outputs": [ - { - "name": "publicKeys", - "type": "bytes", - "internalType": "bytes" - }, - { - "name": "signatures", - "type": "bytes", - "internalType": "bytes" - } - ], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "onExitedAndStuckValidatorsCountsUpdated", - "inputs": [], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "onRewardsMinted", - "inputs": [ - { - "name": "totalShares", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "onWithdrawalCredentialsChanged", - "inputs": [], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "pauseFor", - "inputs": [ - { - "name": "duration", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "proposeNodeOperatorManagerAddressChange", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "proposedAddress", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "proposeNodeOperatorRewardAddressChange", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "proposedAddress", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "publicRelease", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bool", - "internalType": "bool" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "recoverERC1155", - "inputs": [ - { - "name": "token", - "type": "address", - "internalType": "address" - }, - { - "name": "tokenId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "recoverERC20", - "inputs": [ - { - "name": "token", - "type": "address", - "internalType": "address" - }, - { - "name": "amount", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "recoverERC721", - "inputs": [ - { - "name": "token", - "type": "address", - "internalType": "address" - }, - { - "name": "tokenId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "recoverEther", - "inputs": [], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "recoverStETHShares", - "inputs": [], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "removeKeys", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "startIndex", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "keysCount", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "renounceRole", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "callerConfirmation", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "reportELRewardsStealingPenalty", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "blockHash", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "amount", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "resetNodeOperatorManagerAddress", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "resume", - "inputs": [], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "revokeRole", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "account", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "setKeyRemovalCharge", - "inputs": [ - { - "name": "amount", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "settleELRewardsStealingPenalty", - "inputs": [ - { - "name": "nodeOperatorIds", - "type": "uint256[]", - "internalType": "uint256[]" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "submitInitialSlashing", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "keyIndex", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "submitWithdrawal", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "keyIndex", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "amount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "isSlashed", - "type": "bool", - "internalType": "bool" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "supportsInterface", - "inputs": [ - { - "name": "interfaceId", - "type": "bytes4", - "internalType": "bytes4" - } - ], - "outputs": [ - { - "name": "", - "type": "bool", - "internalType": "bool" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "unsafeUpdateValidatorsCount", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "exitedValidatorsKeysCount", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "stuckValidatorsKeysCount", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "updateExitedValidatorsCount", - "inputs": [ - { - "name": "nodeOperatorIds", - "type": "bytes", - "internalType": "bytes" - }, - { - "name": "exitedValidatorsCounts", - "type": "bytes", - "internalType": "bytes" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "updateRefundedValidatorsCount", - "inputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "updateStuckValidatorsCount", - "inputs": [ - { - "name": "nodeOperatorIds", - "type": "bytes", - "internalType": "bytes" - }, - { - "name": "stuckValidatorsCounts", - "type": "bytes", - "internalType": "bytes" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "updateTargetValidatorsLimits", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "targetLimitMode", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "targetLimit", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "event", - "name": "BatchEnqueued", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "count", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "DepositableSigningKeysCountChanged", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "depositableKeysCount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "DepositedSigningKeysCountChanged", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "depositedKeysCount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ELRewardsStealingPenaltyCancelled", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "amount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ELRewardsStealingPenaltyReported", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "proposedBlockHash", - "type": "bytes32", - "indexed": false, - "internalType": "bytes32" - }, - { - "name": "stolenAmount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ELRewardsStealingPenaltySettled", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ERC1155Recovered", - "inputs": [ - { - "name": "token", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "tokenId", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - }, - { - "name": "recipient", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "amount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ERC20Recovered", - "inputs": [ - { - "name": "token", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "recipient", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "amount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ERC721Recovered", - "inputs": [ - { - "name": "token", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "tokenId", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - }, - { - "name": "recipient", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "EtherRecovered", - "inputs": [ - { - "name": "recipient", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "amount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ExitedSigningKeysCountChanged", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "exitedKeysCount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "InitialSlashingSubmitted", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "keyIndex", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "Initialized", - "inputs": [ - { - "name": "version", - "type": "uint64", - "indexed": false, - "internalType": "uint64" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "KeyRemovalChargeApplied", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "KeyRemovalChargeSet", - "inputs": [ - { - "name": "amount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "NodeOperatorAdded", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "managerAddress", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "rewardAddress", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "NodeOperatorManagerAddressChangeProposed", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "oldProposedAddress", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "newProposedAddress", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "NodeOperatorManagerAddressChanged", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "oldAddress", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "newAddress", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "NodeOperatorRewardAddressChangeProposed", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "oldProposedAddress", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "newProposedAddress", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "NodeOperatorRewardAddressChanged", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "oldAddress", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "newAddress", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "NonceChanged", - "inputs": [ - { - "name": "nonce", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "Paused", - "inputs": [ - { - "name": "duration", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "PublicRelease", - "inputs": [], - "anonymous": false - }, - { - "type": "event", - "name": "ReferrerSet", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "referrer", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "Resumed", - "inputs": [], - "anonymous": false - }, - { - "type": "event", - "name": "RoleAdminChanged", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - }, - { - "name": "previousAdminRole", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - }, - { - "name": "newAdminRole", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "RoleGranted", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - }, - { - "name": "account", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "sender", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "RoleRevoked", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - }, - { - "name": "account", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "sender", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "SigningKeyAdded", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "pubkey", - "type": "bytes", - "indexed": false, - "internalType": "bytes" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "SigningKeyRemoved", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "pubkey", - "type": "bytes", - "indexed": false, - "internalType": "bytes" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "StETHSharesRecovered", - "inputs": [ - { - "name": "recipient", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "shares", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "StuckSigningKeysCountChanged", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "stuckKeysCount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "TargetValidatorsCountChanged", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "targetLimitMode", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - }, - { - "name": "targetValidatorsCount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "TotalSigningKeysCountChanged", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "totalKeysCount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "VettedSigningKeysCountChanged", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "vettedKeysCount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "VettedSigningKeysCountDecreased", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "WithdrawalSubmitted", - "inputs": [ - { - "name": "nodeOperatorId", - "type": "uint256", - "indexed": true, - "internalType": "uint256" - }, - { - "name": "keyIndex", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - }, - { - "name": "amount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "error", - "name": "AccessControlBadConfirmation", - "inputs": [] - }, - { - "type": "error", - "name": "AccessControlUnauthorizedAccount", - "inputs": [ - { - "name": "account", - "type": "address", - "internalType": "address" - }, - { - "name": "neededRole", - "type": "bytes32", - "internalType": "bytes32" - } - ] - }, - { - "type": "error", - "name": "AlreadyActivated", - "inputs": [] - }, - { - "type": "error", - "name": "AlreadyProposed", - "inputs": [] - }, - { - "type": "error", - "name": "AlreadySubmitted", - "inputs": [] - }, - { - "type": "error", - "name": "AlreadyWithdrawn", - "inputs": [] - }, - { - "type": "error", - "name": "EmptyKey", - "inputs": [] - }, - { - "type": "error", - "name": "ExitedKeysDecrease", - "inputs": [] - }, - { - "type": "error", - "name": "ExitedKeysHigherThanTotalDeposited", - "inputs": [] - }, - { - "type": "error", - "name": "FailedToSendEther", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidAmount", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidInitialization", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidInput", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidKeysCount", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidLength", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidReportData", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidVetKeysPointer", - "inputs": [] - }, - { - "type": "error", - "name": "MaxSigningKeysCountExceeded", - "inputs": [] - }, - { - "type": "error", - "name": "MethodCallIsNotAllowed", - "inputs": [] - }, - { - "type": "error", - "name": "NodeOperatorDoesNotExist", - "inputs": [] - }, - { - "type": "error", - "name": "NotAllowedToJoinYet", - "inputs": [] - }, - { - "type": "error", - "name": "NotAllowedToRecover", - "inputs": [] - }, - { - "type": "error", - "name": "NotEnoughKeys", - "inputs": [] - }, - { - "type": "error", - "name": "NotInitializing", - "inputs": [] - }, - { - "type": "error", - "name": "NotSupported", - "inputs": [] - }, - { - "type": "error", - "name": "PauseUntilMustBeInFuture", - "inputs": [] - }, - { - "type": "error", - "name": "PausedExpected", - "inputs": [] - }, - { - "type": "error", - "name": "QueueIsEmpty", - "inputs": [] - }, - { - "type": "error", - "name": "QueueLookupNoLimit", - "inputs": [] - }, - { - "type": "error", - "name": "ResumedExpected", - "inputs": [] - }, - { - "type": "error", - "name": "SameAddress", - "inputs": [] - }, - { - "type": "error", - "name": "SenderIsNotEligible", - "inputs": [] - }, - { - "type": "error", - "name": "SenderIsNotManagerAddress", - "inputs": [] - }, - { - "type": "error", - "name": "SenderIsNotProposedAddress", - "inputs": [] - }, - { - "type": "error", - "name": "SenderIsNotRewardAddress", - "inputs": [] - }, - { - "type": "error", - "name": "SigningKeysInvalidOffset", - "inputs": [] - }, - { - "type": "error", - "name": "StuckKeysHigherThanNonExited", - "inputs": [] - }, - { - "type": "error", - "name": "ZeroAccountingAddress", - "inputs": [] - }, - { - "type": "error", - "name": "ZeroAdminAddress", - "inputs": [] - }, - { - "type": "error", - "name": "ZeroLocatorAddress", - "inputs": [] - }, - { - "type": "error", - "name": "ZeroPauseDuration", - "inputs": [] - } - ] diff --git a/utils/agent.py b/utils/agent.py index 88a7f48dc..9fc0ad270 100644 --- a/utils/agent.py +++ b/utils/agent.py @@ -1,10 +1,17 @@ -from utils.config import contracts, AGENT -from utils.evm_script import encode_call_script -from typing import Tuple, Sequence +from utils.config import network_name, contracts, AGENT +from utils.evm_script import ( + encode_call_script, +) +from typing import ( + Tuple, + Optional, + Sequence, +) def agent_forward(call_script: Sequence[Tuple[str, str]]) -> Tuple[str, str]: agent = contracts.agent + print(f"Forwarding call script to agent: {call_script}") return (AGENT, agent.forward.encode_input(encode_call_script(call_script))) diff --git a/utils/config.py b/utils/config.py index 8e36dc08a..a8877702b 100644 --- a/utils/config.py +++ b/utils/config.py @@ -99,9 +99,9 @@ def local_deployer() -> LocalAccount: def get_deployer_account() -> Union[LocalAccount, Account]: is_live = get_is_live() - deployer = os.environ.get("DEPLOYER") if is_live: + deployer = os.environ.get("DEPLOYER") if deployer is None: raise EnvironmentError("For live deployment please set DEPLOYER env variable to the deployer account name") return accounts.load(deployer) @@ -212,8 +212,17 @@ def csm(self) -> interface.CSModule: @property def cs_early_adoption(self) -> interface.CSEarlyAdoption: + """Deprecated""" return interface.CSEarlyAdoption(CS_EARLY_ADOPTION_ADDRESS) + @property + def cs_permissionless_gate(self) -> interface.CSPermissionlessGate: + return interface.CSPermissionlessGate(CS_PERMISSIONLESS_GATE_ADDRESS) + + @property + def cs_vetted_gate(self) -> interface.CSVettedGate: + return interface.CSVettedGate(CS_VETTED_GATE_ADDRESS) + @property def cs_accounting(self) -> interface.CSAccounting: return interface.CSAccounting(CS_ACCOUNTING_ADDRESS) @@ -234,6 +243,22 @@ def csm_hash_consensus(self) -> interface.CSHashConsensus: def cs_verifier(self) -> interface.CSVerifier: return interface.CSVerifier(CS_VERIFIER_ADDRESS) + @property + def cs_verifier_v2(self) -> interface.CSVerifierV2: + return interface.CSVerifierV2(CS_VERIFIER_V2_ADDRESS) + + @property + def cs_exit_penalties(self) -> interface.CSExitPenalties: + return interface.CSExitPenalties(CS_EXIT_PENALTIES) + + @property + def cs_ejector(self) -> interface.CSEjector: + return interface.CSEjector(CS_EJECTOR_ADDRESS) + + @property + def cs_strikes(self) -> interface.CSStrikes: + return interface.CSStrikes(CS_STRIKES_ADDRESS) + @property def sandbox(self) -> interface.SimpleDVT: return interface.Sandbox(SANDBOX) @@ -286,6 +311,10 @@ def validators_exit_bus_oracle(self) -> interface.ValidatorsExitBusOracle: def oracle_report_sanity_checker(self) -> interface.OracleReportSanityChecker: return interface.OracleReportSanityChecker(ORACLE_REPORT_SANITY_CHECKER) + @property + def triggerable_withdrawals_gateway(self): + return interface.TriggerableWithdrawalsGateway(TRIGGERABLE_WITHDRAWALS_GATEWAY) + @property def withdrawal_queue(self) -> interface.WithdrawalQueueERC721: return interface.WithdrawalQueueERC721(WITHDRAWAL_QUEUE) @@ -406,6 +435,10 @@ def trp_escrow_factory(self) -> interface.VestingEscrowFactory: def token_rate_notifier(self) -> interface.TokenRateNotifier: return interface.TokenRateNotifier(L1_TOKEN_RATE_NOTIFIER) + @property + def validator_exit_verifier(self) -> interface.ValidatorsExitBusOracle: + return interface.ValidatorExitVerifier(VALIDATOR_EXIT_VERIFIER) + @property def dual_governance(self) -> interface.DualGovernance: return interface.DualGovernance(DUAL_GOVERNANCE) diff --git a/utils/test/event_validators/dual_governance.py b/utils/test/event_validators/dual_governance.py index a6b84c833..11d2d5f44 100644 --- a/utils/test/event_validators/dual_governance.py +++ b/utils/test/event_validators/dual_governance.py @@ -8,8 +8,8 @@ def validate_dual_governance_submit_event( proposal_id: int, proposer: str, executor: str, - metadata: str, - proposal_calls: any, + metadata: str = None, + proposal_calls: any = None, emitted_by: list[str] = None, ) -> None: _events_chain = ["LogScriptCall", "ProposalSubmitted", "ProposalSubmitted"] @@ -21,20 +21,21 @@ def validate_dual_governance_submit_event( assert event["ProposalSubmitted"][0]["id"] == proposal_id, "Wrong proposalId" assert event["ProposalSubmitted"][0]["executor"] == executor, "Wrong executor" - assert len(event["ProposalSubmitted"][0]["calls"]) == len(proposal_calls), "Wrong callsCount" - - for i in range(0, len(proposal_calls)): - assert event["ProposalSubmitted"][0]["calls"][i][0] == proposal_calls[i]["target"], "Wrong target" - assert event["ProposalSubmitted"][0]["calls"][i][1] == proposal_calls[i]["value"], "Wrong value" - assert event["ProposalSubmitted"][0]["calls"][i][2] == proposal_calls[i]["data"], "Wrong data" + if proposal_calls: + assert len(event["ProposalSubmitted"][0]["calls"]) == len(proposal_calls), "Wrong callsCount" + for i in range(0, len(proposal_calls)): + assert event["ProposalSubmitted"][0]["calls"][i][0] == proposal_calls[i]["target"], "Wrong target" + assert event["ProposalSubmitted"][0]["calls"][i][1] == proposal_calls[i]["value"], "Wrong value" + assert event["ProposalSubmitted"][0]["calls"][i][2] == proposal_calls[i]["data"], "Wrong data" assert event["ProposalSubmitted"][1]["proposalId"] == proposal_id, "Wrong proposalId" assert event["ProposalSubmitted"][1]["proposerAccount"] == proposer, "Wrong proposer" - assert event["ProposalSubmitted"][1]["metadata"] == metadata, "Wrong metadata" - assert len(event["ProposalSubmitted"]) == len(emitted_by), "Wrong emitted_by count" + if metadata: + assert event["ProposalSubmitted"][1]["metadata"] == metadata, "Wrong metadata" if emitted_by is not None: + assert len(event["ProposalSubmitted"]) == len(emitted_by), "Wrong emitted_by count" for i in range(0, len(emitted_by)): assert convert.to_address(event["ProposalSubmitted"][i]["_emitted_by"]) == convert.to_address( emitted_by[i] From ffe2c210fa3a2bc6834296b5552068e757ff4713 Mon Sep 17 00:00:00 2001 From: hweawer Date: Thu, 7 Aug 2025 15:23:17 +0200 Subject: [PATCH 02/28] Vote for exit hashes --- archive/scripts/vote_hoodi_exit_hashes.py | 82 ++++++++++++ archive/tests/test_vote_hoodi_exit_hashes.py | 128 +++++++++++++++++++ 2 files changed, 210 insertions(+) create mode 100644 archive/scripts/vote_hoodi_exit_hashes.py create mode 100644 archive/tests/test_vote_hoodi_exit_hashes.py diff --git a/archive/scripts/vote_hoodi_exit_hashes.py b/archive/scripts/vote_hoodi_exit_hashes.py new file mode 100644 index 000000000..2ef6d5098 --- /dev/null +++ b/archive/scripts/vote_hoodi_exit_hashes.py @@ -0,0 +1,82 @@ +""" +Vote [DATE] - Grant and Revoke SUBMIT_REPORT_HASH_ROLE for ValidatorsExitBus Oracle + +1. Grant SUBMIT_REPORT_HASH_ROLE to the agent +2. Perform oracle operations with predefined data +3. Revoke SUBMIT_REPORT_HASH_ROLE from the agent + +Vote passed & executed on [DATE], block [BLOCK_NUMBER] +""" + +import time +from typing import Dict, Tuple, Optional +from brownie import interface +from brownie.network.transaction import TransactionReceipt +from utils.config import contracts + +from utils.voting import confirm_vote_script, create_vote +from utils.evm_script import encode_call_script +from utils.config import get_deployer_account, get_is_live, get_priority_fee +from utils.agent import agent_forward +from utils.permissions import encode_oz_grant_role, encode_oz_revoke_role + +EXIT_HASH_TO_SUBMIT = "0x4e72449ac50f5fa83bc2d642f2c95a63f72f1b87ad292f52c0fe5c28f3cf6e47" +VOTE_DESCRIPTION = "Grant and revoke SUBMIT_REPORT_HASH_ROLE for ValidatorsExitBus Oracle operations on Hoodi" + +def start_vote(tx_params: Dict[str, str], silent: bool = False) -> Tuple[int, Optional[TransactionReceipt]]: + """Prepare and run voting.""" + + # Grant SUBMIT_REPORT_HASH_ROLE to agent, perform operations, then revoke + validators_exit_bus = interface.ValidatorsExitBus(contracts.validators_exit_bus_oracle) + calldata = validators_exit_bus.submitExitRequestsHash.encode_input(EXIT_HASH_TO_SUBMIT) + + + call_script_items = [ + # 1. Grant SUBMIT_REPORT_HASH_ROLE to the agent + agent_forward([ + encode_oz_grant_role( + contract=validators_exit_bus, + role_name="SUBMIT_REPORT_HASH_ROLE", + grant_to=contracts.agent + ) + ]), + + # 2. Perform your contract calls with predefined data + # Choose one of the two options below: + + # Option A: Use predefined calldata (if you already have the encoded function call) + agent_forward([ + (contracts.validators_exit_bus_oracle.address, calldata) + ]), + + # 3. Revoke SUBMIT_REPORT_HASH_ROLE from the agent + agent_forward([ + encode_oz_revoke_role( + contract=validators_exit_bus, + role_name="SUBMIT_REPORT_HASH_ROLE", + revoke_from=contracts.agent + ) + ]) + ] + + encoded_call_script = encode_call_script(call_script_items) + + return confirm_vote_script(encoded_call_script, silent) and create_vote( + vote_desc=VOTE_DESCRIPTION, + evm_script=encoded_call_script, + tx_params=tx_params + ) + +def main(): + tx_params = {"from": get_deployer_account()} + if get_is_live(): + tx_params["priority_fee"] = get_priority_fee() + + vote_id, _ = start_vote(tx_params=tx_params, silent=False) + + vote_id >= 0 and print(f"Vote created: {vote_id}.") + + time.sleep(5) # hack for waiting thread #2. + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/archive/tests/test_vote_hoodi_exit_hashes.py b/archive/tests/test_vote_hoodi_exit_hashes.py new file mode 100644 index 000000000..b4a0811df --- /dev/null +++ b/archive/tests/test_vote_hoodi_exit_hashes.py @@ -0,0 +1,128 @@ +from typing import Optional +from scripts.vote_hoodi_exit_hashes import start_vote, EXIT_HASH_TO_SUBMIT +from brownie import interface, chain, convert, web3 # type: ignore +from brownie.network.event import EventDict +from utils.test.tx_tracing_helpers import group_voting_events_from_receipt, group_dg_events_from_receipt +from utils.test.event_validators.dual_governance import validate_dual_governance_submit_event +from utils.dual_governance import wait_for_noon_utc_to_satisfy_time_constrains +from utils.config import ( + DUAL_GOVERNANCE, + TIMELOCK, + DUAL_GOVERNANCE_EXECUTORS, + LDO_HOLDER_ADDRESS_FOR_TESTS, + AGENT, + VOTING, + contracts, +) + + +def validate_role_grant_event(event: EventDict, role_hash: str, account: str, emitted_by: Optional[str] = None): + """Validates an OpenZeppelin AccessControl role grant event""" + assert "RoleGranted" in event, "No RoleGranted event found" + assert event["RoleGranted"][0]["role"] == role_hash, f"Wrong role hash. Expected: {role_hash}, Got: {event['RoleGranted'][0]['role']}" + assert event["RoleGranted"][0]["account"] == convert.to_address(account), f"Wrong account. Expected: {account}, Got: {event['RoleGranted'][0]['account']}" + + if emitted_by is not None: + assert convert.to_address(event["RoleGranted"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + + +def validate_role_revoke_event(event: EventDict, role_hash: str, account: str, emitted_by: Optional[str] = None): + """Validates an OpenZeppelin AccessControl role revoke event""" + assert "RoleRevoked" in event, "No RoleRevoked event found" + assert event["RoleRevoked"][0]["role"] == role_hash, f"Wrong role hash. Expected: {role_hash}, Got: {event['RoleRevoked'][0]['role']}" + assert event["RoleRevoked"][0]["account"] == convert.to_address(account), f"Wrong account. Expected: {account}, Got: {event['RoleRevoked'][0]['account']}" + + if emitted_by is not None: + assert convert.to_address(event["RoleRevoked"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + + +def validate_submit_exit_requests_hash_event(event: EventDict, expected_hash: str, emitted_by: Optional[str] = None): + """Validates RequestsHashSubmitted event from ValidatorsExitBus""" + assert "RequestsHashSubmitted" in event, "No RequestsHashSubmitted event found" + assert event["RequestsHashSubmitted"][0]["exitRequestsHash"] == expected_hash, f"Wrong hash. Expected: {expected_hash}, Got: {event['RequestsHashSubmitted'][0]['exitRequestsHash']}" + + if emitted_by is not None: + assert convert.to_address(event["RequestsHashSubmitted"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + + +def test_vote_hoodi_exit_hashes(helpers, accounts, vote_ids_from_env, stranger): + """Test the vote that grants SUBMIT_REPORT_HASH_ROLE temporarily to agent, uses it, then revokes it""" + + # Calculate the role hash for SUBMIT_REPORT_HASH_ROLE + SUBMIT_REPORT_HASH_ROLE = web3.keccak(text="SUBMIT_REPORT_HASH_ROLE") + + # Get contracts + validators_exit_bus = interface.ValidatorsExitBus(contracts.validators_exit_bus_oracle) + timelock = interface.EmergencyProtectedTimelock(TIMELOCK) + dual_governance = interface.DualGovernance(DUAL_GOVERNANCE) + + # Check initial state - agent should not have the role + assert not validators_exit_bus.hasRole(SUBMIT_REPORT_HASH_ROLE, AGENT), "Agent should not have SUBMIT_REPORT_HASH_ROLE before vote" + + # START VOTE + if len(vote_ids_from_env) > 0: + (vote_id,) = vote_ids_from_env + else: + tx_params = {"from": LDO_HOLDER_ADDRESS_FOR_TESTS} + vote_id, _ = start_vote(tx_params, silent=True) + + vote_tx = helpers.execute_vote(accounts, vote_id, contracts.voting) + print(f"voteId = {vote_id}") + + proposal_id = vote_tx.events["ProposalSubmitted"][1]["proposalId"] + print(f"proposalId = {proposal_id}") + + chain.sleep(timelock.getAfterSubmitDelay() + 1) + dual_governance.scheduleProposal(proposal_id, {"from": stranger}) + + chain.sleep(timelock.getAfterScheduleDelay() + 1) + wait_for_noon_utc_to_satisfy_time_constrains() + + dg_tx = timelock.execute(proposal_id, {"from": stranger}) + + # --- VALIDATE EXECUTION RESULTS --- + + # 1. Verify SUBMIT_REPORT_HASH_ROLE was granted and then revoked (final state is revoked) + assert not validators_exit_bus.hasRole(SUBMIT_REPORT_HASH_ROLE, AGENT), "Agent should not have SUBMIT_REPORT_HASH_ROLE after vote" + + # --- VALIDATE EVENTS --- + voting_events = group_voting_events_from_receipt(vote_tx) + assert len(voting_events) >= 1, "No voting events found" + + validate_dual_governance_submit_event( + voting_events[0], + proposal_id, + proposer=VOTING, + executor=DUAL_GOVERNANCE_EXECUTORS[0], + ) + + dg_execution_events = group_dg_events_from_receipt(dg_tx, timelock=TIMELOCK, admin_executor=DUAL_GOVERNANCE_EXECUTORS[0]) + assert len(dg_execution_events) == 3, f"Expected 3 dual governance events, got {len(dg_execution_events)}" + + # 0. Grant SUBMIT_REPORT_HASH_ROLE to agent + validate_role_grant_event( + dg_execution_events[0], + role_hash=SUBMIT_REPORT_HASH_ROLE.hex(), + account=AGENT, + emitted_by=contracts.validators_exit_bus_oracle + ) + + # 1. Submit exit requests hash + validate_submit_exit_requests_hash_event( + dg_execution_events[1], + expected_hash=EXIT_HASH_TO_SUBMIT, + emitted_by=contracts.validators_exit_bus_oracle + ) + + # 2. Revoke SUBMIT_REPORT_HASH_ROLE from agent + validate_role_revoke_event( + dg_execution_events[2], + role_hash=SUBMIT_REPORT_HASH_ROLE.hex(), + account=AGENT, + emitted_by=contracts.validators_exit_bus_oracle + ) + + print("✅ Vote executed successfully:") + print(f" - SUBMIT_REPORT_HASH_ROLE granted and revoked to/from agent") + print(f" - Exit hash {EXIT_HASH_TO_SUBMIT} submitted") + print(f" - All events validated correctly") \ No newline at end of file From 8794b7d465d3d79fa775e7566ebab2a3d2f421e4 Mon Sep 17 00:00:00 2001 From: Nikita P Date: Thu, 7 Aug 2025 16:41:21 +0300 Subject: [PATCH 03/28] Update test_permissions.py --- tests/regression/test_permissions.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/regression/test_permissions.py b/tests/regression/test_permissions.py index d6eef14ff..f6e343dae 100644 --- a/tests/regression/test_permissions.py +++ b/tests/regression/test_permissions.py @@ -538,19 +538,28 @@ def get_http_w3_provider_url(): assert False, 'Web3 HTTP Provider token env var not found' +def get_max_log_range(): + if os.getenv("MAX_GET_LOGS_RANGE") is not None: + return int(os.getenv("MAX_GET_LOGS_RANGE")) + return 100000 + def active_aragon_roles(protocol_permissions): local_rpc_provider = web3 remote_rpc_provider = Web3(Web3.HTTPProvider(get_http_w3_provider_url())) + max_range = get_max_log_range() event_signature_hash = remote_rpc_provider.keccak(text="SetPermission(address,address,bytes32,bool)").hex() - def fetch_events_in_batches(start_block, end_block, provider=local_rpc_provider, step=100000): + def fetch_events_in_batches(start_block, end_block, provider=local_rpc_provider, step=max_range): """Fetch events in batches of `step` blocks with a progress bar.""" events = [] total_batches = (end_block - start_block) // step + 1 with tqdm(total=total_batches, desc="Fetching Events") as pbar: for batch_start in range(start_block, end_block, step): batch_end = min(batch_start + step - 1, end_block) + print(total_batches) + print(batch_start) + print(batch_end) batch_events = provider.eth.filter( {"address": contracts.acl.address, "fromBlock": batch_start, "toBlock": batch_end, "topics": [event_signature_hash]} ).get_all_entries() From ee20e347c842bd9c471445f54826a606ae4afd85 Mon Sep 17 00:00:00 2001 From: Nikita P Date: Thu, 7 Aug 2025 16:44:40 +0300 Subject: [PATCH 04/28] Update test_permissions.py --- tests/regression/test_permissions.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/regression/test_permissions.py b/tests/regression/test_permissions.py index f6e343dae..b36977bd2 100644 --- a/tests/regression/test_permissions.py +++ b/tests/regression/test_permissions.py @@ -557,9 +557,6 @@ def fetch_events_in_batches(start_block, end_block, provider=local_rpc_provider, with tqdm(total=total_batches, desc="Fetching Events") as pbar: for batch_start in range(start_block, end_block, step): batch_end = min(batch_start + step - 1, end_block) - print(total_batches) - print(batch_start) - print(batch_end) batch_events = provider.eth.filter( {"address": contracts.acl.address, "fromBlock": batch_start, "toBlock": batch_end, "topics": [event_signature_hash]} ).get_all_entries() From 9d2dac46a7adf147a61acc427495149c2b0beba6 Mon Sep 17 00:00:00 2001 From: hweawer Date: Fri, 8 Aug 2025 11:42:49 +0200 Subject: [PATCH 05/28] Changes --- archive/scripts/vote_hoodi_exit_hashes.py | 4 ++-- archive/tests/test_vote_hoodi_exit_hashes.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/archive/scripts/vote_hoodi_exit_hashes.py b/archive/scripts/vote_hoodi_exit_hashes.py index 2ef6d5098..fe77d101c 100644 --- a/archive/scripts/vote_hoodi_exit_hashes.py +++ b/archive/scripts/vote_hoodi_exit_hashes.py @@ -21,13 +21,13 @@ from utils.permissions import encode_oz_grant_role, encode_oz_revoke_role EXIT_HASH_TO_SUBMIT = "0x4e72449ac50f5fa83bc2d642f2c95a63f72f1b87ad292f52c0fe5c28f3cf6e47" -VOTE_DESCRIPTION = "Grant and revoke SUBMIT_REPORT_HASH_ROLE for ValidatorsExitBus Oracle operations on Hoodi" +VOTE_DESCRIPTION = "Grant and revoke SUBMIT_DATA_ROLE for ValidatorsExitBus Oracle operations on Hoodi" def start_vote(tx_params: Dict[str, str], silent: bool = False) -> Tuple[int, Optional[TransactionReceipt]]: """Prepare and run voting.""" # Grant SUBMIT_REPORT_HASH_ROLE to agent, perform operations, then revoke - validators_exit_bus = interface.ValidatorsExitBus(contracts.validators_exit_bus_oracle) + validators_exit_bus = interface.ValidatorsExitBusOracle(contracts.validators_exit_bus_oracle) calldata = validators_exit_bus.submitExitRequestsHash.encode_input(EXIT_HASH_TO_SUBMIT) diff --git a/archive/tests/test_vote_hoodi_exit_hashes.py b/archive/tests/test_vote_hoodi_exit_hashes.py index b4a0811df..f4017a883 100644 --- a/archive/tests/test_vote_hoodi_exit_hashes.py +++ b/archive/tests/test_vote_hoodi_exit_hashes.py @@ -1,5 +1,5 @@ from typing import Optional -from scripts.vote_hoodi_exit_hashes import start_vote, EXIT_HASH_TO_SUBMIT +from archive.scripts.vote_hoodi_exit_hashes import start_vote, EXIT_HASH_TO_SUBMIT from brownie import interface, chain, convert, web3 # type: ignore from brownie.network.event import EventDict from utils.test.tx_tracing_helpers import group_voting_events_from_receipt, group_dg_events_from_receipt @@ -52,7 +52,7 @@ def test_vote_hoodi_exit_hashes(helpers, accounts, vote_ids_from_env, stranger): SUBMIT_REPORT_HASH_ROLE = web3.keccak(text="SUBMIT_REPORT_HASH_ROLE") # Get contracts - validators_exit_bus = interface.ValidatorsExitBus(contracts.validators_exit_bus_oracle) + validators_exit_bus = interface.ValidatorsExitBusOracle(contracts.validators_exit_bus_oracle) timelock = interface.EmergencyProtectedTimelock(TIMELOCK) dual_governance = interface.DualGovernance(DUAL_GOVERNANCE) From 44e93ca7d7d1860f4c7ddf628bfe78c51cefde3f Mon Sep 17 00:00:00 2001 From: hweawer Date: Fri, 8 Aug 2025 13:05:09 +0200 Subject: [PATCH 06/28] Update --- .../vote_hoodi_exit_hashes.py | 89 ++++++++++--------- .../test_vote_hoodi_exit_hashes.py | 2 +- 2 files changed, 50 insertions(+), 41 deletions(-) rename {archive/scripts => scripts}/vote_hoodi_exit_hashes.py (51%) rename {archive/tests => tests}/test_vote_hoodi_exit_hashes.py (98%) diff --git a/archive/scripts/vote_hoodi_exit_hashes.py b/scripts/vote_hoodi_exit_hashes.py similarity index 51% rename from archive/scripts/vote_hoodi_exit_hashes.py rename to scripts/vote_hoodi_exit_hashes.py index fe77d101c..5a22efbfb 100644 --- a/archive/scripts/vote_hoodi_exit_hashes.py +++ b/scripts/vote_hoodi_exit_hashes.py @@ -8,6 +8,8 @@ Vote passed & executed on [DATE], block [BLOCK_NUMBER] """ +DESCRIPTION = "Update Sandbox Module Implementation (HOODI)" + import time from typing import Dict, Tuple, Optional from brownie import interface @@ -16,67 +18,74 @@ from utils.voting import confirm_vote_script, create_vote from utils.evm_script import encode_call_script +from archive.scripts.vote_tw_csm2_hoodi import prepare_proposal from utils.config import get_deployer_account, get_is_live, get_priority_fee from utils.agent import agent_forward +from utils.ipfs import upload_vote_ipfs_description, calculate_vote_ipfs_description +from utils.voting import confirm_vote_script, create_vote from utils.permissions import encode_oz_grant_role, encode_oz_revoke_role EXIT_HASH_TO_SUBMIT = "0x4e72449ac50f5fa83bc2d642f2c95a63f72f1b87ad292f52c0fe5c28f3cf6e47" VOTE_DESCRIPTION = "Grant and revoke SUBMIT_DATA_ROLE for ValidatorsExitBus Oracle operations on Hoodi" + def start_vote(tx_params: Dict[str, str], silent: bool = False) -> Tuple[int, Optional[TransactionReceipt]]: """Prepare and run voting.""" - + # Grant SUBMIT_REPORT_HASH_ROLE to agent, perform operations, then revoke validators_exit_bus = interface.ValidatorsExitBusOracle(contracts.validators_exit_bus_oracle) calldata = validators_exit_bus.submitExitRequestsHash.encode_input(EXIT_HASH_TO_SUBMIT) - - call_script_items = [ - # 1. Grant SUBMIT_REPORT_HASH_ROLE to the agent - agent_forward([ - encode_oz_grant_role( - contract=validators_exit_bus, - role_name="SUBMIT_REPORT_HASH_ROLE", - grant_to=contracts.agent - ) - ]), - - # 2. Perform your contract calls with predefined data - # Choose one of the two options below: - - # Option A: Use predefined calldata (if you already have the encoded function call) - agent_forward([ - (contracts.validators_exit_bus_oracle.address, calldata) - ]), - - # 3. Revoke SUBMIT_REPORT_HASH_ROLE from the agent - agent_forward([ - encode_oz_revoke_role( - contract=validators_exit_bus, - role_name="SUBMIT_REPORT_HASH_ROLE", - revoke_from=contracts.agent - ) - ]) - ] - - encoded_call_script = encode_call_script(call_script_items) - - return confirm_vote_script(encoded_call_script, silent) and create_vote( - vote_desc=VOTE_DESCRIPTION, - evm_script=encoded_call_script, - tx_params=tx_params + vote_desc_items, call_script_items = zip( + ( + "1. Grant SUBMIT_REPORT_HASH_ROLE to the agent", + agent_forward( + [ + encode_oz_grant_role( + contract=validators_exit_bus, role_name="SUBMIT_REPORT_HASH_ROLE", grant_to=contracts.agent + ) + ] + ), + ), + ( + "2. Perform your contract calls with predefined data", + agent_forward([(contracts.validators_exit_bus_oracle.address, calldata)]), + ), + ( + "3. Revoke SUBMIT_REPORT_HASH_ROLE from the agent", + agent_forward( + [ + encode_oz_revoke_role( + contract=validators_exit_bus, role_name="SUBMIT_REPORT_HASH_ROLE", revoke_from=contracts.agent + ) + ] + ), + ), ) + if silent: + desc_ipfs = calculate_vote_ipfs_description(DESCRIPTION) + else: + desc_ipfs = upload_vote_ipfs_description(DESCRIPTION) + + dg_desc = "\n".join(vote_desc_items) + dg_vote = prepare_proposal(call_script_items, dg_desc) + vote_items = {dg_desc: dg_vote} + + return confirm_vote_script(vote_items, silent, desc_ipfs) and create_vote(vote_items, tx_params, desc_ipfs=desc_ipfs) + + def main(): tx_params = {"from": get_deployer_account()} if get_is_live(): tx_params["priority_fee"] = get_priority_fee() - + vote_id, _ = start_vote(tx_params=tx_params, silent=False) - + vote_id >= 0 and print(f"Vote created: {vote_id}.") - + time.sleep(5) # hack for waiting thread #2. + if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/archive/tests/test_vote_hoodi_exit_hashes.py b/tests/test_vote_hoodi_exit_hashes.py similarity index 98% rename from archive/tests/test_vote_hoodi_exit_hashes.py rename to tests/test_vote_hoodi_exit_hashes.py index f4017a883..470985518 100644 --- a/archive/tests/test_vote_hoodi_exit_hashes.py +++ b/tests/test_vote_hoodi_exit_hashes.py @@ -1,5 +1,5 @@ from typing import Optional -from archive.scripts.vote_hoodi_exit_hashes import start_vote, EXIT_HASH_TO_SUBMIT +from scripts.vote_hoodi_exit_hashes import start_vote, EXIT_HASH_TO_SUBMIT from brownie import interface, chain, convert, web3 # type: ignore from brownie.network.event import EventDict from utils.test.tx_tracing_helpers import group_voting_events_from_receipt, group_dg_events_from_receipt From 99599eb34847388eb7dc1a195471b78858ad4842 Mon Sep 17 00:00:00 2001 From: hweawer Date: Fri, 8 Aug 2025 13:19:34 +0200 Subject: [PATCH 07/28] Revert --- tests/regression/test_permissions.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/tests/regression/test_permissions.py b/tests/regression/test_permissions.py index b36977bd2..d6eef14ff 100644 --- a/tests/regression/test_permissions.py +++ b/tests/regression/test_permissions.py @@ -538,19 +538,13 @@ def get_http_w3_provider_url(): assert False, 'Web3 HTTP Provider token env var not found' -def get_max_log_range(): - if os.getenv("MAX_GET_LOGS_RANGE") is not None: - return int(os.getenv("MAX_GET_LOGS_RANGE")) - return 100000 - def active_aragon_roles(protocol_permissions): local_rpc_provider = web3 remote_rpc_provider = Web3(Web3.HTTPProvider(get_http_w3_provider_url())) - max_range = get_max_log_range() event_signature_hash = remote_rpc_provider.keccak(text="SetPermission(address,address,bytes32,bool)").hex() - def fetch_events_in_batches(start_block, end_block, provider=local_rpc_provider, step=max_range): + def fetch_events_in_batches(start_block, end_block, provider=local_rpc_provider, step=100000): """Fetch events in batches of `step` blocks with a progress bar.""" events = [] total_batches = (end_block - start_block) // step + 1 From 6c9f306bf1116cd6168db425453a88eac1b67561 Mon Sep 17 00:00:00 2001 From: hweawer Date: Fri, 8 Aug 2025 13:28:36 +0200 Subject: [PATCH 08/28] Update --- scripts/vote_hoodi_exit_hashes.py | 43 ++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/scripts/vote_hoodi_exit_hashes.py b/scripts/vote_hoodi_exit_hashes.py index 5a22efbfb..d6d4f06f1 100644 --- a/scripts/vote_hoodi_exit_hashes.py +++ b/scripts/vote_hoodi_exit_hashes.py @@ -12,8 +12,13 @@ import time from typing import Dict, Tuple, Optional -from brownie import interface +from brownie import interface, web3, convert from brownie.network.transaction import TransactionReceipt + +from utils.config import ( + ARAGON_KERNEL, + AGENT, +) from utils.config import contracts from utils.voting import confirm_vote_script, create_vote @@ -26,7 +31,7 @@ from utils.permissions import encode_oz_grant_role, encode_oz_revoke_role EXIT_HASH_TO_SUBMIT = "0x4e72449ac50f5fa83bc2d642f2c95a63f72f1b87ad292f52c0fe5c28f3cf6e47" -VOTE_DESCRIPTION = "Grant and revoke SUBMIT_DATA_ROLE for ValidatorsExitBus Oracle operations on Hoodi" +VOTE_DESCRIPTION = "Run ValidatorsExitBus Oracle submitExitRequestsHash on Hoodi" def start_vote(tx_params: Dict[str, str], silent: bool = False) -> Tuple[int, Optional[TransactionReceipt]]: @@ -38,7 +43,20 @@ def start_vote(tx_params: Dict[str, str], silent: bool = False) -> Tuple[int, Op vote_desc_items, call_script_items = zip( ( - "1. Grant SUBMIT_REPORT_HASH_ROLE to the agent", + f"1. Grant APP_MANAGER_ROLE role to the AGENT", + agent_forward( + [ + ( + contracts.acl.address, + contracts.acl.grantPermission.encode_input( + AGENT, ARAGON_KERNEL, convert.to_uint(web3.keccak(text="APP_MANAGER_ROLE")) + ), + ) + ] + ), + ), + ( + "2. Grant SUBMIT_REPORT_HASH_ROLE to the agent", agent_forward( [ encode_oz_grant_role( @@ -48,11 +66,11 @@ def start_vote(tx_params: Dict[str, str], silent: bool = False) -> Tuple[int, Op ), ), ( - "2. Perform your contract calls with predefined data", + "3. Perform your contract calls with predefined data", agent_forward([(contracts.validators_exit_bus_oracle.address, calldata)]), ), ( - "3. Revoke SUBMIT_REPORT_HASH_ROLE from the agent", + "4. Revoke SUBMIT_REPORT_HASH_ROLE from the agent", agent_forward( [ encode_oz_revoke_role( @@ -61,6 +79,17 @@ def start_vote(tx_params: Dict[str, str], silent: bool = False) -> Tuple[int, Op ] ), ), + ( + f"5. Revoke APP_MANAGER_ROLE role from the AGENT", + agent_forward([( + contracts.acl.address, + contracts.acl.revokePermission.encode_input( + AGENT, + ARAGON_KERNEL, + convert.to_uint(web3.keccak(text="APP_MANAGER_ROLE")) + ) + )]), + ), ) if silent: @@ -72,7 +101,9 @@ def start_vote(tx_params: Dict[str, str], silent: bool = False) -> Tuple[int, Op dg_vote = prepare_proposal(call_script_items, dg_desc) vote_items = {dg_desc: dg_vote} - return confirm_vote_script(vote_items, silent, desc_ipfs) and create_vote(vote_items, tx_params, desc_ipfs=desc_ipfs) + return confirm_vote_script(vote_items, silent, desc_ipfs) and create_vote( + vote_items, tx_params, desc_ipfs=desc_ipfs + ) def main(): From 1895debd4d2dc78ae4004fa5cf26171a401543c9 Mon Sep 17 00:00:00 2001 From: Eddort Date: Fri, 8 Aug 2025 16:47:23 +0200 Subject: [PATCH 09/28] wip: initial voting scripts --- scripts/vote_tw_csm2_mainnet.py | 901 +++++++++++++++++++++++ tests/test_vote_tw_csm2_mainnet.py | 1062 ++++++++++++++++++++++++++++ 2 files changed, 1963 insertions(+) create mode 100644 scripts/vote_tw_csm2_mainnet.py create mode 100644 tests/test_vote_tw_csm2_mainnet.py diff --git a/scripts/vote_tw_csm2_mainnet.py b/scripts/vote_tw_csm2_mainnet.py new file mode 100644 index 000000000..9e7e28dc8 --- /dev/null +++ b/scripts/vote_tw_csm2_mainnet.py @@ -0,0 +1,901 @@ +""" +Vote 23/09/2025 [MAINNET] + +--- Locator +1. Update locator implementation +--- VEB +2. Update VEBO implementation +3. Call finalizeUpgrade_v2(maxValidatorsPerReport, maxExitRequestsLimit, exitsPerFrame, frameDurationInSec) on VEBO +4. Grant VEBO role MANAGE_CONSENSUS_VERSION_ROLE to the AGENT +5. Bump VEBO consensus version to `4` +6. Revoke VEBO role MANAGE_CONSENSUS_VERSION_ROLE from the AGENT +7. Grant SUBMIT_REPORT_HASH_ROLE on Validator Exit Bus Oracle to the EasyTrack EVM Script Executor +--- Triggerable Withdrawals Gateway (TWG) +8. Grant TWG role ADD_FULL_WITHDRAWAL_REQUEST_ROLE to the CS Ejector +9. Grant TWG role ADD_FULL_WITHDRAWAL_REQUEST_ROLE to the VEB +10. Connect TRIGGERABLE_WITHDRAWALS_GATEWAY to Dual Governance tiebreaker +--- WV +11. Update WithdrawalVault implementation +12. Call finalizeUpgrade_v2() on WithdrawalVault +--- AO +13. Update Accounting Oracle implementation +14. Grant AO MANAGE_CONSENSUS_VERSION_ROLE to the AGENT +15. Bump AO consensus version to `4` +16. Revoke AO MANAGE_CONSENSUS_VERSION_ROLE from the AGENT +17. Call finalizeUpgrade_v3() on AO +--- SR +18. Update SR implementation +19. Call finalizeUpgrade_v3() on SR +20. Grant SR role REPORT_VALIDATOR_EXITING_STATUS_ROLE to ValidatorExitVerifier +21. Grant SR role REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE to TWG +--- Curated Staking Module +22. Grant APP_MANAGER_ROLE role to the AGENT on Kernel +23. Update `NodeOperatorsRegistry` implementation +24. Call finalizeUpgrade_v4 on Curated Staking Module +--- sDVT +25. Update `SimpleDVT` implementation +26. Call finalizeUpgrade_v4 on sDVT +27. Revoke APP_MANAGER_ROLE role from the AGENT on Kernel +--- Oracle configs --- +28. Grant CONFIG_MANAGER_ROLE role to the AGENT +29. Remove NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP variable from OracleDaemonConfig +30. Remove VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS variable from OracleDaemonConfig +31. Remove VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS variable from OracleDaemonConfig +32. Add EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS variable to OracleDaemonConfig +33. Revoke CONFIG_MANAGER_ROLE role from the AGENT +--- CSM --- +34. Upgrade CSM implementation on proxy +35. Call `finalizeUpgradeV2()` on CSM contract +36. Upgrade CSAccounting implementation on proxy +37. Call `finalizeUpgradeV2(bondCurves)` on CSAccounting contract +38. Upgrade CSFeeOracle implementation on proxy +39. Call `finalizeUpgradeV2(consensusVersion)` on CSFeeOracle contract +40. Upgrade CSFeeDistributor implementation on proxy +41. Call `finalizeUpgradeV2(admin)` on CSFeeDistributor contract +42. Revoke CSAccounting role SET_BOND_CURVE_ROLE from the CSM contract +43. Revoke CSAccounting role RESET_BOND_CURVE_ROLE from the CSM contract +44. Revoke CSAccounting role RESET_BOND_CURVE_ROLE from the CSM committee +45. Grant CSM role CREATE_NODE_OPERATOR_ROLE for the permissionless gate +46. Grant CSM role CREATE_NODE_OPERATOR_ROLE for the vetted gate +47. Grant CSAccounting role SET_BOND_CURVE_ROLE for the vetted gate +48. Revoke role VERIFIER_ROLE from the previous instance of the Verifier contract +49. Grant role VERIFIER_ROLE to the new instance of the Verifier contract +50. Revoke CSM role PAUSE_ROLE from the previous GateSeal instance +51. Revoke CSAccounting role PAUSE_ROLE from the previous GateSeal instance +52. Revoke CSFeeOracle role PAUSE_ROLE from the previous GateSeal instance +53. Grant CSM role PAUSE_ROLE for the new GateSeal instance +54. Grant CSAccounting role PAUSE_ROLE for the new GateSeal instance +55. Grant CSFeeOracle role PAUSE_ROLE for the new GateSeal instance +56. Grant MANAGE_BOND_CURVES_ROLE to the AGENT +57. Add Identified Community Stakers Gate Bond Curve +58. Revoke MANAGE_BOND_CURVES_ROLE from the AGENT +59. Increase CSM share in Staking Router from 15% to 16% +--- Gate Seals --- +60. Revoke PAUSE_ROLE on WithdrawalQueue from the old GateSeal +61. Revoke PAUSE_ROLE on ValidatorsExitBusOracle from the old GateSeal +62. Grant PAUSE_ROLE on WithdrawalQueue to the new WithdrawalQueue GateSeal +63. Grant PAUSE_ROLE on ValidatorsExitBusOracle to the new Triggerable Withdrawals GateSeal +64. Grant PAUSE_ROLE on TriggerableWithdrawalsGateway to the new Triggerable Withdrawals GateSeal +--- ResealManager --- +65. Grant PAUSE_ROLE on TriggerableWithdrawalsGateway to ResealManager +66. Grant RESUME_ROLE on TriggerableWithdrawalsGateway to ResealManager +--- EasyTrack --- +67. Add CSSetVettedGateTree factory to EasyTrack with permissions +68. Add `SubmitValidatorsExitRequestHashes` (SDVT) EVM script factory to Easy Track +69. Add `SubmitValidatorsExitRequestHashes` (Curated Module) EVM script factory to Easy Track + +Vote passed & executed on Jul-23-2025 12:54:36 PM UTC, block 862608 +""" +import time + +from typing import TYPE_CHECKING, Any, Dict +from typing import Tuple, Optional, Sequence +from brownie import interface, web3, convert, ZERO_ADDRESS # type: ignore +from utils.agent import agent_forward +from utils.config import ( + CSM_COMMITTEE_MS, + CS_MODULE_ID, + CS_MODULE_MODULE_FEE_BP, + CS_MODULE_TREASURY_FEE_BP, + CS_MODULE_MAX_DEPOSITS_PER_BLOCK, + CS_MODULE_MIN_DEPOSIT_BLOCK_DISTANCE, + CS_MODULE_TARGET_SHARE_BP, + CS_GATE_SEAL_ADDRESS, + NODE_OPERATORS_REGISTRY_ARAGON_APP_ID, + SIMPLE_DVT_ARAGON_APP_ID, + ARAGON_KERNEL, + AGENT, + contracts, +) +from utils.ipfs import upload_vote_ipfs_description, calculate_vote_ipfs_description +from utils.permissions import encode_oz_grant_role, encode_oz_revoke_role +from utils.easy_track import ( + add_evmscript_factory, + create_permissions, +) +from utils.voting import confirm_vote_script, create_vote +from utils.config import get_deployer_account, get_priority_fee, get_is_live + +DESCRIPTION = "Triggerable withdrawals and CSM v2 upgrade voting (HOODI)" + +# New core contracts implementations +LIDO_LOCATOR_IMPL = "0x003f20CD17e7683A7F88A7AfF004f0C44F0cfB31" +ACCOUNTING_ORACLE_IMPL = "0x2341c9BE0E639f262f8170f9ef1efeCC92cCF617" +VALIDATORS_EXIT_BUS_ORACLE_IMPL = "0x7E6d9C9C44417bf2EaF69685981646e9752D623A" +WITHDRAWAL_VAULT_IMPL = "0xfe7A58960Af333eAdeAeC39149F9d6A71dc3E668" +STAKING_ROUTER_IMPL = "0xd5F04A81ac472B2cB32073CE9dDABa6FaF022827" +NODE_OPERATORS_REGISTRY_IMPL = "0x95F00b016bB31b7182D96D25074684518246E42a" + +TRIGGERABLE_WITHDRAWALS_GATEWAY = "0x6679090D92b08a2a686eF8614feECD8cDFE209db" +VALIDATOR_EXIT_VERIFIER = "0xFd4386A8795956f4B6D01cbb6dB116749731D7bD" + +# Oracle consensus versions +AO_CONSENSUS_VERSION = 4 +VEBO_CONSENSUS_VERSION = 4 +CSM_CONSENSUS_VERSION = 3 + +# Fixed constants from Holesky version +EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS = 14 * 7200 # 14 days in slots (assuming 12 seconds per slot) +NOR_EXIT_DEADLINE_IN_SEC = 172800 # 172800 + +# VEB parameters from Holesky +MAX_VALIDATORS_PER_REPORT = 600 +MAX_EXIT_REQUESTS_LIMIT = 11200 +EXITS_PER_FRAME = 1 +FRAME_DURATION_IN_SEC = 48 + +# CSM +CS_MODULE_NEW_TARGET_SHARE_BP = 1600 # 16% +CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP = 2100 # 21% + +CS_ACCOUNTING_IMPL_V2_ADDRESS = "0x9483b34504292a0E4f6509e5887D2c68f7129638" +CS_FEE_DISTRIBUTOR_IMPL_V2_ADDRESS = "0xe05F7Aab7177D73f26e62a5296120583F5F18031" +CS_FEE_ORACLE_IMPL_V2_ADDRESS = "0x752fF00fcacdB66Bc512a067F15A5E0B0b50EADB" +CSM_IMPL_V2_ADDRESS = "0x9aE387EB2abA80B9B1ebc145597D593EFAE61f31" + +CS_GATE_SEAL_V2_ADDRESS = "0x94a3aEB0E9148F64CB453Be2BDe2Bc0148f6AC24" +CS_EJECTOR_ADDRESS = "0x21e271cBa32672B106737AbeB3a45E53Fe9a0df4" +CS_PERMISSIONLESS_GATE_ADDRESS = "0x5553077102322689876A6AdFd48D75014c28acfb" +CS_VETTED_GATE_ADDRESS = "0x10a254E724fe2b7f305F76f3F116a3969c53845f" +CS_VERIFIER_V2_ADDRESS = "0xf805b3711cBB48F15Ae2bb27095ddC38c5339968" + +CS_CURVES = [ + ([1, 2.4 * 10**18], [2, 1.3 * 10**18]), # Default Curve + ([1, 1.5 * 10**18], [2, 1.3 * 10**18]), # Legacy EA Curve +] +CS_ICS_GATE_BOND_CURVE = ([1, 1.5 * 10**18], [2, 1.3 * 10**18]) # Identified Community Stakers Gate Bond Curve + +# Add missing constants +OLD_GATE_SEAL_ADDRESS = "0x2168Ea6D948Ab49c3D34c667A7e02F92369F3A9C" +NEW_WQ_GATE_SEAL = "0x73d76Bd3D589B2b2185c402da82cdAfbc18b958D" +NEW_TW_GATE_SEAL = "0x368f2fcb593170823cc844F1B29e75E3d26879A1" +RESEAL_MANAGER = "0x05172CbCDb7307228F781436b327679e4DAE166B" + +# Add EasyTrack constants +EASYTRACK_EVMSCRIPT_EXECUTOR = "0x79a20FD0FA36453B2F45eAbab19bfef43575Ba9E" +EASYTRACK_SDVT_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY = "0xAa3D6A8B52447F272c1E8FAaA06EA06658bd95E2" +EASYTRACK_CURATED_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY = "0x397206ecdbdcb1A55A75e60Fc4D054feC72E5f63" +EASYTRACK_CS_SET_VETTED_GATE_TREE_FACTORY = "0xa890fc73e1b771Ee6073e2402E631c312FF92Cd9" + + +def encode_staking_router_proxy_update(implementation: str) -> Tuple[str, str]: + proxy = interface.OssifiableProxy(contracts.staking_router) + return proxy.address, proxy.proxy__upgradeTo.encode_input(implementation) + + +def encode_proxy_upgrade_to(proxy: Any, implementation: str) -> Tuple[str, str]: + proxy = interface.OssifiableProxy(proxy) + return proxy.address, proxy.proxy__upgradeTo.encode_input(implementation) + + +def encode_wv_proxy_upgrade_to(proxy: Any, implementation: str) -> Tuple[str, str]: + proxy = interface.WithdrawalContractProxy(proxy) + + return proxy.address, proxy.proxy_upgradeTo.encode_input(implementation, b'') + + +def encode_oracle_upgrade_consensus(proxy: Any, consensus_version: int) -> Tuple[str, str]: + oracle = interface.BaseOracle(proxy) + return oracle.address, oracle.setConsensusVersion.encode_input(consensus_version) + + +def encode_staking_router_update_csm_module_share() -> Tuple[str, str]: + """Encode call to update CSM share limit""" + return ( + contracts.staking_router.address, + contracts.staking_router.updateStakingModule.encode_input( + CS_MODULE_ID, + CS_MODULE_NEW_TARGET_SHARE_BP, + CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP, + CS_MODULE_MODULE_FEE_BP, + CS_MODULE_TREASURY_FEE_BP, + CS_MODULE_MAX_DEPOSITS_PER_BLOCK, + CS_MODULE_MIN_DEPOSIT_BLOCK_DISTANCE, + ) + ) + + +def to_percent(bp: int) -> float: + """ + Convert basis points to percentage. + """ + return bp / 10000 * 100 + + +def start_vote(tx_params: Dict[str, str], silent: bool) -> Tuple[int, Optional[Any]]: + vote_desc_items, call_script_items = zip( + # --- locator + ( + "1. Update locator implementation", + agent_forward([encode_proxy_upgrade_to(contracts.lido_locator, LIDO_LOCATOR_IMPL)]) + ), + # --- VEB + ( + "2. Update VEBO implementation", + agent_forward([encode_proxy_upgrade_to(contracts.validators_exit_bus_oracle, VALIDATORS_EXIT_BUS_ORACLE_IMPL)]) + ), + ( + "3. Call finalizeUpgrade_v2 on VEBO", + agent_forward([ + ( + contracts.validators_exit_bus_oracle.address, + contracts.validators_exit_bus_oracle.finalizeUpgrade_v2.encode_input( + MAX_VALIDATORS_PER_REPORT, MAX_EXIT_REQUESTS_LIMIT, EXITS_PER_FRAME, FRAME_DURATION_IN_SEC + ), + ) + ]) + ), + ( + "4. Grant VEBO role MANAGE_CONSENSUS_VERSION_ROLE to the AGENT", + agent_forward([ + encode_oz_grant_role( + contract=contracts.validators_exit_bus_oracle, + role_name="MANAGE_CONSENSUS_VERSION_ROLE", + grant_to=contracts.agent, + ) + ]) + ), + ( + "5. Bump VEBO consensus version to `4`", + agent_forward([encode_oracle_upgrade_consensus(contracts.validators_exit_bus_oracle, VEBO_CONSENSUS_VERSION)]) + ), + ( + "6. Revoke VEBO role MANAGE_CONSENSUS_VERSION_ROLE from the AGENT", + agent_forward([ + encode_oz_revoke_role( + contract=contracts.validators_exit_bus_oracle, + role_name="MANAGE_CONSENSUS_VERSION_ROLE", + revoke_from=contracts.agent, + ) + ]) + ), + ( + "7. Grant SUBMIT_REPORT_HASH_ROLE on Validator Exit Bus Oracle to the EasyTrack EVM Script Executor", + agent_forward([ + encode_oz_grant_role( + contract=contracts.validators_exit_bus_oracle, + role_name="SUBMIT_REPORT_HASH_ROLE", + grant_to=EASYTRACK_EVMSCRIPT_EXECUTOR, + ) + ]) + ), + # --- Triggerable Withdrawals Gateway (TWG) + ( + "8. Grant TWG role ADD_FULL_WITHDRAWAL_REQUEST_ROLE to the CS Ejector", + agent_forward([ + encode_oz_grant_role( + contract=interface.TriggerableWithdrawalsGateway(TRIGGERABLE_WITHDRAWALS_GATEWAY), + role_name="ADD_FULL_WITHDRAWAL_REQUEST_ROLE", + grant_to=CS_EJECTOR_ADDRESS, + ) + ]) + ), + ( + "9. Grant TWG role ADD_FULL_WITHDRAWAL_REQUEST_ROLE to the VEB", + agent_forward([ + encode_oz_grant_role( + contract=interface.TriggerableWithdrawalsGateway(TRIGGERABLE_WITHDRAWALS_GATEWAY), + role_name="ADD_FULL_WITHDRAWAL_REQUEST_ROLE", + grant_to=contracts.validators_exit_bus_oracle, + ) + ]) + ), + ( + "10. Connect TRIGGERABLE_WITHDRAWALS_GATEWAY to Dual Governance tiebreaker", + ( + contracts.dual_governance.address, + contracts.dual_governance.addTiebreakerSealableWithdrawalBlocker.encode_input( + TRIGGERABLE_WITHDRAWALS_GATEWAY + ), + ) + ), + # --- WV + ( + "11. Update WithdrawalVault implementation", + agent_forward([encode_wv_proxy_upgrade_to(contracts.withdrawal_vault, WITHDRAWAL_VAULT_IMPL)]) + ), + ( + "12. Call finalizeUpgrade_v2 on WithdrawalVault", + agent_forward([ + ( + contracts.withdrawal_vault.address, + contracts.withdrawal_vault.finalizeUpgrade_v2.encode_input(), + ) + ]) + ), + # --- AO + ( + "13. Update Accounting Oracle implementation", + agent_forward([encode_proxy_upgrade_to(contracts.accounting_oracle, ACCOUNTING_ORACLE_IMPL)]) + ), + ( + "14. Grant AO MANAGE_CONSENSUS_VERSION_ROLE to the AGENT", + agent_forward([ + encode_oz_grant_role( + contract=contracts.accounting_oracle, + role_name="MANAGE_CONSENSUS_VERSION_ROLE", + grant_to=contracts.agent, + ) + ]) + ), + ( + "15. Bump AO consensus version to `4`", + agent_forward([encode_oracle_upgrade_consensus(contracts.accounting_oracle, AO_CONSENSUS_VERSION)]) + ), + ( + "16. Revoke AO MANAGE_CONSENSUS_VERSION_ROLE from the AGENT", + agent_forward([ + encode_oz_revoke_role( + contract=contracts.accounting_oracle, + role_name="MANAGE_CONSENSUS_VERSION_ROLE", + revoke_from=contracts.agent, + ) + ]) + ), + ( + "17. Call finalizeUpgrade_v3() on AO", + agent_forward([ + ( + contracts.accounting_oracle.address, + contracts.accounting_oracle.finalizeUpgrade_v3.encode_input(), + ) + ]) + ), + # --- SR + ( + "18. Update SR implementation", + agent_forward([encode_staking_router_proxy_update(STAKING_ROUTER_IMPL)]) + ), + ( + "19. Call finalizeUpgrade_v3() on SR", + agent_forward([( + contracts.staking_router.address, + contracts.staking_router.finalizeUpgrade_v3.encode_input(), + )]) + ), + ( + "20. Grant SR role REPORT_VALIDATOR_EXITING_STATUS_ROLE to ValidatorExitDelayVerifier", + agent_forward([ + encode_oz_grant_role( + contract=contracts.staking_router, + role_name="REPORT_VALIDATOR_EXITING_STATUS_ROLE", + grant_to=VALIDATOR_EXIT_VERIFIER, + ) + ]) + ), + ( + "21. Grant SR role REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE to TWG", + agent_forward([ + encode_oz_grant_role( + contract=contracts.staking_router, + role_name="REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE", + grant_to=interface.TriggerableWithdrawalsGateway(TRIGGERABLE_WITHDRAWALS_GATEWAY), + ) + ]) + ), + # --- Curated Staking Module and sDVT + ( + "22. Grant APP_MANAGER_ROLE role to the AGENT", + agent_forward([ + ( + contracts.acl.address, + contracts.acl.grantPermission.encode_input( + AGENT, + ARAGON_KERNEL, + convert.to_uint(web3.keccak(text="APP_MANAGER_ROLE")) + ) + ) + ]) + ), + ( + "23. Update `NodeOperatorsRegistry` implementation", + agent_forward([ + ( + contracts.kernel.address, + contracts.kernel.setApp.encode_input( + contracts.kernel.APP_BASES_NAMESPACE(), + NODE_OPERATORS_REGISTRY_ARAGON_APP_ID, + NODE_OPERATORS_REGISTRY_IMPL + ) + ) + ]) + ), + ( + "24. Call finalizeUpgrade_v4 on Curated Staking Module", + agent_forward([ + ( + interface.NodeOperatorsRegistry(contracts.node_operators_registry).address, + interface.NodeOperatorsRegistry(contracts.node_operators_registry).finalizeUpgrade_v4.encode_input( + NOR_EXIT_DEADLINE_IN_SEC + ) + ) + ]) + ), + ( + "25. Update `SDVT` implementation", + agent_forward([ + ( + contracts.kernel.address, + contracts.kernel.setApp.encode_input( + contracts.kernel.APP_BASES_NAMESPACE(), + SIMPLE_DVT_ARAGON_APP_ID, + NODE_OPERATORS_REGISTRY_IMPL + ) + ) + ]) + ), + ( + "26. Call finalizeUpgrade_v4 on SDVT", + agent_forward([ + ( + interface.NodeOperatorsRegistry(contracts.simple_dvt).address, + interface.NodeOperatorsRegistry(contracts.simple_dvt).finalizeUpgrade_v4.encode_input( + NOR_EXIT_DEADLINE_IN_SEC + ) + ) + ]) + ), + ( + "27. Revoke APP_MANAGER_ROLE role from the AGENT", + agent_forward([ + ( + contracts.acl.address, + contracts.acl.revokePermission.encode_input( + AGENT, + ARAGON_KERNEL, + convert.to_uint(web3.keccak(text="APP_MANAGER_ROLE")) + ) + ) + ]) + ), + # --- Oracle configs + ( + "28. Grant CONFIG_MANAGER_ROLE role to the AGENT", + agent_forward([ + encode_oz_grant_role( + contract=contracts.oracle_daemon_config, + role_name="CONFIG_MANAGER_ROLE", + grant_to=contracts.agent, + ) + ]) + ), + ( + "29. Remove NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP variable from OracleDaemonConfig", + agent_forward([ + ( + contracts.oracle_daemon_config.address, + contracts.oracle_daemon_config.unset.encode_input('NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP'), + ) + ]) + ), + ( + "30. Remove VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS variable from OracleDaemonConfig", + agent_forward([ + ( + contracts.oracle_daemon_config.address, + contracts.oracle_daemon_config.unset.encode_input('VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS'), + ) + ]) + ), + ( + "31. Remove VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS variable from OracleDaemonConfig", + agent_forward([ + ( + contracts.oracle_daemon_config.address, + contracts.oracle_daemon_config.unset.encode_input('VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS'), + ) + ]) + ), + ( + "32. Add EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS variable to OracleDaemonConfig", + agent_forward([ + ( + contracts.oracle_daemon_config.address, + contracts.oracle_daemon_config.set.encode_input('EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS', EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS), + ) + ]) + ), + ( + "33. Revoke CONFIG_MANAGER_ROLE role from the AGENT", + agent_forward([ + encode_oz_revoke_role( + contract=contracts.oracle_daemon_config, + role_name="CONFIG_MANAGER_ROLE", + revoke_from=contracts.agent, + ) + ]) + ), + # --- CSM + ( + "34. Upgrade CSM implementation on proxy", + agent_forward([ + encode_proxy_upgrade_to( + contracts.csm, + CSM_IMPL_V2_ADDRESS, + ) + ]) + ), + ( + "35. Call `finalizeUpgradeV2()` on CSM contract", + agent_forward([ + ( + contracts.csm.address, + contracts.csm.finalizeUpgradeV2.encode_input(), + ) + ]) + ), + ( + "36. Upgrade CSAccounting implementation on proxy", + agent_forward([ + encode_proxy_upgrade_to( + contracts.cs_accounting, + CS_ACCOUNTING_IMPL_V2_ADDRESS, + ) + ]) + ), + ( + "37. Call `finalizeUpgradeV2(bondCurves)` on CSAccounting contract", + agent_forward([ + ( + contracts.cs_accounting.address, + contracts.cs_accounting.finalizeUpgradeV2.encode_input(CS_CURVES), + ) + ]) + ), + ( + "38. Upgrade CSFeeOracle implementation on proxy", + agent_forward([ + encode_proxy_upgrade_to( + contracts.cs_fee_oracle, + CS_FEE_ORACLE_IMPL_V2_ADDRESS, + ) + ]) + ), + ( + "39. Call `finalizeUpgradeV2(consensusVersion)` on CSFeeOracle contract", + agent_forward([ + ( + contracts.cs_fee_oracle.address, + contracts.cs_fee_oracle.finalizeUpgradeV2.encode_input(CSM_CONSENSUS_VERSION), + ) + ]) + ), + ( + "40. Upgrade CSFeeDistributor implementation on proxy", + agent_forward([ + encode_proxy_upgrade_to( + contracts.cs_fee_distributor, + CS_FEE_DISTRIBUTOR_IMPL_V2_ADDRESS, + ) + ]) + ), + ( + "41. Call `finalizeUpgradeV2(admin)` on CSFeeDistributor contract", + agent_forward([ + ( + contracts.cs_fee_distributor.address, + contracts.cs_fee_distributor.finalizeUpgradeV2.encode_input(contracts.agent), + ) + ]) + ), + ( + "42. Revoke CSAccounting role SET_BOND_CURVE_ROLE from the CSM contract", + agent_forward([ + encode_oz_revoke_role( + contract=contracts.cs_accounting, + role_name="SET_BOND_CURVE_ROLE", + revoke_from=contracts.csm, + ) + ]) + ), + ( + "43. Revoke CSAccounting role RESET_BOND_CURVE_ROLE from the CSM contract", + agent_forward([ + encode_oz_revoke_role( + contract=contracts.cs_accounting, + role_name="RESET_BOND_CURVE_ROLE", + revoke_from=contracts.csm, + ) + ]) + ), + ( + "44. Revoke CSAccounting role RESET_BOND_CURVE_ROLE from the CSM committee", + agent_forward([ + encode_oz_revoke_role( + contract=contracts.cs_accounting, + role_name="RESET_BOND_CURVE_ROLE", + revoke_from=CSM_COMMITTEE_MS, + ) + ]) + ), + ( + "45. Grant CSM role CREATE_NODE_OPERATOR_ROLE for the permissionless gate", + agent_forward([ + encode_oz_grant_role( + contract=contracts.csm, + role_name="CREATE_NODE_OPERATOR_ROLE", + grant_to=CS_PERMISSIONLESS_GATE_ADDRESS, + ) + ]) + ), + ( + "46. Grant CSM role CREATE_NODE_OPERATOR_ROLE for the vetted gate", + agent_forward([ + encode_oz_grant_role( + contract=contracts.csm, + role_name="CREATE_NODE_OPERATOR_ROLE", + grant_to=CS_VETTED_GATE_ADDRESS, + ) + ]) + ), + ( + "47. Grant CSAccounting role SET_BOND_CURVE_ROLE for the vetted gate", + agent_forward([ + encode_oz_grant_role( + contract=contracts.cs_accounting, + role_name="SET_BOND_CURVE_ROLE", + grant_to=CS_VETTED_GATE_ADDRESS, + ) + ]) + ), + ( + "48. Revoke role VERIFIER_ROLE from the previous instance of the Verifier contract", + agent_forward([ + encode_oz_revoke_role( + contract=contracts.csm, + role_name="VERIFIER_ROLE", + revoke_from=contracts.cs_verifier, + ) + ]) + ), + ( + "49. Grant role VERIFIER_ROLE to the new instance of the Verifier contract", + agent_forward([ + encode_oz_grant_role( + contract=contracts.csm, + role_name="VERIFIER_ROLE", + grant_to=CS_VERIFIER_V2_ADDRESS, + ) + ]) + ), + ( + "50. Revoke CSM role PAUSE_ROLE from the previous GateSeal instance", + agent_forward([ + encode_oz_revoke_role( + contract=contracts.csm, + role_name="PAUSE_ROLE", + revoke_from=CS_GATE_SEAL_ADDRESS, + ) + ]) + ), + ( + "51. Revoke CSAccounting role PAUSE_ROLE from the previous GateSeal instance", + agent_forward([ + encode_oz_revoke_role( + contract=contracts.cs_accounting, + role_name="PAUSE_ROLE", + revoke_from=CS_GATE_SEAL_ADDRESS, + ) + ]) + ), + ( + "52. Revoke CSFeeOracle role PAUSE_ROLE from the previous GateSeal instance", + agent_forward([ + encode_oz_revoke_role( + contract=contracts.cs_fee_oracle, + role_name="PAUSE_ROLE", + revoke_from=CS_GATE_SEAL_ADDRESS, + ) + ]) + ), + ( + "53. Grant CSM role PAUSE_ROLE for the new GateSeal instance", + agent_forward([ + encode_oz_grant_role( + contract=contracts.csm, + role_name="PAUSE_ROLE", + grant_to=CS_GATE_SEAL_V2_ADDRESS, + ) + ]) + ), + ( + "54. Grant CSAccounting role PAUSE_ROLE for the new GateSeal instance", + agent_forward([ + encode_oz_grant_role( + contract=contracts.cs_accounting, + role_name="PAUSE_ROLE", + grant_to=CS_GATE_SEAL_V2_ADDRESS, + ) + ]) + ), + ( + "55. Grant CSFeeOracle role PAUSE_ROLE for the new GateSeal instance", + agent_forward([ + encode_oz_grant_role( + contract=contracts.cs_fee_oracle, + role_name="PAUSE_ROLE", + grant_to=CS_GATE_SEAL_V2_ADDRESS, + ) + ]) + ), + ( + "56. Grant MANAGE_BOND_CURVES_ROLE to the AGENT", + agent_forward([ + encode_oz_grant_role( + contract=contracts.cs_accounting, + role_name="MANAGE_BOND_CURVES_ROLE", + grant_to=contracts.agent, + ) + ]) + ), + ( + "57. Add Identified Community Stakers Gate Bond Curve", + agent_forward([ + ( + contracts.cs_accounting.address, + contracts.cs_accounting.addBondCurve.encode_input(CS_ICS_GATE_BOND_CURVE), + ) + ]) + ), + ( + "58. Revoke MANAGE_BOND_CURVES_ROLE from the AGENT", + agent_forward([ + encode_oz_revoke_role( + contract=contracts.cs_accounting, + role_name="MANAGE_BOND_CURVES_ROLE", + revoke_from=contracts.agent, + ) + ]) + ), + ( + "59. Increase CSM share in Staking Router from 15% to 16%", + agent_forward([encode_staking_router_update_csm_module_share()]) + ), + # --- Gate Seals + ( + "60. Revoke PAUSE_ROLE on WithdrawalQueue from the old GateSeal", + agent_forward([ + encode_oz_revoke_role( + contract=contracts.withdrawal_queue, + role_name="PAUSE_ROLE", + revoke_from=OLD_GATE_SEAL_ADDRESS, + ) + ]) + ), + ( + "61. Revoke PAUSE_ROLE on ValidatorsExitBusOracle from the old GateSeal", + agent_forward([ + encode_oz_revoke_role( + contract=contracts.validators_exit_bus_oracle, + role_name="PAUSE_ROLE", + revoke_from=OLD_GATE_SEAL_ADDRESS, + ) + ]) + ), + ( + "62. Grant PAUSE_ROLE on WithdrawalQueue to the new WithdrawalQueue GateSeal", + agent_forward([ + encode_oz_grant_role( + contract=contracts.withdrawal_queue, + role_name="PAUSE_ROLE", + grant_to=NEW_WQ_GATE_SEAL, + ) + ]) + ), + ( + "63. Grant PAUSE_ROLE on ValidatorsExitBusOracle to the new Triggerable Withdrawals GateSeal", + agent_forward([ + encode_oz_grant_role( + contract=contracts.validators_exit_bus_oracle, + role_name="PAUSE_ROLE", + grant_to=NEW_TW_GATE_SEAL, + ) + ]) + ), + ( + "64. Grant PAUSE_ROLE on TriggerableWithdrawalsGateway to the new Triggerable Withdrawals GateSeal", + agent_forward([ + encode_oz_grant_role( + contract=interface.TriggerableWithdrawalsGateway(TRIGGERABLE_WITHDRAWALS_GATEWAY), + role_name="PAUSE_ROLE", + grant_to=NEW_TW_GATE_SEAL, + ) + ]) + ), + ( + "65. Grant PAUSE_ROLE on TriggerableWithdrawalsGateway to ResealManager", + agent_forward([ + encode_oz_grant_role( + contract=interface.TriggerableWithdrawalsGateway(TRIGGERABLE_WITHDRAWALS_GATEWAY), + role_name="PAUSE_ROLE", + grant_to=RESEAL_MANAGER, + ) + ]) + ), + ( + "66. Grant RESUME_ROLE on TriggerableWithdrawalsGateway to ResealManager", + agent_forward([ + encode_oz_grant_role( + contract=interface.TriggerableWithdrawalsGateway(TRIGGERABLE_WITHDRAWALS_GATEWAY), + role_name="RESUME_ROLE", + grant_to=RESEAL_MANAGER, + ) + ]) + ), + ) + + dg_bypass_item = { + "67. Add CSSetVettedGateTree factory to EasyTrack with permissions": add_evmscript_factory( + factory=EASYTRACK_CS_SET_VETTED_GATE_TREE_FACTORY, + permissions=(create_permissions(interface.CSVettedGate(CS_VETTED_GATE_ADDRESS), "setTreeParams")), + ), + "68. Add `SubmitValidatorsExitRequestHashes` (SDVT) EVM script factory to Easy Track": add_evmscript_factory( + factory=EASYTRACK_SDVT_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY, + permissions=(create_permissions(contracts.validators_exit_bus_oracle, "submitExitRequestsHash")), + ), + "69. Add `SubmitValidatorsExitRequestHashes` (Curated Module) EVM script factory to Easy Track": add_evmscript_factory( + factory=EASYTRACK_CURATED_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY, + permissions=(create_permissions(contracts.validators_exit_bus_oracle, "submitExitRequestsHash")), + ) + } + + if silent: + desc_ipfs = calculate_vote_ipfs_description(DESCRIPTION) + else: + desc_ipfs = upload_vote_ipfs_description(DESCRIPTION) + + dg_desc = "\n".join(vote_desc_items) + + dg_vote = prepare_proposal(call_script_items, dg_desc) + vote_items = {dg_desc: dg_vote, **dg_bypass_item} + + assert confirm_vote_script(vote_items, silent, desc_ipfs) + + return create_vote(vote_items, tx_params, desc_ipfs=desc_ipfs) + +def prepare_proposal( + call_script: Sequence[Tuple], + description: Optional[str] = "", +) -> Tuple[str, str]: + dual_governance = contracts.dual_governance + forwarded = [] + + for _call in call_script: + forwarded.append((_call[0], _call[1])) + + print(f"Forwarding call script to dual governance: {forwarded}") + return ( + contracts.dual_governance.address, + dual_governance.submitProposal.encode_input([(_call[0], 0, _call[1]) for _call in forwarded], description), + ) + +def main(): + tx_params = {"from": get_deployer_account()} + if get_is_live(): + tx_params["priority_fee"] = get_priority_fee() + + vote_id, _ = start_vote(tx_params=tx_params, silent=False) + + vote_id >= 0 and print(f"Vote created: {vote_id}.") + + time.sleep(5) # hack for waiting thread #2. diff --git a/tests/test_vote_tw_csm2_mainnet.py b/tests/test_vote_tw_csm2_mainnet.py new file mode 100644 index 000000000..0be8f7241 --- /dev/null +++ b/tests/test_vote_tw_csm2_mainnet.py @@ -0,0 +1,1062 @@ +from typing import Optional +from scripts.vote_tw_csm2_mainnet import start_vote +from brownie import interface, reverts, chain, convert, web3, ZERO_ADDRESS # type: ignore +from brownie.network.event import EventDict +from utils.easy_track import create_permissions +from utils.test.tx_tracing_helpers import group_voting_events_from_receipt, group_dg_events_from_receipt +from utils.test.event_validators.easy_track import validate_evmscript_factory_added_event, EVMScriptFactoryAdded +from utils.test.event_validators.dual_governance import validate_dual_governance_submit_event +from utils.dual_governance import wait_for_noon_utc_to_satisfy_time_constrains +from utils.config import ( + DUAL_GOVERNANCE, + TIMELOCK, + DUAL_GOVERNANCE_EXECUTORS, + LDO_HOLDER_ADDRESS_FOR_TESTS, + CS_MODULE_ID, + CS_MODULE_MODULE_FEE_BP, + CS_MODULE_MAX_DEPOSITS_PER_BLOCK, + CS_MODULE_MIN_DEPOSIT_BLOCK_DISTANCE, + CS_MODULE_TREASURY_FEE_BP, + CS_GATE_SEAL_ADDRESS, + CSM_COMMITTEE_MS, + ARAGON_KERNEL, + AGENT, + VOTING, + contracts, +) + + +def validate_proxy_upgrade_event(event: EventDict, implementation: str, emitted_by: Optional[str] = None): + assert "Upgraded" in event, "No Upgraded event found" + + assert event["Upgraded"][0]["implementation"] == implementation, "Wrong implementation address" + + if emitted_by is not None: + assert convert.to_address(event["Upgraded"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + + +def validate_consensus_version_set_event(event: EventDict, new_version: int, prev_version: int, emitted_by: Optional[str] = None): + assert "ConsensusVersionSet" in event, "No ConsensusVersionSet event found" + + assert event["ConsensusVersionSet"][0]["version"] == new_version, "Wrong new version" + + assert event["ConsensusVersionSet"][0]["prevVersion"] == prev_version, "Wrong previous version" + + if emitted_by is not None: + assert convert.to_address(event["ConsensusVersionSet"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + + +def validate_role_grant_event(event: EventDict, role_hash: str, account: str, emitted_by: Optional[str] = None): + assert "RoleGranted" in event, "No RoleGranted event found" + + # Strip 0x prefix for consistent comparison + expected_role_hash = role_hash.replace('0x', '') + actual_role_hash = event["RoleGranted"][0]["role"].hex().replace('0x', '') + + assert actual_role_hash == expected_role_hash, "Wrong role hash" + + assert convert.to_address(event["RoleGranted"][0]["account"]) == convert.to_address(account), "Wrong account" + + if emitted_by is not None: + assert convert.to_address(event["RoleGranted"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + + +def validate_role_revoke_event(event: EventDict, role_hash: str, account: str, emitted_by: Optional[str] = None): + assert "RoleRevoked" in event, "No RoleRevoked event found" + + # Strip 0x prefix for consistent comparison + expected_role_hash = role_hash.replace('0x', '') + actual_role_hash = event["RoleRevoked"][0]["role"].hex().replace('0x', '') + + assert actual_role_hash == expected_role_hash, "Wrong role hash" + + assert convert.to_address(event["RoleRevoked"][0]["account"]) == convert.to_address(account), "Wrong account" + + if emitted_by is not None: + assert convert.to_address(event["RoleRevoked"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + + +def validate_contract_version_set_event(event: EventDict, version: int, emitted_by: Optional[str] = None): + assert "ContractVersionSet" in event, "No ContractVersionSet event found" + + assert event["ContractVersionSet"][0]["version"] == version, "Wrong version" + + if emitted_by is not None: + assert convert.to_address(event["ContractVersionSet"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + + +def validate_bond_curve_added_event(event: EventDict, curve_id: int, emitted_by: Optional[str] = None): + assert "BondCurveAdded" in event, "No BondCurveAdded event found" + + assert event["BondCurveAdded"][0]["curveId"] == curve_id, "Wrong curve ID" + + if emitted_by is not None: + assert convert.to_address(event["BondCurveAdded"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + + +def validate_staking_module_update_event( + event: EventDict, + module_id: int, + share_limit: int, + priority_share_threshold: int, + module_fee_points_bp: int, + treasury_fee_points_bp: int, + max_deposits_per_block: int, + min_deposit_block_distance: int, + emitted_by: Optional[str] = None +): + assert "StakingModuleShareLimitSet" in event, "No StakingModuleShareLimitSet event found" + assert "StakingModuleFeesSet" in event, "No StakingModuleFeesSet event found" + assert "StakingModuleMaxDepositsPerBlockSet" in event, "No StakingModuleMaxDepositsPerBlockSet event found" + assert "StakingModuleMinDepositBlockDistanceSet" in event, "No StakingModuleMinDepositBlockDistanceSet event found" + + assert len(event["StakingModuleShareLimitSet"]) == 1, "Multiple StakingModuleShareLimitSet events found" + assert len(event["StakingModuleFeesSet"]) == 1, "Multiple StakingModuleFeesSet events found" + assert len(event["StakingModuleMaxDepositsPerBlockSet"]) == 1, "Multiple StakingModuleMaxDepositsPerBlockSet events found" + assert len(event["StakingModuleMinDepositBlockDistanceSet"]) == 1, "Multiple StakingModuleMinDepositBlockDistanceSet events found" + + assert event["StakingModuleShareLimitSet"][0]["stakingModuleId"] == module_id, "Wrong module ID" + assert event["StakingModuleShareLimitSet"][0]["stakeShareLimit"] == share_limit, "Wrong share limit" + assert event["StakingModuleShareLimitSet"][0]["priorityExitShareThreshold"] == priority_share_threshold, "Wrong priority threshold" + + assert event["StakingModuleFeesSet"][0]["stakingModuleFee"] == module_fee_points_bp, "Wrong fee points" + assert event["StakingModuleFeesSet"][0]["treasuryFee"] == treasury_fee_points_bp, "Wrong treasury fee points" + + assert event["StakingModuleMaxDepositsPerBlockSet"][0]["maxDepositsPerBlock"] == max_deposits_per_block, "Wrong max deposits" + + assert event["StakingModuleMinDepositBlockDistanceSet"][0]["minDepositBlockDistance"] == min_deposit_block_distance, "Wrong min distance" + + if emitted_by is not None: + assert convert.to_address(event["StakingModuleShareLimitSet"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + assert convert.to_address(event["StakingModuleFeesSet"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + assert convert.to_address(event["StakingModuleMaxDepositsPerBlockSet"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + assert convert.to_address(event["StakingModuleMinDepositBlockDistanceSet"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + + +def get_ossifiable_proxy_impl(proxy_address): + """Get implementation address from an OssifiableProxy""" + proxy = interface.OssifiableProxy(proxy_address) + return proxy.proxy__getImplementation() + + +def get_wv_contract_proxy_impl(proxy_address): + """Get implementation address from an WithdrawalContractProxy""" + proxy = interface.WithdrawalContractProxy(proxy_address) + return proxy.implementation() + + +def check_proxy_implementation(proxy_address, expected_impl): + """Check that proxy has expected implementation""" + actual_impl = get_ossifiable_proxy_impl(proxy_address) + assert actual_impl == expected_impl, f"Expected impl {expected_impl}, got {actual_impl}" + + +# New core contracts implementations +LIDO_LOCATOR_IMPL = "0x003f20CD17e7683A7F88A7AfF004f0C44F0cfB31" +ACCOUNTING_ORACLE_IMPL = "0x2341c9BE0E639f262f8170f9ef1efeCC92cCF617" +VALIDATORS_EXIT_BUS_ORACLE_IMPL = "0x7E6d9C9C44417bf2EaF69685981646e9752D623A" +WITHDRAWAL_VAULT_IMPL = "0xfe7A58960Af333eAdeAeC39149F9d6A71dc3E668" +STAKING_ROUTER_IMPL = "0xd5F04A81ac472B2cB32073CE9dDABa6FaF022827" +NODE_OPERATORS_REGISTRY_IMPL = "0x95F00b016bB31b7182D96D25074684518246E42a" + +TRIGGERABLE_WITHDRAWALS_GATEWAY = "0x6679090D92b08a2a686eF8614feECD8cDFE209db" +VALIDATOR_EXIT_VERIFIER = "0xFd4386A8795956f4B6D01cbb6dB116749731D7bD" + +# Add missing constants +OLD_GATE_SEAL_ADDRESS = "0x2168Ea6D948Ab49c3D34c667A7e02F92369F3A9C" +NEW_WQ_GATE_SEAL = "0x73d76Bd3D589B2b2185c402da82cdAfbc18b958D" +NEW_TW_GATE_SEAL = "0x368f2fcb593170823cc844F1B29e75E3d26879A1" +RESEAL_MANAGER = "0x05172CbCDb7307228F781436b327679e4DAE166B" + +# Add EasyTrack constants +EASYTRACK_EVMSCRIPT_EXECUTOR = "0x79a20FD0FA36453B2F45eAbab19bfef43575Ba9E" +EASYTRACK_SDVT_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY = "0xAa3D6A8B52447F272c1E8FAaA06EA06658bd95E2" +EASYTRACK_CURATED_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY = "0x397206ecdbdcb1A55A75e60Fc4D054feC72E5f63" + +# Oracle consensus versions +AO_CONSENSUS_VERSION = 4 +VEBO_CONSENSUS_VERSION = 4 +CSM_CONSENSUS_VERSION = 3 + +EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS = 14 * 7200 + +NOR_EXIT_DEADLINE_IN_SEC = 172800 + +# CSM +CS_MODULE_NEW_TARGET_SHARE_BP = 1600 # 16% +CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP = 2100 # 21% + +CS_ACCOUNTING_IMPL_V2_ADDRESS = "0x9483b34504292a0E4f6509e5887D2c68f7129638" +CS_FEE_DISTRIBUTOR_IMPL_V2_ADDRESS = "0xe05F7Aab7177D73f26e62a5296120583F5F18031" +CS_FEE_ORACLE_IMPL_V2_ADDRESS = "0x752fF00fcacdB66Bc512a067F15A5E0B0b50EADB" +CSM_IMPL_V2_ADDRESS = "0x9aE387EB2abA80B9B1ebc145597D593EFAE61f31" + +CS_GATE_SEAL_V2_ADDRESS = "0x94a3aEB0E9148F64CB453Be2BDe2Bc0148f6AC24" +CS_EJECTOR_ADDRESS = "0x21e271cBa32672B106737AbeB3a45E53Fe9a0df4" +CS_PERMISSIONLESS_GATE_ADDRESS = "0x5553077102322689876A6AdFd48D75014c28acfb" +CS_VETTED_GATE_ADDRESS = "0x10a254E724fe2b7f305F76f3F116a3969c53845f" +CS_VERIFIER_V2_ADDRESS = "0xf805b3711cBB48F15Ae2bb27095ddC38c5339968" + +CS_CURVES = [ + ([1, 2.4 * 10**18], [2, 1.3 * 10**18]), # Default Curve + ([1, 1.5 * 10**18], [2, 1.3 * 10**18]), # Legacy EA Curve +] +CS_ICS_GATE_BOND_CURVE = ([1, 1.5 * 10**18], [2, 1.3 * 10**18]) # Identified Community Stakers Gate Bond Curve + +# Contract versions expected after upgrade +CSM_V2_VERSION = 2 +CS_ACCOUNTING_V2_VERSION = 2 +CS_FEE_ORACLE_V2_VERSION = 2 +CS_FEE_DISTRIBUTOR_V2_VERSION = 2 + +EASYTRACK_CS_SET_VETTED_GATE_TREE_FACTORY = "0xa890fc73e1b771Ee6073e2402E631c312FF92Cd9" + + +def test_tw_vote(helpers, accounts, vote_ids_from_env, stranger): + # Save original implementations for comparison + locator_impl_before = get_ossifiable_proxy_impl(contracts.lido_locator) + accounting_oracle_impl_before = get_ossifiable_proxy_impl(contracts.accounting_oracle) + vebo_impl_before = get_ossifiable_proxy_impl(contracts.validators_exit_bus_oracle) + withdrawal_vault_impl_before = get_wv_contract_proxy_impl(contracts.withdrawal_vault) + staking_router_impl_before = get_ossifiable_proxy_impl(contracts.staking_router) + + csm_impl_before = get_ossifiable_proxy_impl(contracts.csm.address) + cs_accounting_impl_before = get_ossifiable_proxy_impl(contracts.cs_accounting.address) + cs_fee_oracle_impl_before = get_ossifiable_proxy_impl(contracts.cs_fee_oracle.address) + cs_fee_distributor_impl_before = get_ossifiable_proxy_impl(contracts.cs_fee_distributor.address) + + timelock = interface.EmergencyProtectedTimelock(TIMELOCK) + dual_governance = interface.DualGovernance(DUAL_GOVERNANCE) + + # Not yet used by the protocol, but needed for the test + triggerable_withdrawals_gateway = interface.TriggerableWithdrawalsGateway(TRIGGERABLE_WITHDRAWALS_GATEWAY) + cs_ejector = interface.CSEjector(CS_EJECTOR_ADDRESS) + cs_permissionless_gate = interface.CSPermissionlessGate(CS_PERMISSIONLESS_GATE_ADDRESS) + cs_vetted_gate = interface.CSVettedGate(CS_VETTED_GATE_ADDRESS) + cs_verifier_v2 = interface.CSVerifierV2(CS_VERIFIER_V2_ADDRESS) + + # --- Initial state checks --- + + # Step 1: Check Lido Locator implementation initial state + assert locator_impl_before != LIDO_LOCATOR_IMPL, "Locator implementation should be different before upgrade" + + # Step 2: Check VEBO implementation initial state + assert vebo_impl_before != VALIDATORS_EXIT_BUS_ORACLE_IMPL, "VEBO implementation should be different before upgrade" + + # Step 3: Check VEBO finalizeUpgrade_v2 state + try: + assert contracts.validators_exit_bus_oracle.getMaxValidatorsPerReport() != 600, "VEBO max validators per report should not be 600 before upgrade" + except Exception: + pass # Function might not exist yet + + # Steps 4-6: Check VEBO consensus version management + initial_vebo_consensus_version = contracts.validators_exit_bus_oracle.getConsensusVersion() + assert initial_vebo_consensus_version < VEBO_CONSENSUS_VERSION, f"VEBO consensus version should be less than {VEBO_CONSENSUS_VERSION}" + + # Step 7: Check TWG role for CS Ejector initial state + add_full_withdrawal_request_role = triggerable_withdrawals_gateway.ADD_FULL_WITHDRAWAL_REQUEST_ROLE() + assert not triggerable_withdrawals_gateway.hasRole(add_full_withdrawal_request_role, cs_ejector), "CS Ejector should not have ADD_FULL_WITHDRAWAL_REQUEST_ROLE before upgrade" + + # Step 8: Check TWG role for VEB initial state + assert not triggerable_withdrawals_gateway.hasRole(add_full_withdrawal_request_role, contracts.validators_exit_bus_oracle), "VEBO should not have ADD_FULL_WITHDRAWAL_REQUEST_ROLE before upgrade" + + # Step 9: Check EasyTrack VEB SUBMIT_REPORT_HASH_ROLE initial state + submit_report_hash_role = web3.keccak(text="SUBMIT_REPORT_HASH_ROLE") + assert not contracts.validators_exit_bus_oracle.hasRole(submit_report_hash_role, EASYTRACK_EVMSCRIPT_EXECUTOR), "EasyTrack executor should not have SUBMIT_REPORT_HASH_ROLE on VEBO before upgrade" + + # Step 10: Check DualGovernance tiebreaker initial state + tiebreaker_details = contracts.dual_governance.getTiebreakerDetails() + initial_tiebreakers = tiebreaker_details[3] # sealableWithdrawalBlockers + assert TRIGGERABLE_WITHDRAWALS_GATEWAY not in initial_tiebreakers, "TWG should not be in tiebreaker list before upgrade" + + # Step 9: Check Withdrawal Vault implementation initial state + assert withdrawal_vault_impl_before != WITHDRAWAL_VAULT_IMPL, "Withdrawal Vault implementation should be different before upgrade" + + # Step 10: Withdrawal Vault finalizeUpgrade_v2 check is done post-execution + assert contracts.withdrawal_vault.getContractVersion() == 1, "Withdrawal Vault version should be 1 before upgrade" + + # Step 11: Check Accounting Oracle implementation initial state + assert accounting_oracle_impl_before != ACCOUNTING_ORACLE_IMPL, "Accounting Oracle implementation should be different before upgrade" + + # Steps 12-14: Check AO consensus version management + initial_ao_consensus_version = contracts.accounting_oracle.getConsensusVersion() + assert initial_ao_consensus_version < AO_CONSENSUS_VERSION, f"AO consensus version should be less than {AO_CONSENSUS_VERSION}" + assert not contracts.accounting_oracle.hasRole(contracts.accounting_oracle.MANAGE_CONSENSUS_VERSION_ROLE(), contracts.agent), "Agent should not have MANAGE_CONSENSUS_VERSION_ROLE on AO before upgrade" + + # Step 17: Check AO version before finalizeUpgrade_v3 + assert contracts.accounting_oracle.getContractVersion() == 2, "AO contract version should be 2 before finalizeUpgrade_v3" + + # Step 15: Check Staking Router implementation initial state + assert staking_router_impl_before != STAKING_ROUTER_IMPL, "Staking Router implementation should be different before upgrade" + + # Steps 16-17: Check SR roles initial state + try: + report_validator_exiting_status_role = contracts.staking_router.REPORT_VALIDATOR_EXITING_STATUS_ROLE() + report_validator_exit_triggered_role = contracts.staking_router.REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE() + except Exception as e: + assert "Unknown typed error: 0x" in str(e), f"Unexpected error: {e}" + report_validator_exiting_status_role = ZERO_ADDRESS + report_validator_exit_triggered_role = ZERO_ADDRESS + + assert report_validator_exiting_status_role == ZERO_ADDRESS, "REPORT_VALIDATOR_EXITING_STATUS_ROLE should not exist before upgrade" + assert report_validator_exit_triggered_role == ZERO_ADDRESS, "REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE should not exist before upgrade" + + # Step 18: Check APP_MANAGER_ROLE initial state + app_manager_role = web3.keccak(text="APP_MANAGER_ROLE") + assert contracts.acl.getPermissionManager(ARAGON_KERNEL, app_manager_role) == AGENT, "AGENT should be the permission manager for APP_MANAGER_ROLE" + assert contracts.node_operators_registry.kernel() == ARAGON_KERNEL, "Node Operators Registry must use the correct kernel" + assert not contracts.acl.hasPermission(VOTING, ARAGON_KERNEL, app_manager_role), "VOTING should not have APP_MANAGER_ROLE before the upgrade" + assert not contracts.acl.hasPermission(AGENT, ARAGON_KERNEL, app_manager_role), "AGENT should not have APP_MANAGER_ROLE before the upgrade" + + # Steps 19-23: Check NOR and sDVT initial state + assert not contracts.acl.hasPermission(contracts.agent, contracts.kernel, app_manager_role), "Agent should not have APP_MANAGER_ROLE before upgrade" + assert contracts.node_operators_registry.getContractVersion() == 3, "Node Operators Registry version should be 3 before upgrade" + assert contracts.simple_dvt.getContractVersion() == 3, "Simple DVT version should be 3 before upgrade" + + # Step 24: Check CONFIG_MANAGER_ROLE initial state + config_manager_role = contracts.oracle_daemon_config.CONFIG_MANAGER_ROLE() + assert not contracts.oracle_daemon_config.hasRole(config_manager_role, contracts.agent), "Agent should not have CONFIG_MANAGER_ROLE on Oracle Daemon Config before upgrade" + + # Steps 25-27: Check Oracle Daemon Config variables to be removed + try: + contracts.oracle_daemon_config.get('NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP') + contracts.oracle_daemon_config.get('VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS') + contracts.oracle_daemon_config.get('VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS') + except Exception as e: + assert False, f"Expected variables to exist before removal: {e}" + + # Step 28: Check that EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS doesn't exist yet + try: + contracts.oracle_daemon_config.get('EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS') + assert False, "EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS should not exist before vote" + except Exception: + pass # Expected to fail + + # Step 29: Check CSM implementation initial state + assert csm_impl_before != CSM_IMPL_V2_ADDRESS, "CSM implementation should be different before vote" + + # Step 30: Check CSM finalizeUpgradeV2 initial state + with reverts(): + # The function should not exist yet + contracts.csm.getInitializedVersion() + + # CSM Step 32: Check CSAccounting implementation (pre-vote state) + assert cs_accounting_impl_before != CS_ACCOUNTING_IMPL_V2_ADDRESS, "CSAccounting implementation should be different before vote" + + # CSM Step 33: Check CSAccounting finalizeUpgradeV2 was not called (pre-vote state) + with reverts(): + # The function should not exist yet + contracts.cs_accounting.getInitializedVersion() + + # CSM Step 34: Check CSFeeOracle implementation (pre-vote state) + assert cs_fee_oracle_impl_before != CS_FEE_ORACLE_IMPL_V2_ADDRESS, "CSFeeOracle implementation should be different before vote" + + # CSM Step 35: Check CSFeeOracle finalizeUpgradeV2 was not called (pre-vote state) + assert contracts.cs_fee_oracle.getContractVersion() < CS_FEE_ORACLE_V2_VERSION, f"CSFeeOracle version should be less than {CS_FEE_ORACLE_V2_VERSION} before vote" + assert contracts.cs_fee_oracle.getConsensusVersion() < 3, "CSFeeOracle consensus version should be less than 3 before vote" + + # CSM Step 36: Check CSFeeDistributor implementation (pre-vote state) + assert cs_fee_distributor_impl_before != CS_FEE_DISTRIBUTOR_IMPL_V2_ADDRESS, "CSFeeDistributor implementation should be different before vote" + + # CSM Step 37: Check CSFeeDistributor finalizeUpgradeV2 was not called (pre-vote state) + with reverts(): + # The function should not exist yet + contracts.cs_fee_distributor.getInitializedVersion() + + # CSM Steps 38-40: CSAccounting roles (pre-vote state) + assert contracts.cs_accounting.hasRole(contracts.cs_accounting.SET_BOND_CURVE_ROLE(), contracts.csm.address), "CSM should have SET_BOND_CURVE_ROLE on CSAccounting before vote" + assert contracts.cs_accounting.hasRole(web3.keccak(text="RESET_BOND_CURVE_ROLE"), contracts.csm.address), "CSM should have RESET_BOND_CURVE_ROLE on CSAccounting before vote" + assert contracts.cs_accounting.hasRole(web3.keccak(text="RESET_BOND_CURVE_ROLE"), CSM_COMMITTEE_MS), "CSM committee should have RESET_BOND_CURVE_ROLE on CSAccounting before vote" + + # CSM Steps 41-42: CSM roles (pre-vote state) + assert not contracts.csm.hasRole(web3.keccak(text="CREATE_NODE_OPERATOR_ROLE"), cs_permissionless_gate.address), "Permissionless gate should not have CREATE_NODE_OPERATOR_ROLE on CSM before vote" + assert not contracts.csm.hasRole(web3.keccak(text="CREATE_NODE_OPERATOR_ROLE"), cs_vetted_gate.address), "Vetted gate should not have CREATE_NODE_OPERATOR_ROLE on CSM before vote" + + # CSM Step 43: CSAccounting bond curve role for vetted gate (pre-vote state) + assert not contracts.cs_accounting.hasRole(contracts.cs_accounting.SET_BOND_CURVE_ROLE(), cs_vetted_gate.address), "Vetted gate should not have SET_BOND_CURVE_ROLE on CSAccounting before vote" + + # CSM Steps 44-45: Verifier roles (pre-vote state) + assert contracts.csm.hasRole(contracts.csm.VERIFIER_ROLE(), contracts.cs_verifier.address), "Old verifier should have VERIFIER_ROLE on CSM before vote" + assert not contracts.csm.hasRole(contracts.csm.VERIFIER_ROLE(), cs_verifier_v2.address), "New verifier should not have VERIFIER_ROLE on CSM before vote" + + # CSM Steps 46-51: GateSeal roles (pre-vote state) + assert contracts.csm.hasRole(contracts.csm.PAUSE_ROLE(), CS_GATE_SEAL_ADDRESS), "Old GateSeal should have PAUSE_ROLE on CSM before vote" + assert contracts.cs_accounting.hasRole(contracts.cs_accounting.PAUSE_ROLE(), CS_GATE_SEAL_ADDRESS), "Old GateSeal should have PAUSE_ROLE on CSAccounting before vote" + assert contracts.cs_fee_oracle.hasRole(contracts.cs_fee_oracle.PAUSE_ROLE(), CS_GATE_SEAL_ADDRESS), "Old GateSeal should have PAUSE_ROLE on CSFeeOracle before vote" + + assert not contracts.csm.hasRole(contracts.csm.PAUSE_ROLE(), CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should not have PAUSE_ROLE on CSM before vote" + assert not contracts.cs_accounting.hasRole(contracts.cs_accounting.PAUSE_ROLE(), CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should not have PAUSE_ROLE on CSAccounting before vote" + assert not contracts.cs_fee_oracle.hasRole(contracts.cs_fee_oracle.PAUSE_ROLE(), CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should not have PAUSE_ROLE on CSFeeOracle before vote" + + # CSM Step 52: Staking Router CSM module state before vote (pre-vote state) + csm_module_before = contracts.staking_router.getStakingModule(CS_MODULE_ID) + csm_share_before = csm_module_before['stakeShareLimit'] + csm_priority_exit_threshold_before = csm_module_before['priorityExitShareThreshold'] + assert csm_share_before != CS_MODULE_NEW_TARGET_SHARE_BP, f"CSM share should not be {CS_MODULE_NEW_TARGET_SHARE_BP} before vote, current: {csm_share_before}" + assert csm_priority_exit_threshold_before != CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP, f"CSM priority exit threshold should not be {CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP} before vote, current: {csm_priority_exit_threshold_before}" + + # CSM Step 65: EasyTrack factories before vote (pre-vote state) + initial_factories = contracts.easy_track.getEVMScriptFactories() + assert EASYTRACK_CS_SET_VETTED_GATE_TREE_FACTORY not in initial_factories, "EasyTrack should not have CSMSetVettedGateTree factory before vote" + assert EASYTRACK_SDVT_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY not in initial_factories, "EasyTrack should not have SDVT validator exit request hashes factory before vote" + assert EASYTRACK_CURATED_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY not in initial_factories, "EasyTrack should not have Curated validator exit request hashes factory before vote" + + # Gate Seals: Check initial states before vote + assert contracts.withdrawal_queue.hasRole(contracts.withdrawal_queue.PAUSE_ROLE(), OLD_GATE_SEAL_ADDRESS), "Old GateSeal should have PAUSE_ROLE on WithdrawalQueue before vote" + assert contracts.validators_exit_bus_oracle.hasRole(contracts.validators_exit_bus_oracle.PAUSE_ROLE(), OLD_GATE_SEAL_ADDRESS), "Old GateSeal should have PAUSE_ROLE on VEBO before vote" + assert not contracts.withdrawal_queue.hasRole(contracts.withdrawal_queue.PAUSE_ROLE(), NEW_WQ_GATE_SEAL), "New WQ GateSeal should not have PAUSE_ROLE on WithdrawalQueue before vote" + assert not contracts.validators_exit_bus_oracle.hasRole(contracts.validators_exit_bus_oracle.PAUSE_ROLE(), NEW_TW_GATE_SEAL), "New TW GateSeal should not have PAUSE_ROLE on VEBO before vote" + assert not triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.PAUSE_ROLE(), NEW_TW_GATE_SEAL), "New TW GateSeal should not have PAUSE_ROLE on TWG before vote" + + # ResealManager: Check initial states before vote + assert not triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.PAUSE_ROLE(), RESEAL_MANAGER), "ResealManager should not have PAUSE_ROLE on TWG before vote" + assert not triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.RESUME_ROLE(), RESEAL_MANAGER), "ResealManager should not have RESUME_ROLE on TWG before vote" + + # START VOTE + if len(vote_ids_from_env) > 0: + (vote_id,) = vote_ids_from_env + else: + tx_params = {"from": LDO_HOLDER_ADDRESS_FOR_TESTS} + vote_id, _ = start_vote(tx_params, silent=True) + + vote_tx = helpers.execute_vote(accounts, vote_id, contracts.voting) + print(f"voteId = {vote_id}") + + proposal_id = vote_tx.events["ProposalSubmitted"][1]["proposalId"] + print(f"proposalId = {proposal_id}") + + chain.sleep(timelock.getAfterSubmitDelay() + 1) + dual_governance.scheduleProposal(proposal_id, {"from": stranger}) + + chain.sleep(timelock.getAfterScheduleDelay() + 1) + wait_for_noon_utc_to_satisfy_time_constrains() + + dg_tx = timelock.execute(proposal_id, {"from": stranger}) + + # --- VALIDATE EXECUTION RESULTS --- + + # Step 1: Validate Lido Locator implementation was updated + assert get_ossifiable_proxy_impl(contracts.lido_locator) == LIDO_LOCATOR_IMPL, "Locator implementation should be updated to the new value" + + # Step 2-3: Validate VEBO implementation was updated and configured + assert get_ossifiable_proxy_impl(contracts.validators_exit_bus_oracle) == VALIDATORS_EXIT_BUS_ORACLE_IMPL, "VEBO implementation should be updated" + assert contracts.validators_exit_bus_oracle.getMaxValidatorsPerReport() == 600, "VEBO max validators per report should be set to 600" + + # Validate exit request limit parameters from finalizeUpgrade_v2 call + exit_request_limits = contracts.validators_exit_bus_oracle.getExitRequestLimitFullInfo() + assert exit_request_limits[0] == 11200, "maxExitRequestsLimit should be 11200" + assert exit_request_limits[1] == 1, "exitsPerFrame should be 1" + assert exit_request_limits[2] == 48, "frameDurationInSec should be 48 hours in seconds" + + # Steps 4-6: Validate VEBO consensus version management + assert not contracts.validators_exit_bus_oracle.hasRole(contracts.validators_exit_bus_oracle.MANAGE_CONSENSUS_VERSION_ROLE(), contracts.agent), "Agent should not have MANAGE_CONSENSUS_VERSION_ROLE on VEBO" + assert contracts.validators_exit_bus_oracle.getConsensusVersion() == VEBO_CONSENSUS_VERSION, f"VEBO consensus version should be set to {VEBO_CONSENSUS_VERSION}" + + # Steps 7-8: Validate TWG roles + assert triggerable_withdrawals_gateway.hasRole(add_full_withdrawal_request_role, cs_ejector), "CS Ejector should have ADD_FULL_WITHDRAWAL_REQUEST_ROLE on TWG" + assert triggerable_withdrawals_gateway.hasRole(add_full_withdrawal_request_role, contracts.validators_exit_bus_oracle), "VEBO should have ADD_FULL_WITHDRAWAL_REQUEST_ROLE on TWG" + + # Step 9: Validate EasyTrack VEB SUBMIT_REPORT_HASH_ROLE + assert contracts.validators_exit_bus_oracle.hasRole(submit_report_hash_role, EASYTRACK_EVMSCRIPT_EXECUTOR), "EasyTrack executor should have SUBMIT_REPORT_HASH_ROLE on VEBO" + + # Step 10: Validate DualGovernance tiebreaker connection + final_tiebreaker_details = contracts.dual_governance.getTiebreakerDetails() + final_tiebreakers = final_tiebreaker_details[3] # sealableWithdrawalBlockers + assert TRIGGERABLE_WITHDRAWALS_GATEWAY in final_tiebreakers, "TWG should be in tiebreaker list after upgrade" + + # Steps 9-10: Validate Withdrawal Vault upgrade + assert get_wv_contract_proxy_impl(contracts.withdrawal_vault) == WITHDRAWAL_VAULT_IMPL, "Withdrawal Vault implementation should be updated" + assert contracts.withdrawal_vault.getContractVersion() == 2, "Withdrawal Vault version should be 2 after finalizeUpgrade_v2" + + # Steps 11-14: Validate Accounting Oracle upgrade + assert get_ossifiable_proxy_impl(contracts.accounting_oracle) == ACCOUNTING_ORACLE_IMPL, "Accounting Oracle implementation should be updated" + assert not contracts.accounting_oracle.hasRole(contracts.accounting_oracle.MANAGE_CONSENSUS_VERSION_ROLE(), contracts.agent), "Agent should not have MANAGE_CONSENSUS_VERSION_ROLE on AO" + assert contracts.accounting_oracle.getConsensusVersion() == AO_CONSENSUS_VERSION, f"AO consensus version should be set to {AO_CONSENSUS_VERSION}" + + # Step 17: Validate AO finalizeUpgrade_v3 + assert contracts.accounting_oracle.getContractVersion() == 3, "AO contract version should be 3 after finalizeUpgrade_v3" + + # Steps 15-17: Validate Staking Router upgrade + assert get_ossifiable_proxy_impl(contracts.staking_router) == STAKING_ROUTER_IMPL, "Staking Router implementation should be updated" + assert contracts.staking_router.hasRole(contracts.staking_router.REPORT_VALIDATOR_EXITING_STATUS_ROLE(), VALIDATOR_EXIT_VERIFIER), "ValidatorExitVerifier should have REPORT_VALIDATOR_EXITING_STATUS_ROLE on SR" + assert contracts.staking_router.hasRole(contracts.staking_router.REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE(), triggerable_withdrawals_gateway), "TWG should have REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE on SR" + + # Steps 18-23: Validate NOR and sDVT updates + assert not contracts.acl.hasPermission(contracts.agent, contracts.kernel, app_manager_role), "Agent should not have APP_MANAGER_ROLE after vote" + assert contracts.node_operators_registry.getContractVersion() == 4, "Node Operators Registry version should be updated to 4" + assert contracts.simple_dvt.getContractVersion() == 4, "Simple DVT version should be updated to 4" + assert contracts.node_operators_registry.exitDeadlineThreshold(0) == NOR_EXIT_DEADLINE_IN_SEC, "NOR exit deadline threshold should be set correctly" + assert contracts.simple_dvt.exitDeadlineThreshold(0) == NOR_EXIT_DEADLINE_IN_SEC, "sDVT exit deadline threshold should be set correctly" + + # Steps 24-28: Validate Oracle Daemon Config changes + assert not contracts.oracle_daemon_config.hasRole(config_manager_role, contracts.agent), "Agent should not have CONFIG_MANAGER_ROLE on Oracle Daemon Config" + for var_name in ['NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP', 'VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS', 'VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS']: + try: + contracts.oracle_daemon_config.get(var_name) + assert False, f"Variable {var_name} should have been removed" + except Exception: + pass # Expected to fail - variable should be removed + assert convert.to_uint(contracts.oracle_daemon_config.get('EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS')) == EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS, f"EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS should be set to {EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS}" + + # Step 29: Validate CSM implementation upgrade + check_proxy_implementation(contracts.csm.address, CSM_IMPL_V2_ADDRESS) + + # Step 30: Validate CSM finalizeUpgradeV2 was called + assert contracts.csm.getInitializedVersion() == CSM_V2_VERSION, f"CSM version should be {CSM_V2_VERSION} after vote" + + # Step 31: Validate CSAccounting implementation upgrade + check_proxy_implementation(contracts.cs_accounting.address, CS_ACCOUNTING_IMPL_V2_ADDRESS) + + # Step 32: Validate CSAccounting finalizeUpgradeV2 was called with bond curves + assert contracts.cs_accounting.getInitializedVersion() == CS_ACCOUNTING_V2_VERSION, f"CSAccounting version should be {CS_ACCOUNTING_V2_VERSION} after vote" + + # Step 33: Validate CSFeeOracle implementation upgrade + check_proxy_implementation(contracts.cs_fee_oracle.address, CS_FEE_ORACLE_IMPL_V2_ADDRESS) + + # Step 34: Validate CSFeeOracle finalizeUpgradeV2 was called with consensus version 3 + assert contracts.cs_fee_oracle.getContractVersion() == CS_FEE_ORACLE_V2_VERSION, f"CSFeeOracle version should be {CS_FEE_ORACLE_V2_VERSION} after vote" + assert contracts.cs_fee_oracle.getConsensusVersion() == CSM_CONSENSUS_VERSION, "CSFeeOracle consensus version should be 3 after vote" + + # Step 35: Validate CSFeeDistributor implementation upgrade + check_proxy_implementation(contracts.cs_fee_distributor.address, CS_FEE_DISTRIBUTOR_IMPL_V2_ADDRESS) + + # Step 36: Validate CSFeeDistributor finalizeUpgradeV2 was called + assert contracts.cs_fee_distributor.getInitializedVersion() == CS_FEE_DISTRIBUTOR_V2_VERSION, f"CSFeeDistributor version should be {CS_FEE_DISTRIBUTOR_V2_VERSION} after vote" + + # Step 37: Validate SET_BOND_CURVE_ROLE was revoked from CSM on CSAccounting + assert not contracts.cs_accounting.hasRole(contracts.cs_accounting.SET_BOND_CURVE_ROLE(), contracts.csm.address), "CSM should not have SET_BOND_CURVE_ROLE on CSAccounting after vote" + + # Step 38: Validate RESET_BOND_CURVE_ROLE was revoked from CSM on CSAccounting + assert not contracts.cs_accounting.hasRole(web3.keccak(text="RESET_BOND_CURVE_ROLE"), contracts.csm.address), "CSM should not have RESET_BOND_CURVE_ROLE on CSAccounting after vote" + + # Step 39: Validate RESET_BOND_CURVE_ROLE was revoked from CSM committee on CSAccounting + assert not contracts.cs_accounting.hasRole(web3.keccak(text="RESET_BOND_CURVE_ROLE"), CSM_COMMITTEE_MS), "CSM committee should not have RESET_BOND_CURVE_ROLE on CSAccounting after vote" + + # Step 40: Validate CREATE_NODE_OPERATOR_ROLE was granted to permissionless gate on CSM + assert contracts.csm.hasRole(contracts.csm.CREATE_NODE_OPERATOR_ROLE(), cs_permissionless_gate.address), "Permissionless gate should have CREATE_NODE_OPERATOR_ROLE on CSM after vote" + + # Step 41: Validate CREATE_NODE_OPERATOR_ROLE was granted to vetted gate on CSM + assert contracts.csm.hasRole(contracts.csm.CREATE_NODE_OPERATOR_ROLE(), cs_vetted_gate.address), "Vetted gate should have CREATE_NODE_OPERATOR_ROLE on CSM after vote" + + # Step 42: Validate SET_BOND_CURVE_ROLE was granted to vetted gate on CSAccounting + assert contracts.cs_accounting.hasRole(contracts.cs_accounting.SET_BOND_CURVE_ROLE(), cs_vetted_gate.address), "Vetted gate should have SET_BOND_CURVE_ROLE on CSAccounting after vote" + + # Step 43: Validate VERIFIER_ROLE was revoked from old verifier on CSM + assert not contracts.csm.hasRole(contracts.csm.VERIFIER_ROLE(), contracts.cs_verifier.address), "Old verifier should not have VERIFIER_ROLE on CSM after vote" + + # Step 44: Validate VERIFIER_ROLE was granted to new verifier on CSM + assert contracts.csm.hasRole(contracts.csm.VERIFIER_ROLE(), cs_verifier_v2.address), "New verifier should have VERIFIER_ROLE on CSM after vote" + + # Step 45: Validate PAUSE_ROLE was revoked from old GateSeal on CSM + assert not contracts.csm.hasRole(contracts.csm.PAUSE_ROLE(), CS_GATE_SEAL_ADDRESS), "Old GateSeal should not have PAUSE_ROLE on CSM after vote" + + # Step 46: Validate PAUSE_ROLE was revoked from old GateSeal on CSAccounting + assert not contracts.cs_accounting.hasRole(contracts.cs_accounting.PAUSE_ROLE(), CS_GATE_SEAL_ADDRESS), "Old GateSeal should not have PAUSE_ROLE on CSAccounting after vote" + + # Step 47: Validate PAUSE_ROLE was revoked from old GateSeal on CSFeeOracle + assert not contracts.cs_fee_oracle.hasRole(contracts.cs_fee_oracle.PAUSE_ROLE(), CS_GATE_SEAL_ADDRESS), "Old GateSeal should not have PAUSE_ROLE on CSFeeOracle after vote" + + # Step 48: Validate PAUSE_ROLE was granted to new GateSeal on CSM + assert contracts.csm.hasRole(contracts.csm.PAUSE_ROLE(), CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should have PAUSE_ROLE on CSM after vote" + + # Step 49: Validate PAUSE_ROLE was granted to new GateSeal on CSAccounting + assert contracts.cs_accounting.hasRole(contracts.cs_accounting.PAUSE_ROLE(), CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should have PAUSE_ROLE on CSAccounting after vote" + + # Step 50: Validate PAUSE_ROLE was granted to new GateSeal on CSFeeOracle + assert contracts.cs_fee_oracle.hasRole(contracts.cs_fee_oracle.PAUSE_ROLE(), CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should have PAUSE_ROLE on CSFeeOracle after vote" + + # Step 50-52: Check add ICS Bond Curve to CSAccounting + assert not contracts.cs_accounting.hasRole(contracts.cs_accounting.MANAGE_BOND_CURVES_ROLE(), contracts.agent), "Agent should not have MANAGE_BOND_CURVES_ROLE on CSAccounting after vote" + assert contracts.cs_accounting.getCurvesCount() == len(CS_CURVES) + 1, "CSAccounting should have legacy bond curves and ICS Bond Curve after vote" + + # Step 53: Increase CSM share in Staking Router + csm_module_after = contracts.staking_router.getStakingModule(CS_MODULE_ID) + csm_share_after = csm_module_after['stakeShareLimit'] + assert csm_share_after == CS_MODULE_NEW_TARGET_SHARE_BP, f"CSM share should be {CS_MODULE_NEW_TARGET_SHARE_BP} after vote, but got {csm_share_after}" + + csm_priority_exit_threshold_after = csm_module_after['priorityExitShareThreshold'] + assert csm_priority_exit_threshold_after == CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP, f"CSM priority exit threshold should be {CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP} after vote, but got {csm_priority_exit_threshold_after}" + + + # Steps 58-62: Validate Gate Seals updates + assert not contracts.withdrawal_queue.hasRole(contracts.withdrawal_queue.PAUSE_ROLE(), OLD_GATE_SEAL_ADDRESS), "Old GateSeal should not have PAUSE_ROLE on WithdrawalQueue after vote" + assert not contracts.validators_exit_bus_oracle.hasRole(contracts.validators_exit_bus_oracle.PAUSE_ROLE(), OLD_GATE_SEAL_ADDRESS), "Old GateSeal should not have PAUSE_ROLE on VEBO after vote" + assert contracts.withdrawal_queue.hasRole(contracts.withdrawal_queue.PAUSE_ROLE(), NEW_WQ_GATE_SEAL), "New WQ GateSeal should have PAUSE_ROLE on WithdrawalQueue after vote" + assert contracts.validators_exit_bus_oracle.hasRole(contracts.validators_exit_bus_oracle.PAUSE_ROLE(), NEW_TW_GATE_SEAL), "New TW GateSeal should have PAUSE_ROLE on VEBO after vote" + assert triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.PAUSE_ROLE(), NEW_TW_GATE_SEAL), "New TW GateSeal should have PAUSE_ROLE on TWG after vote" + + # Steps 63-64: Validate ResealManager roles + assert triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.PAUSE_ROLE(), RESEAL_MANAGER), "ResealManager should have PAUSE_ROLE on TWG after vote" + assert triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.RESUME_ROLE(), RESEAL_MANAGER), "ResealManager should have RESUME_ROLE on TWG after vote" + + # Step 65: Add EasyTrack factory for CSSetVettedGateTree + new_factories = contracts.easy_track.getEVMScriptFactories() + assert EASYTRACK_CS_SET_VETTED_GATE_TREE_FACTORY in new_factories, "EasyTrack should have CSSetVettedGateTree factory after vote" + + # Steps 66-67: Validate EasyTrack factories for validator exit request hashes + assert EASYTRACK_SDVT_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY in new_factories, "EasyTrack should have SDVT validator exit request hashes factory after vote" + assert EASYTRACK_CURATED_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY in new_factories, "EasyTrack should have Curated validator exit request hashes factory after vote" + + # --- VALIDATE EVENTS --- + + voting_events = group_voting_events_from_receipt(vote_tx) + dg_execution_events = group_dg_events_from_receipt(dg_tx, timelock=TIMELOCK, admin_executor=DUAL_GOVERNANCE_EXECUTORS[0]) + + # Validate voting events structure + assert len(voting_events) == 4, "Unexpected number of voting events" + dg_voting_event, dg_bypass_voting_event1, dg_bypass_voting_event2, dg_bypass_voting_event3 = voting_events + + # Validate DG execution events structure + assert len(dg_execution_events) == 66, "Unexpected number of dual governance events" + + + # Main DG voting event validation + validate_dual_governance_submit_event( + dg_voting_event, + proposal_id, + proposer=VOTING, + executor=DUAL_GOVERNANCE_EXECUTORS[0], + ) + + # Validate EasyTrack bypass events for new factories + validate_evmscript_factory_added_event( + event=dg_bypass_voting_event1, + p=EVMScriptFactoryAdded( + factory_addr=EASYTRACK_CS_SET_VETTED_GATE_TREE_FACTORY, + permissions=create_permissions(interface.CSVettedGate(CS_VETTED_GATE_ADDRESS), "setTreeParams") + ), + emitted_by=contracts.easy_track, + ) + + validate_evmscript_factory_added_event( + event=dg_bypass_voting_event2, + p=EVMScriptFactoryAdded( + factory_addr=EASYTRACK_SDVT_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY, + permissions=create_permissions(contracts.validators_exit_bus_oracle, "submitExitRequestsHash") + ), + emitted_by=contracts.easy_track, + ) + + validate_evmscript_factory_added_event( + event=dg_bypass_voting_event3, + p=EVMScriptFactoryAdded( + factory_addr=EASYTRACK_CURATED_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY, + permissions=create_permissions(contracts.validators_exit_bus_oracle, "submitExitRequestsHash") + ), + emitted_by=contracts.easy_track, + ) + + # === DG EXECUTION EVENTS VALIDATION === + + # 0. Lido Locator upgrade events + validate_proxy_upgrade_event(dg_execution_events[0], LIDO_LOCATOR_IMPL, emitted_by=contracts.lido_locator) + + # 1. VEBO upgrade events + validate_proxy_upgrade_event(dg_execution_events[1], VALIDATORS_EXIT_BUS_ORACLE_IMPL, emitted_by=contracts.validators_exit_bus_oracle) + + # 2. VEBO finalize upgrade events + validate_contract_version_set_event(dg_execution_events[2], version=2, emitted_by=contracts.validators_exit_bus_oracle) + assert 'ExitRequestsLimitSet' in dg_execution_events[2], "ExitRequestsLimitSet event not found" + assert dg_execution_events[2]['ExitRequestsLimitSet'][0]['maxExitRequestsLimit'] == 11200, "Wrong maxExitRequestsLimit" + assert dg_execution_events[2]['ExitRequestsLimitSet'][0]['exitsPerFrame'] == 1, "Wrong exitsPerFrame" + assert dg_execution_events[2]['ExitRequestsLimitSet'][0]['frameDurationInSec'] == 48, "Wrong frameDurationInSec" + + # 3. Grant VEBO MANAGE_CONSENSUS_VERSION_ROLE to Agent + validate_role_grant_event( + dg_execution_events[3], + role_hash=web3.keccak(text="MANAGE_CONSENSUS_VERSION_ROLE").hex(), + account=contracts.agent.address, + emitted_by=contracts.validators_exit_bus_oracle + ) + + # 4. Set VEBO consensus version to 4 + validate_consensus_version_set_event( + dg_execution_events[4], + new_version=4, + prev_version=3, + emitted_by=contracts.validators_exit_bus_oracle + ) + + # 5. Revoke VEBO MANAGE_CONSENSUS_VERSION_ROLE from Agent + validate_role_revoke_event( + dg_execution_events[5], + role_hash=web3.keccak(text="MANAGE_CONSENSUS_VERSION_ROLE").hex(), + account=contracts.agent.address, + emitted_by=contracts.validators_exit_bus_oracle + ) + + # 6. Grant VEBO SUBMIT_REPORT_HASH_ROLE to EasyTrack executor + validate_role_grant_event( + dg_execution_events[6], + role_hash=web3.keccak(text="SUBMIT_REPORT_HASH_ROLE").hex(), + account=EASYTRACK_EVMSCRIPT_EXECUTOR, + emitted_by=contracts.validators_exit_bus_oracle + ) + + # 7. Grant TWG ADD_FULL_WITHDRAWAL_REQUEST_ROLE to CS Ejector + validate_role_grant_event( + dg_execution_events[7], + role_hash=web3.keccak(text="ADD_FULL_WITHDRAWAL_REQUEST_ROLE").hex(), + account=CS_EJECTOR_ADDRESS, + emitted_by=triggerable_withdrawals_gateway + ) + + # 8. Grant TWG ADD_FULL_WITHDRAWAL_REQUEST_ROLE to VEBO + validate_role_grant_event( + dg_execution_events[8], + role_hash=web3.keccak(text="ADD_FULL_WITHDRAWAL_REQUEST_ROLE").hex(), + account=contracts.validators_exit_bus_oracle.address, + emitted_by=triggerable_withdrawals_gateway + ) + + # 9. Connect TWG to Dual Governance tiebreaker + assert 'SealableWithdrawalBlockerAdded' in dg_execution_events[9], "SealableWithdrawalBlockerAdded event not found" + assert dg_execution_events[9]['SealableWithdrawalBlockerAdded'][0]['sealable'] == TRIGGERABLE_WITHDRAWALS_GATEWAY, "Wrong sealableWithdrawalBlocker" + + # 10. Update WithdrawalVault implementation + validate_proxy_upgrade_event(dg_execution_events[10], WITHDRAWAL_VAULT_IMPL, emitted_by=contracts.withdrawal_vault) + + # 11. Call finalizeUpgrade_v2 on WithdrawalVault + validate_contract_version_set_event(dg_execution_events[11], version=2, emitted_by=contracts.withdrawal_vault) + + # 12. Update AO implementation + validate_proxy_upgrade_event(dg_execution_events[12], ACCOUNTING_ORACLE_IMPL, emitted_by=contracts.accounting_oracle) + + # 13. Grant AO MANAGE_CONSENSUS_VERSION_ROLE to the AGENT + validate_role_grant_event( + dg_execution_events[13], + role_hash=web3.keccak(text="MANAGE_CONSENSUS_VERSION_ROLE").hex(), + account=contracts.agent.address, + emitted_by=contracts.accounting_oracle + ) + + # 14. Bump AO consensus version to 4 + validate_consensus_version_set_event( + dg_execution_events[14], + new_version=4, + prev_version=3, + emitted_by=contracts.accounting_oracle + ) + + # 15. Revoke AO MANAGE_CONSENSUS_VERSION_ROLE from the AGENT + validate_role_revoke_event( + dg_execution_events[15], + role_hash=web3.keccak(text="MANAGE_CONSENSUS_VERSION_ROLE").hex(), + account=contracts.agent.address, + emitted_by=contracts.accounting_oracle + ) + + # 16. Call finalizeUpgrade_v3() on AO + validate_contract_version_set_event(dg_execution_events[16], version=3, emitted_by=contracts.accounting_oracle) + + # 17. Update SR implementation + validate_proxy_upgrade_event(dg_execution_events[17], STAKING_ROUTER_IMPL, emitted_by=contracts.staking_router) + + # 18. Call finalizeUpgrade_v3() on SR + validate_contract_version_set_event(dg_execution_events[18], version=3, emitted_by=contracts.staking_router) + + # 19. Grant SR REPORT_VALIDATOR_EXITING_STATUS_ROLE to ValidatorExitVerifier + validate_role_grant_event( + dg_execution_events[19], + role_hash=web3.keccak(text="REPORT_VALIDATOR_EXITING_STATUS_ROLE").hex(), + account=VALIDATOR_EXIT_VERIFIER, + emitted_by=contracts.staking_router + ) + + # 20. Grant SR REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE to TWG + validate_role_grant_event( + dg_execution_events[20], + role_hash=web3.keccak(text="REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE").hex(), + account=triggerable_withdrawals_gateway.address, + emitted_by=contracts.staking_router + ) + + # 21. Grant APP_MANAGER_ROLE on Kernel to Voting + assert 'SetPermission' in dg_execution_events[21] + assert dg_execution_events[21]['SetPermission'][0]['allowed'] is True + + # 22. Set new implementation for NOR + assert 'SetApp' in dg_execution_events[22] + + # 23. Finalize upgrade for NOR + validate_contract_version_set_event(dg_execution_events[23], version=4, emitted_by=contracts.node_operators_registry) + assert 'ExitDeadlineThresholdChanged' in dg_execution_events[23] + assert dg_execution_events[23]['ExitDeadlineThresholdChanged'][0]['threshold'] == NOR_EXIT_DEADLINE_IN_SEC + + # 24. Set new implementation for sDVT + assert 'SetApp' in dg_execution_events[24] + + # 25. Finalize upgrade for sDVT + validate_contract_version_set_event(dg_execution_events[25], version=4, emitted_by=contracts.simple_dvt) + assert 'ExitDeadlineThresholdChanged' in dg_execution_events[25] + assert dg_execution_events[25]['ExitDeadlineThresholdChanged'][0]['threshold'] == NOR_EXIT_DEADLINE_IN_SEC + + # 26. Revoke APP_MANAGER_ROLE on Kernel from Voting + assert 'SetPermission' in dg_execution_events[26] + assert dg_execution_events[26]['SetPermission'][0]['allowed'] is False + + # 27. Grant CONFIG_MANAGER_ROLE on OracleDaemonConfig to Agent + validate_role_grant_event( + dg_execution_events[27], + role_hash=contracts.oracle_daemon_config.CONFIG_MANAGER_ROLE().hex(), + account=contracts.agent.address, + emitted_by=contracts.oracle_daemon_config + ) + + # 28. Unset NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP + assert 'ConfigValueUnset' in dg_execution_events[28] + assert 'NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP' in dg_execution_events[28]['ConfigValueUnset'][0]['key'] + + # 29. Unset VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS + assert 'ConfigValueUnset' in dg_execution_events[29] + assert 'VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS' in dg_execution_events[29]['ConfigValueUnset'][0]['key'] + + # 30. Unset VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS + assert 'ConfigValueUnset' in dg_execution_events[30] + assert 'VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS' in dg_execution_events[30]['ConfigValueUnset'][0]['key'] + + # 31. Set EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS + assert 'ConfigValueSet' in dg_execution_events[31] + assert 'EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS' in dg_execution_events[31]['ConfigValueSet'][0]['key'] + assert convert.to_int(dg_execution_events[31]['ConfigValueSet'][0]['value']) == EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS + + # 32. Revoke CONFIG_MANAGER_ROLE from the AGENT + validate_role_revoke_event( + dg_execution_events[32], + role_hash=contracts.oracle_daemon_config.CONFIG_MANAGER_ROLE().hex(), + account=contracts.agent.address, + emitted_by=contracts.oracle_daemon_config + ) + + # 33. CSM implementation upgrade + validate_proxy_upgrade_event(dg_execution_events[33], CSM_IMPL_V2_ADDRESS, emitted_by=contracts.csm) + + # 34. CSM finalize upgrade validation + assert 'Initialized' in dg_execution_events[34] + assert dg_execution_events[34]['Initialized'][0]['version'] == CSM_V2_VERSION + + # 35. CSAccounting implementation upgrade + validate_proxy_upgrade_event(dg_execution_events[35], CS_ACCOUNTING_IMPL_V2_ADDRESS, emitted_by=contracts.cs_accounting) + + # 36. CSAccounting finalize upgrade with bond curves + assert 'BondCurveAdded' in dg_execution_events[36] + assert len(dg_execution_events[36]['BondCurveAdded']) == len(CS_CURVES) + assert 'Initialized' in dg_execution_events[36] + assert dg_execution_events[36]['Initialized'][0]['version'] == CS_ACCOUNTING_V2_VERSION + + # 37. CSFeeOracle implementation upgrade + validate_proxy_upgrade_event(dg_execution_events[37], CS_FEE_ORACLE_IMPL_V2_ADDRESS, emitted_by=contracts.cs_fee_oracle) + + # 38. CSFeeOracle finalize upgrade with consensus version + validate_consensus_version_set_event(dg_execution_events[38], new_version=3, prev_version=2, emitted_by=contracts.cs_fee_oracle) + validate_contract_version_set_event(dg_execution_events[38], version=CS_FEE_ORACLE_V2_VERSION, emitted_by=contracts.cs_fee_oracle) + + # 39. CSFeeDistributor implementation upgrade + validate_proxy_upgrade_event(dg_execution_events[39], CS_FEE_DISTRIBUTOR_IMPL_V2_ADDRESS, emitted_by=contracts.cs_fee_distributor) + + # 40. CSFeeDistributor finalize upgrade + assert 'RebateRecipientSet' in dg_execution_events[40] + assert 'Initialized' in dg_execution_events[40] + assert dg_execution_events[40]['Initialized'][0]['version'] == CS_FEE_DISTRIBUTOR_V2_VERSION + + # 41. Revoke SET_BOND_CURVE_ROLE from CSM on CSAccounting + validate_role_revoke_event( + dg_execution_events[41], + role_hash=contracts.cs_accounting.SET_BOND_CURVE_ROLE().hex(), + account=contracts.csm.address, + emitted_by=contracts.cs_accounting + ) + + # 42. Revoke RESET_BOND_CURVE_ROLE from CSM on CSAccounting + validate_role_revoke_event( + dg_execution_events[42], + role_hash=web3.keccak(text="RESET_BOND_CURVE_ROLE").hex(), + account=contracts.csm.address, + emitted_by=contracts.cs_accounting + ) + + # 43. Revoke RESET_BOND_CURVE_ROLE from CSM committee on CSAccounting + validate_role_revoke_event( + dg_execution_events[43], + role_hash=web3.keccak(text="RESET_BOND_CURVE_ROLE").hex(), + account=CSM_COMMITTEE_MS, + emitted_by=contracts.cs_accounting + ) + + # 44. Grant CREATE_NODE_OPERATOR_ROLE to permissionless gate on CSM + validate_role_grant_event( + dg_execution_events[44], + role_hash=contracts.csm.CREATE_NODE_OPERATOR_ROLE().hex(), + account=CS_PERMISSIONLESS_GATE_ADDRESS, + emitted_by=contracts.csm + ) + + # 45. Grant CREATE_NODE_OPERATOR_ROLE to vetted gate on CSM + validate_role_grant_event( + dg_execution_events[45], + role_hash=contracts.csm.CREATE_NODE_OPERATOR_ROLE().hex(), + account=CS_VETTED_GATE_ADDRESS, + emitted_by=contracts.csm + ) + + # 46. Grant SET_BOND_CURVE_ROLE to vetted gate on CSAccounting + validate_role_grant_event( + dg_execution_events[46], + role_hash=contracts.cs_accounting.SET_BOND_CURVE_ROLE().hex(), + account=CS_VETTED_GATE_ADDRESS, + emitted_by=contracts.cs_accounting + ) + + # 47. Revoke VERIFIER_ROLE from old verifier on CSM + validate_role_revoke_event( + dg_execution_events[47], + role_hash=contracts.csm.VERIFIER_ROLE().hex(), + account=contracts.cs_verifier.address, + emitted_by=contracts.csm + ) + + # 48. Grant VERIFIER_ROLE to new verifier on CSM + validate_role_grant_event( + dg_execution_events[48], + role_hash=contracts.csm.VERIFIER_ROLE().hex(), + account=CS_VERIFIER_V2_ADDRESS, + emitted_by=contracts.csm + ) + + # 49. Revoke PAUSE_ROLE from old GateSeal on CSM + validate_role_revoke_event( + dg_execution_events[49], + role_hash=contracts.csm.PAUSE_ROLE().hex(), + account=CS_GATE_SEAL_ADDRESS, + emitted_by=contracts.csm + ) + + # 50. Revoke PAUSE_ROLE from old GateSeal on CSAccounting + validate_role_revoke_event( + dg_execution_events[50], + role_hash=contracts.cs_accounting.PAUSE_ROLE().hex(), + account=CS_GATE_SEAL_ADDRESS, + emitted_by=contracts.cs_accounting + ) + + # 51. Revoke PAUSE_ROLE from old GateSeal on CSFeeOracle + validate_role_revoke_event( + dg_execution_events[51], + role_hash=contracts.cs_fee_oracle.PAUSE_ROLE().hex(), + account=CS_GATE_SEAL_ADDRESS, + emitted_by=contracts.cs_fee_oracle + ) + + # 52. Grant PAUSE_ROLE to new GateSeal on CSM + validate_role_grant_event( + dg_execution_events[52], + role_hash=contracts.csm.PAUSE_ROLE().hex(), + account=CS_GATE_SEAL_V2_ADDRESS, + emitted_by=contracts.csm + ) + + # 53. Grant PAUSE_ROLE to new GateSeal on CSAccounting + validate_role_grant_event( + dg_execution_events[53], + role_hash=contracts.cs_accounting.PAUSE_ROLE().hex(), + account=CS_GATE_SEAL_V2_ADDRESS, + emitted_by=contracts.cs_accounting + ) + + # 54. Grant PAUSE_ROLE to new GateSeal on CSFeeOracle + validate_role_grant_event( + dg_execution_events[54], + role_hash=contracts.cs_fee_oracle.PAUSE_ROLE().hex(), + account=CS_GATE_SEAL_V2_ADDRESS, + emitted_by=contracts.cs_fee_oracle + ) + + # 55. Grant MANAGE_BOND_CURVES_ROLE to agent on CSAccounting + validate_role_grant_event( + dg_execution_events[55], + role_hash=contracts.cs_accounting.MANAGE_BOND_CURVES_ROLE().hex(), + account=contracts.agent.address, + emitted_by=contracts.cs_accounting + ) + + # 56. Add ICS bond curve + ics_curve_id = len(CS_CURVES) + validate_bond_curve_added_event(dg_execution_events[56], curve_id=ics_curve_id, emitted_by=contracts.cs_accounting) + + # 57. Revoke MANAGE_BOND_CURVES_ROLE from agent on CSAccounting + validate_role_revoke_event( + dg_execution_events[57], + role_hash=contracts.cs_accounting.MANAGE_BOND_CURVES_ROLE().hex(), + account=contracts.agent.address, + emitted_by=contracts.cs_accounting + ) + + # 58. Increase CSM share in Staking Router + validate_staking_module_update_event( + dg_execution_events[58], + module_id=CS_MODULE_ID, + share_limit=CS_MODULE_NEW_TARGET_SHARE_BP, + priority_share_threshold=CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP, + module_fee_points_bp=CS_MODULE_MODULE_FEE_BP, + treasury_fee_points_bp=CS_MODULE_TREASURY_FEE_BP, + max_deposits_per_block=CS_MODULE_MAX_DEPOSITS_PER_BLOCK, + min_deposit_block_distance=CS_MODULE_MIN_DEPOSIT_BLOCK_DISTANCE, + emitted_by=contracts.staking_router + ) + + # 59-65. Gate Seals and ResealManager role updates + # 59. Revoke PAUSE_ROLE on WithdrawalQueue from the old GateSeal + validate_role_revoke_event( + dg_execution_events[59], + role_hash=contracts.withdrawal_queue.PAUSE_ROLE().hex(), + account=OLD_GATE_SEAL_ADDRESS, + emitted_by=contracts.withdrawal_queue + ) + + # 60. Revoke PAUSE_ROLE on ValidatorsExitBusOracle from the old GateSeal + validate_role_revoke_event( + dg_execution_events[60], + role_hash=contracts.validators_exit_bus_oracle.PAUSE_ROLE().hex(), + account=OLD_GATE_SEAL_ADDRESS, + emitted_by=contracts.validators_exit_bus_oracle + ) + + # 61. Grant PAUSE_ROLE on WithdrawalQueue to the new WithdrawalQueue GateSeal + validate_role_grant_event( + dg_execution_events[61], + role_hash=contracts.withdrawal_queue.PAUSE_ROLE().hex(), + account=NEW_WQ_GATE_SEAL, + emitted_by=contracts.withdrawal_queue + ) + + # 62. Grant PAUSE_ROLE on ValidatorsExitBusOracle to the new Triggerable Withdrawals GateSeal + validate_role_grant_event( + dg_execution_events[62], + role_hash=contracts.validators_exit_bus_oracle.PAUSE_ROLE().hex(), + account=NEW_TW_GATE_SEAL, + emitted_by=contracts.validators_exit_bus_oracle + ) + + # 63. Grant PAUSE_ROLE on TriggerableWithdrawalsGateway to the new Triggerable Withdrawals GateSeal + validate_role_grant_event( + dg_execution_events[63], + role_hash=triggerable_withdrawals_gateway.PAUSE_ROLE().hex(), + account=NEW_TW_GATE_SEAL, + emitted_by=triggerable_withdrawals_gateway + ) + + # 64. Grant PAUSE_ROLE on TriggerableWithdrawalsGateway to ResealManager + validate_role_grant_event( + dg_execution_events[64], + role_hash=triggerable_withdrawals_gateway.PAUSE_ROLE().hex(), + account=RESEAL_MANAGER, + emitted_by=triggerable_withdrawals_gateway + ) + + # 65. Grant RESUME_ROLE on TriggerableWithdrawalsGateway to ResealManager + validate_role_grant_event( + dg_execution_events[65], + role_hash=triggerable_withdrawals_gateway.RESUME_ROLE().hex(), + account=RESEAL_MANAGER, + emitted_by=triggerable_withdrawals_gateway + ) From dc69058b3cc25923c5d149ffe9259e6571cc7c61 Mon Sep 17 00:00:00 2001 From: Eddort Date: Fri, 8 Aug 2025 16:52:01 +0200 Subject: [PATCH 10/28] wip: and todos from madlabman --- scripts/vote_tw_csm2_mainnet.py | 17 +++--- tests/test_vote_tw_csm2_mainnet.py | 85 +++++++++++++++++------------- 2 files changed, 56 insertions(+), 46 deletions(-) diff --git a/scripts/vote_tw_csm2_mainnet.py b/scripts/vote_tw_csm2_mainnet.py index 9e7e28dc8..28f7c3674 100644 --- a/scripts/vote_tw_csm2_mainnet.py +++ b/scripts/vote_tw_csm2_mainnet.py @@ -83,14 +83,13 @@ 67. Add CSSetVettedGateTree factory to EasyTrack with permissions 68. Add `SubmitValidatorsExitRequestHashes` (SDVT) EVM script factory to Easy Track 69. Add `SubmitValidatorsExitRequestHashes` (Curated Module) EVM script factory to Easy Track - -Vote passed & executed on Jul-23-2025 12:54:36 PM UTC, block 862608 """ import time from typing import TYPE_CHECKING, Any, Dict from typing import Tuple, Optional, Sequence -from brownie import interface, web3, convert, ZERO_ADDRESS # type: ignore +from brownie import interface, web3, convert, ZERO_ADDRESS +from brownie.convert.main import to_uint # type: ignore from utils.agent import agent_forward from utils.config import ( CSM_COMMITTEE_MS, @@ -389,7 +388,7 @@ def start_vote(tx_params: Dict[str, str], silent: bool) -> Tuple[int, Optional[A encode_oz_grant_role( contract=contracts.staking_router, role_name="REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE", - grant_to=interface.TriggerableWithdrawalsGateway(TRIGGERABLE_WITHDRAWALS_GATEWAY), + grant_to=interface.TriggerableWithdrawalsGateway(TRIGGERABLE_WITHDRAWALS_GATEWAY), # FIXME: simply use the address ) ]) ), @@ -402,7 +401,7 @@ def start_vote(tx_params: Dict[str, str], silent: bool) -> Tuple[int, Optional[A contracts.acl.grantPermission.encode_input( AGENT, ARAGON_KERNEL, - convert.to_uint(web3.keccak(text="APP_MANAGER_ROLE")) + convert.to_uint(web3.keccak(text="APP_MANAGER_ROLE")) # FIXME: no need for to_uint I guess ) ) ]) @@ -463,7 +462,7 @@ def start_vote(tx_params: Dict[str, str], silent: bool) -> Tuple[int, Optional[A contracts.acl.revokePermission.encode_input( AGENT, ARAGON_KERNEL, - convert.to_uint(web3.keccak(text="APP_MANAGER_ROLE")) + convert.to_uint(web3.keccak(text="APP_MANAGER_ROLE")) # FIXME: remove to_uint ) ) ]) @@ -475,7 +474,7 @@ def start_vote(tx_params: Dict[str, str], silent: bool) -> Tuple[int, Optional[A encode_oz_grant_role( contract=contracts.oracle_daemon_config, role_name="CONFIG_MANAGER_ROLE", - grant_to=contracts.agent, + grant_to=contracts.agent, # FIXME: misleading usage of contract ) ]) ), @@ -521,7 +520,7 @@ def start_vote(tx_params: Dict[str, str], silent: bool) -> Tuple[int, Optional[A encode_oz_revoke_role( contract=contracts.oracle_daemon_config, role_name="CONFIG_MANAGER_ROLE", - revoke_from=contracts.agent, + revoke_from=contracts.agent, # FIXME: typing says its str ) ]) ), @@ -890,7 +889,7 @@ def prepare_proposal( ) def main(): - tx_params = {"from": get_deployer_account()} + tx_params: dict = {"from": get_deployer_account()} if get_is_live(): tx_params["priority_fee"] = get_priority_fee() diff --git a/tests/test_vote_tw_csm2_mainnet.py b/tests/test_vote_tw_csm2_mainnet.py index 0be8f7241..b5c97071a 100644 --- a/tests/test_vote_tw_csm2_mainnet.py +++ b/tests/test_vote_tw_csm2_mainnet.py @@ -1,4 +1,6 @@ from typing import Optional + +from brownie.exceptions import VirtualMachineError from scripts.vote_tw_csm2_mainnet import start_vote from brownie import interface, reverts, chain, convert, web3, ZERO_ADDRESS # type: ignore from brownie.network.event import EventDict @@ -89,6 +91,7 @@ def validate_bond_curve_added_event(event: EventDict, curve_id: int, emitted_by: assert "BondCurveAdded" in event, "No BondCurveAdded event found" assert event["BondCurveAdded"][0]["curveId"] == curve_id, "Wrong curve ID" + # FIXME: Where is the intervals check? if emitted_by is not None: assert convert.to_address(event["BondCurveAdded"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" @@ -145,6 +148,7 @@ def get_wv_contract_proxy_impl(proxy_address): return proxy.implementation() +# FIXME: no method for WV? def check_proxy_implementation(proxy_address, expected_impl): """Check that proxy has expected implementation""" actual_impl = get_ossifiable_proxy_impl(proxy_address) @@ -244,14 +248,15 @@ def test_tw_vote(helpers, accounts, vote_ids_from_env, stranger): assert vebo_impl_before != VALIDATORS_EXIT_BUS_ORACLE_IMPL, "VEBO implementation should be different before upgrade" # Step 3: Check VEBO finalizeUpgrade_v2 state - try: - assert contracts.validators_exit_bus_oracle.getMaxValidatorsPerReport() != 600, "VEBO max validators per report should not be 600 before upgrade" + try: # FIXME: with reverts + assert contracts.validators_exit_bus_oracle.getMaxValidatorsPerReport() != 600, "VEBO max validators per report should not be 600 before upgrade" # FIXME: magic number except Exception: pass # Function might not exist yet # Steps 4-6: Check VEBO consensus version management initial_vebo_consensus_version = contracts.validators_exit_bus_oracle.getConsensusVersion() assert initial_vebo_consensus_version < VEBO_CONSENSUS_VERSION, f"VEBO consensus version should be less than {VEBO_CONSENSUS_VERSION}" + # FIXME: Why no check for the role SUBMIT_REPORT_HASH_ROLE? # Step 7: Check TWG role for CS Ejector initial state add_full_withdrawal_request_role = triggerable_withdrawals_gateway.ADD_FULL_WITHDRAWAL_REQUEST_ROLE() @@ -443,6 +448,7 @@ def test_tw_vote(helpers, accounts, vote_ids_from_env, stranger): assert contracts.validators_exit_bus_oracle.getMaxValidatorsPerReport() == 600, "VEBO max validators per report should be set to 600" # Validate exit request limit parameters from finalizeUpgrade_v2 call + # FIXME: Magic numbers. exit_request_limits = contracts.validators_exit_bus_oracle.getExitRequestLimitFullInfo() assert exit_request_limits[0] == 11200, "maxExitRequestsLimit should be 11200" assert exit_request_limits[1] == 1, "exitsPerFrame should be 1" @@ -452,23 +458,23 @@ def test_tw_vote(helpers, accounts, vote_ids_from_env, stranger): assert not contracts.validators_exit_bus_oracle.hasRole(contracts.validators_exit_bus_oracle.MANAGE_CONSENSUS_VERSION_ROLE(), contracts.agent), "Agent should not have MANAGE_CONSENSUS_VERSION_ROLE on VEBO" assert contracts.validators_exit_bus_oracle.getConsensusVersion() == VEBO_CONSENSUS_VERSION, f"VEBO consensus version should be set to {VEBO_CONSENSUS_VERSION}" - # Steps 7-8: Validate TWG roles + # Step 7: Validate EasyTrack VEB SUBMIT_REPORT_HASH_ROLE + assert contracts.validators_exit_bus_oracle.hasRole(submit_report_hash_role, EASYTRACK_EVMSCRIPT_EXECUTOR), "EasyTrack executor should have SUBMIT_REPORT_HASH_ROLE on VEBO" + + # Steps 8-9: Validate TWG roles assert triggerable_withdrawals_gateway.hasRole(add_full_withdrawal_request_role, cs_ejector), "CS Ejector should have ADD_FULL_WITHDRAWAL_REQUEST_ROLE on TWG" assert triggerable_withdrawals_gateway.hasRole(add_full_withdrawal_request_role, contracts.validators_exit_bus_oracle), "VEBO should have ADD_FULL_WITHDRAWAL_REQUEST_ROLE on TWG" - # Step 9: Validate EasyTrack VEB SUBMIT_REPORT_HASH_ROLE - assert contracts.validators_exit_bus_oracle.hasRole(submit_report_hash_role, EASYTRACK_EVMSCRIPT_EXECUTOR), "EasyTrack executor should have SUBMIT_REPORT_HASH_ROLE on VEBO" - # Step 10: Validate DualGovernance tiebreaker connection final_tiebreaker_details = contracts.dual_governance.getTiebreakerDetails() final_tiebreakers = final_tiebreaker_details[3] # sealableWithdrawalBlockers assert TRIGGERABLE_WITHDRAWALS_GATEWAY in final_tiebreakers, "TWG should be in tiebreaker list after upgrade" - # Steps 9-10: Validate Withdrawal Vault upgrade + # Steps 11-12: Validate Withdrawal Vault upgrade assert get_wv_contract_proxy_impl(contracts.withdrawal_vault) == WITHDRAWAL_VAULT_IMPL, "Withdrawal Vault implementation should be updated" assert contracts.withdrawal_vault.getContractVersion() == 2, "Withdrawal Vault version should be 2 after finalizeUpgrade_v2" - # Steps 11-14: Validate Accounting Oracle upgrade + # Steps 13-16: Validate Accounting Oracle upgrade assert get_ossifiable_proxy_impl(contracts.accounting_oracle) == ACCOUNTING_ORACLE_IMPL, "Accounting Oracle implementation should be updated" assert not contracts.accounting_oracle.hasRole(contracts.accounting_oracle.MANAGE_CONSENSUS_VERSION_ROLE(), contracts.agent), "Agent should not have MANAGE_CONSENSUS_VERSION_ROLE on AO" assert contracts.accounting_oracle.getConsensusVersion() == AO_CONSENSUS_VERSION, f"AO consensus version should be set to {AO_CONSENSUS_VERSION}" @@ -476,98 +482,103 @@ def test_tw_vote(helpers, accounts, vote_ids_from_env, stranger): # Step 17: Validate AO finalizeUpgrade_v3 assert contracts.accounting_oracle.getContractVersion() == 3, "AO contract version should be 3 after finalizeUpgrade_v3" - # Steps 15-17: Validate Staking Router upgrade + # Steps 18-21: Validate Staking Router upgrade assert get_ossifiable_proxy_impl(contracts.staking_router) == STAKING_ROUTER_IMPL, "Staking Router implementation should be updated" + assert contracts.staking_router.getContractVersion() == 3, "Staking Router version should be 3 after finalizeUpgrade_v3" assert contracts.staking_router.hasRole(contracts.staking_router.REPORT_VALIDATOR_EXITING_STATUS_ROLE(), VALIDATOR_EXIT_VERIFIER), "ValidatorExitVerifier should have REPORT_VALIDATOR_EXITING_STATUS_ROLE on SR" assert contracts.staking_router.hasRole(contracts.staking_router.REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE(), triggerable_withdrawals_gateway), "TWG should have REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE on SR" - # Steps 18-23: Validate NOR and sDVT updates + # Steps 22-27: Validate NOR and sDVT updates assert not contracts.acl.hasPermission(contracts.agent, contracts.kernel, app_manager_role), "Agent should not have APP_MANAGER_ROLE after vote" assert contracts.node_operators_registry.getContractVersion() == 4, "Node Operators Registry version should be updated to 4" assert contracts.simple_dvt.getContractVersion() == 4, "Simple DVT version should be updated to 4" - assert contracts.node_operators_registry.exitDeadlineThreshold(0) == NOR_EXIT_DEADLINE_IN_SEC, "NOR exit deadline threshold should be set correctly" - assert contracts.simple_dvt.exitDeadlineThreshold(0) == NOR_EXIT_DEADLINE_IN_SEC, "sDVT exit deadline threshold should be set correctly" + assert contracts.node_operators_registry.exitDeadlineThreshold(0) == NOR_EXIT_DEADLINE_IN_SEC, "NOR exit deadline threshold should be set correctly after finalizeUpgrade_v4" + assert contracts.simple_dvt.exitDeadlineThreshold(0) == NOR_EXIT_DEADLINE_IN_SEC, "sDVT exit deadline threshold should be set correctly after finalizeUpgrade_v4" - # Steps 24-28: Validate Oracle Daemon Config changes + # Steps 28-33: Validate Oracle Daemon Config changes assert not contracts.oracle_daemon_config.hasRole(config_manager_role, contracts.agent), "Agent should not have CONFIG_MANAGER_ROLE on Oracle Daemon Config" for var_name in ['NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP', 'VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS', 'VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS']: try: contracts.oracle_daemon_config.get(var_name) - assert False, f"Variable {var_name} should have been removed" - except Exception: + except VirtualMachineError: pass # Expected to fail - variable should be removed + else: + raise AssertionError(f"Variable {var_name} should have been removed") assert convert.to_uint(contracts.oracle_daemon_config.get('EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS')) == EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS, f"EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS should be set to {EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS}" - # Step 29: Validate CSM implementation upgrade + # Step 34: Validate CSM implementation upgrade check_proxy_implementation(contracts.csm.address, CSM_IMPL_V2_ADDRESS) - # Step 30: Validate CSM finalizeUpgradeV2 was called + # Step 35: Validate CSM finalizeUpgradeV2 was called assert contracts.csm.getInitializedVersion() == CSM_V2_VERSION, f"CSM version should be {CSM_V2_VERSION} after vote" - # Step 31: Validate CSAccounting implementation upgrade + # Step 36: Validate CSAccounting implementation upgrade check_proxy_implementation(contracts.cs_accounting.address, CS_ACCOUNTING_IMPL_V2_ADDRESS) - # Step 32: Validate CSAccounting finalizeUpgradeV2 was called with bond curves + # Step 37: Validate CSAccounting finalizeUpgradeV2 was called with bond curves assert contracts.cs_accounting.getInitializedVersion() == CS_ACCOUNTING_V2_VERSION, f"CSAccounting version should be {CS_ACCOUNTING_V2_VERSION} after vote" + # FIXME: check bond curves - # Step 33: Validate CSFeeOracle implementation upgrade + # Step 38: Validate CSFeeOracle implementation upgrade check_proxy_implementation(contracts.cs_fee_oracle.address, CS_FEE_ORACLE_IMPL_V2_ADDRESS) - # Step 34: Validate CSFeeOracle finalizeUpgradeV2 was called with consensus version 3 + # Step 39: Validate CSFeeOracle finalizeUpgradeV2 was called with consensus version 3 assert contracts.cs_fee_oracle.getContractVersion() == CS_FEE_ORACLE_V2_VERSION, f"CSFeeOracle version should be {CS_FEE_ORACLE_V2_VERSION} after vote" assert contracts.cs_fee_oracle.getConsensusVersion() == CSM_CONSENSUS_VERSION, "CSFeeOracle consensus version should be 3 after vote" - # Step 35: Validate CSFeeDistributor implementation upgrade + # Step 40: Validate CSFeeDistributor implementation upgrade check_proxy_implementation(contracts.cs_fee_distributor.address, CS_FEE_DISTRIBUTOR_IMPL_V2_ADDRESS) - # Step 36: Validate CSFeeDistributor finalizeUpgradeV2 was called + # Step 41: Validate CSFeeDistributor finalizeUpgradeV2 was called assert contracts.cs_fee_distributor.getInitializedVersion() == CS_FEE_DISTRIBUTOR_V2_VERSION, f"CSFeeDistributor version should be {CS_FEE_DISTRIBUTOR_V2_VERSION} after vote" + assert contracts.cs_fee_distributor.rebateRecipient() == contracts.agent.address, "Rebate recipient should be the agent after vote" - # Step 37: Validate SET_BOND_CURVE_ROLE was revoked from CSM on CSAccounting + # Step 42: Validate SET_BOND_CURVE_ROLE was revoked from CSM on CSAccounting assert not contracts.cs_accounting.hasRole(contracts.cs_accounting.SET_BOND_CURVE_ROLE(), contracts.csm.address), "CSM should not have SET_BOND_CURVE_ROLE on CSAccounting after vote" - # Step 38: Validate RESET_BOND_CURVE_ROLE was revoked from CSM on CSAccounting + # Step 43: Validate RESET_BOND_CURVE_ROLE was revoked from CSM on CSAccounting assert not contracts.cs_accounting.hasRole(web3.keccak(text="RESET_BOND_CURVE_ROLE"), contracts.csm.address), "CSM should not have RESET_BOND_CURVE_ROLE on CSAccounting after vote" - # Step 39: Validate RESET_BOND_CURVE_ROLE was revoked from CSM committee on CSAccounting + # Step 44: Validate RESET_BOND_CURVE_ROLE was revoked from CSM committee on CSAccounting assert not contracts.cs_accounting.hasRole(web3.keccak(text="RESET_BOND_CURVE_ROLE"), CSM_COMMITTEE_MS), "CSM committee should not have RESET_BOND_CURVE_ROLE on CSAccounting after vote" - # Step 40: Validate CREATE_NODE_OPERATOR_ROLE was granted to permissionless gate on CSM + # Step 45: Validate CREATE_NODE_OPERATOR_ROLE was granted to permissionless gate on CSM assert contracts.csm.hasRole(contracts.csm.CREATE_NODE_OPERATOR_ROLE(), cs_permissionless_gate.address), "Permissionless gate should have CREATE_NODE_OPERATOR_ROLE on CSM after vote" - # Step 41: Validate CREATE_NODE_OPERATOR_ROLE was granted to vetted gate on CSM + # Step 46: Validate CREATE_NODE_OPERATOR_ROLE was granted to vetted gate on CSM assert contracts.csm.hasRole(contracts.csm.CREATE_NODE_OPERATOR_ROLE(), cs_vetted_gate.address), "Vetted gate should have CREATE_NODE_OPERATOR_ROLE on CSM after vote" - # Step 42: Validate SET_BOND_CURVE_ROLE was granted to vetted gate on CSAccounting + # Step 47: Validate SET_BOND_CURVE_ROLE was granted to vetted gate on CSAccounting assert contracts.cs_accounting.hasRole(contracts.cs_accounting.SET_BOND_CURVE_ROLE(), cs_vetted_gate.address), "Vetted gate should have SET_BOND_CURVE_ROLE on CSAccounting after vote" - # Step 43: Validate VERIFIER_ROLE was revoked from old verifier on CSM + # Step 48: Validate VERIFIER_ROLE was revoked from old verifier on CSM assert not contracts.csm.hasRole(contracts.csm.VERIFIER_ROLE(), contracts.cs_verifier.address), "Old verifier should not have VERIFIER_ROLE on CSM after vote" - # Step 44: Validate VERIFIER_ROLE was granted to new verifier on CSM + # Step 49: Validate VERIFIER_ROLE was granted to new verifier on CSM assert contracts.csm.hasRole(contracts.csm.VERIFIER_ROLE(), cs_verifier_v2.address), "New verifier should have VERIFIER_ROLE on CSM after vote" - # Step 45: Validate PAUSE_ROLE was revoked from old GateSeal on CSM + # Step 50: Validate PAUSE_ROLE was revoked from old GateSeal on CSM assert not contracts.csm.hasRole(contracts.csm.PAUSE_ROLE(), CS_GATE_SEAL_ADDRESS), "Old GateSeal should not have PAUSE_ROLE on CSM after vote" - # Step 46: Validate PAUSE_ROLE was revoked from old GateSeal on CSAccounting + # Step 51: Validate PAUSE_ROLE was revoked from old GateSeal on CSAccounting assert not contracts.cs_accounting.hasRole(contracts.cs_accounting.PAUSE_ROLE(), CS_GATE_SEAL_ADDRESS), "Old GateSeal should not have PAUSE_ROLE on CSAccounting after vote" - # Step 47: Validate PAUSE_ROLE was revoked from old GateSeal on CSFeeOracle + # Step 52: Validate PAUSE_ROLE was revoked from old GateSeal on CSFeeOracle assert not contracts.cs_fee_oracle.hasRole(contracts.cs_fee_oracle.PAUSE_ROLE(), CS_GATE_SEAL_ADDRESS), "Old GateSeal should not have PAUSE_ROLE on CSFeeOracle after vote" - # Step 48: Validate PAUSE_ROLE was granted to new GateSeal on CSM + # Step 53: Validate PAUSE_ROLE was granted to new GateSeal on CSM assert contracts.csm.hasRole(contracts.csm.PAUSE_ROLE(), CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should have PAUSE_ROLE on CSM after vote" - # Step 49: Validate PAUSE_ROLE was granted to new GateSeal on CSAccounting + # Step 54: Validate PAUSE_ROLE was granted to new GateSeal on CSAccounting assert contracts.cs_accounting.hasRole(contracts.cs_accounting.PAUSE_ROLE(), CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should have PAUSE_ROLE on CSAccounting after vote" - # Step 50: Validate PAUSE_ROLE was granted to new GateSeal on CSFeeOracle + # Step 55: Validate PAUSE_ROLE was granted to new GateSeal on CSFeeOracle assert contracts.cs_fee_oracle.hasRole(contracts.cs_fee_oracle.PAUSE_ROLE(), CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should have PAUSE_ROLE on CSFeeOracle after vote" # Step 50-52: Check add ICS Bond Curve to CSAccounting assert not contracts.cs_accounting.hasRole(contracts.cs_accounting.MANAGE_BOND_CURVES_ROLE(), contracts.agent), "Agent should not have MANAGE_BOND_CURVES_ROLE on CSAccounting after vote" assert contracts.cs_accounting.getCurvesCount() == len(CS_CURVES) + 1, "CSAccounting should have legacy bond curves and ICS Bond Curve after vote" + # FIXME: Check curves? # Step 53: Increase CSM share in Staking Router csm_module_after = contracts.staking_router.getStakingModule(CS_MODULE_ID) From 5d8b7065d923d5b1eabadacbf0dcc68debd4788c Mon Sep 17 00:00:00 2001 From: hweawer Date: Mon, 11 Aug 2025 16:19:44 +0200 Subject: [PATCH 11/28] Vote for exit hashes (#464) * Vote for exit hashes * Update test_permissions.py * Update test_permissions.py * Changes * Update * Revert * Update * Update * Format * Comment with CID * Update descriptions * Update date * Move to archieve --------- Co-authored-by: Nikita P --- archive/scripts/vote_hoodi_exit_hashes.py | 136 ++++++++++++++ archive/tests/test_vote_hoodi_exit_hashes.py | 188 +++++++++++++++++++ configs/config_hoodi.py | 2 +- 3 files changed, 325 insertions(+), 1 deletion(-) create mode 100644 archive/scripts/vote_hoodi_exit_hashes.py create mode 100644 archive/tests/test_vote_hoodi_exit_hashes.py diff --git a/archive/scripts/vote_hoodi_exit_hashes.py b/archive/scripts/vote_hoodi_exit_hashes.py new file mode 100644 index 000000000..7eba452b2 --- /dev/null +++ b/archive/scripts/vote_hoodi_exit_hashes.py @@ -0,0 +1,136 @@ +""" +Vote 2025-08-11 - Submit Exit Requests Hash to ValidatorsExitBus Oracle + +1. Upgrade Lido Locator implementation +2. Grant REPORT_VALIDATOR_EXITING_STATUS_ROLE to new validator exit verifier +3. Revoke REPORT_VALIDATOR_EXITING_STATUS_ROLE from old validator exit verifier +4. Grant SUBMIT_REPORT_HASH_ROLE to the agent +5. Submit exit requests hash to ValidatorsExitBus Oracle +6. Revoke SUBMIT_REPORT_HASH_ROLE from the agent + +Vote passed & executed on 2025-08-11 04:09 PM GMT+2, block 985695 +""" + +import time +from typing import Any, Dict, Tuple, Optional +from brownie import interface +from brownie.network.transaction import TransactionReceipt + +from utils.config import contracts +from utils.voting import confirm_vote_script, create_vote +from archive.scripts.vote_tw_csm2_hoodi import prepare_proposal +from utils.config import get_deployer_account, get_is_live, get_priority_fee +from utils.agent import agent_forward +from utils.ipfs import upload_vote_ipfs_description, calculate_vote_ipfs_description +from utils.permissions import encode_oz_grant_role, encode_oz_revoke_role + +OLD_VALIDATOR_EXIT_VERIFIER = "0xFd4386A8795956f4B6D01cbb6dB116749731D7bD" +# CID: bafkreidetdrrl3zjxer6tv6qqnsxdqrldntydluorllmetpsozl4yr7pva - validators data +EXIT_HASH_TO_SUBMIT = "0x4e72449ac50f5fa83bc2d642f2c95a63f72f1b87ad292f52c0fe5c28f3cf6e47" +LIDO_LOCATOR_IMPL = "0xA656983a6686615850BE018b7d42a7C3E46DcD71" + +DESCRIPTION = "TW Upgrade & Test for Validators Exiting via Voting (HOODI)" + + +def encode_proxy_upgrade_to(proxy: Any, implementation: str) -> Tuple[str, str]: + proxy = interface.OssifiableProxy(proxy) + return proxy.address, proxy.proxy__upgradeTo.encode_input(implementation) + + +def start_vote(tx_params: Dict[str, str], silent: bool = False) -> Tuple[int, Optional[TransactionReceipt]]: + """Prepare and run voting.""" + + validators_exit_bus = interface.ValidatorsExitBusOracle(contracts.validators_exit_bus_oracle) + + vote_desc_items, call_script_items = zip( + ( + "1. Upgrade Lido Locator implementation", + agent_forward([encode_proxy_upgrade_to(contracts.lido_locator, LIDO_LOCATOR_IMPL)]), + ), + ( + "2. Grant REPORT_VALIDATOR_EXITING_STATUS_ROLE to new validator exit verifier", + agent_forward( + [ + encode_oz_grant_role( + contract=contracts.staking_router, + role_name="REPORT_VALIDATOR_EXITING_STATUS_ROLE", + grant_to=contracts.validator_exit_verifier, + ) + ] + ), + ), + ( + "3. Revoke REPORT_VALIDATOR_EXITING_STATUS_ROLE from old validator exit verifier", + agent_forward( + [ + encode_oz_revoke_role( + contract=contracts.staking_router, + role_name="REPORT_VALIDATOR_EXITING_STATUS_ROLE", + revoke_from=OLD_VALIDATOR_EXIT_VERIFIER, + ) + ] + ), + ), + ( + "4. Grant SUBMIT_REPORT_HASH_ROLE to the agent", + agent_forward( + [ + encode_oz_grant_role( + contract=validators_exit_bus, + role_name="SUBMIT_REPORT_HASH_ROLE", + grant_to=contracts.agent, + ) + ] + ), + ), + ( + "5. Submit exit requests hash to ValidatorsExitBus Oracle", + agent_forward( + [ + ( + contracts.validators_exit_bus_oracle.address, + validators_exit_bus.submitExitRequestsHash.encode_input(EXIT_HASH_TO_SUBMIT), + ) + ] + ), + ), + ( + "6. Revoke SUBMIT_REPORT_HASH_ROLE from the agent", + agent_forward( + [ + encode_oz_revoke_role( + contract=validators_exit_bus, + role_name="SUBMIT_REPORT_HASH_ROLE", + revoke_from=contracts.agent, + ) + ] + ), + ), + ) + + if silent: + desc_ipfs = calculate_vote_ipfs_description(DESCRIPTION) + else: + desc_ipfs = upload_vote_ipfs_description(DESCRIPTION) + + dg_vote = prepare_proposal(call_script_items, DESCRIPTION) + vote_items = {DESCRIPTION: dg_vote} + + assert confirm_vote_script(vote_items, silent, desc_ipfs) + return create_vote(vote_items, tx_params, desc_ipfs=desc_ipfs) + + +def main(): + tx_params = {"from": get_deployer_account()} + if get_is_live(): + tx_params["priority_fee"] = get_priority_fee() + + vote_id, _ = start_vote(tx_params=tx_params, silent=False) + + vote_id >= 0 and print(f"Vote created: {vote_id}.") + + time.sleep(5) # hack for waiting thread #2. + + +if __name__ == "__main__": + main() diff --git a/archive/tests/test_vote_hoodi_exit_hashes.py b/archive/tests/test_vote_hoodi_exit_hashes.py new file mode 100644 index 000000000..3b97e40be --- /dev/null +++ b/archive/tests/test_vote_hoodi_exit_hashes.py @@ -0,0 +1,188 @@ +from typing import Optional +from archive.scripts.vote_hoodi_exit_hashes import start_vote, EXIT_HASH_TO_SUBMIT, OLD_VALIDATOR_EXIT_VERIFIER, LIDO_LOCATOR_IMPL +from brownie import interface, chain, convert, web3 # type: ignore +from brownie.network.event import EventDict +from utils.test.tx_tracing_helpers import group_voting_events_from_receipt, group_dg_events_from_receipt +from utils.test.event_validators.dual_governance import validate_dual_governance_submit_event +from utils.dual_governance import wait_for_noon_utc_to_satisfy_time_constrains +from utils.config import ( + DUAL_GOVERNANCE, + TIMELOCK, + DUAL_GOVERNANCE_EXECUTORS, + LDO_HOLDER_ADDRESS_FOR_TESTS, + AGENT, + VOTING, + contracts, +) + + +def validate_role_grant_event(event: EventDict, role_hash: str, account: str, emitted_by: Optional[str] = None): + """Validates an OpenZeppelin AccessControl role grant event""" + assert "RoleGranted" in event, "No RoleGranted event found" + assert event["RoleGranted"][0]["role"] == role_hash, f"Wrong role hash. Expected: {role_hash}, Got: {event['RoleGranted'][0]['role']}" + assert event["RoleGranted"][0]["account"] == convert.to_address(account), f"Wrong account. Expected: {account}, Got: {event['RoleGranted'][0]['account']}" + + if emitted_by is not None: + assert convert.to_address(event["RoleGranted"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + + +def validate_role_revoke_event(event: EventDict, role_hash: str, account: str, emitted_by: Optional[str] = None): + """Validates an OpenZeppelin AccessControl role revoke event""" + assert "RoleRevoked" in event, "No RoleRevoked event found" + assert event["RoleRevoked"][0]["role"] == role_hash, f"Wrong role hash. Expected: {role_hash}, Got: {event['RoleRevoked'][0]['role']}" + assert event["RoleRevoked"][0]["account"] == convert.to_address(account), f"Wrong account. Expected: {account}, Got: {event['RoleRevoked'][0]['account']}" + + if emitted_by is not None: + assert convert.to_address(event["RoleRevoked"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + + +def validate_submit_exit_requests_hash_event(event: EventDict, expected_hash: str, emitted_by: Optional[str] = None): + """Validates RequestsHashSubmitted event from ValidatorsExitBus""" + assert "RequestsHashSubmitted" in event, "No RequestsHashSubmitted event found" + assert event["RequestsHashSubmitted"][0]["exitRequestsHash"] == expected_hash, f"Wrong hash. Expected: {expected_hash}, Got: {event['RequestsHashSubmitted'][0]['exitRequestsHash']}" + + if emitted_by is not None: + assert convert.to_address(event["RequestsHashSubmitted"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + + +def validate_proxy_upgrade_event(event: EventDict, expected_implementation: str, emitted_by: Optional[str] = None): + """Validates Upgraded event from OssifiableProxy""" + assert "Upgraded" in event, "No Upgraded event found" + assert event["Upgraded"][0]["implementation"] == convert.to_address(expected_implementation), f"Wrong implementation. Expected: {expected_implementation}, Got: {event['Upgraded'][0]['implementation']}" + + if emitted_by is not None: + assert convert.to_address(event["Upgraded"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + + +def test_vote_hoodi_exit_hashes(helpers, accounts, vote_ids_from_env, stranger): + """Test the comprehensive vote that grants validator roles, submits exit hash, and manages permissions""" + + # Calculate role hashes + SUBMIT_REPORT_HASH_ROLE = web3.keccak(text="SUBMIT_REPORT_HASH_ROLE") + REPORT_VALIDATOR_EXITING_STATUS_ROLE = web3.keccak(text="REPORT_VALIDATOR_EXITING_STATUS_ROLE") + + # Get contracts + validators_exit_bus = interface.ValidatorsExitBusOracle(contracts.validators_exit_bus_oracle) + staking_router = interface.StakingRouter(contracts.staking_router) + lido_locator_proxy = interface.OssifiableProxy(contracts.lido_locator) + timelock = interface.EmergencyProtectedTimelock(TIMELOCK) + dual_governance = interface.DualGovernance(DUAL_GOVERNANCE) + + # Check initial state + initial_implementation = lido_locator_proxy.proxy__getImplementation() + assert not validators_exit_bus.hasRole(SUBMIT_REPORT_HASH_ROLE, AGENT), "Agent should not have SUBMIT_REPORT_HASH_ROLE before vote" + + # Check if old verifier currently has the role (to be revoked) + old_verifier_has_role_before = staking_router.hasRole(REPORT_VALIDATOR_EXITING_STATUS_ROLE, OLD_VALIDATOR_EXIT_VERIFIER) + new_verifier_has_role_before = staking_router.hasRole(REPORT_VALIDATOR_EXITING_STATUS_ROLE, contracts.validator_exit_verifier) + + # START VOTE + if len(vote_ids_from_env) > 0: + (vote_id,) = vote_ids_from_env + else: + tx_params = {"from": LDO_HOLDER_ADDRESS_FOR_TESTS} + vote_id, _ = start_vote(tx_params, silent=True) + + vote_tx = helpers.execute_vote(accounts, vote_id, contracts.voting) + print(f"voteId = {vote_id}") + + proposal_id = vote_tx.events["ProposalSubmitted"][1]["proposalId"] + print(f"proposalId = {proposal_id}") + + chain.sleep(timelock.getAfterSubmitDelay() + 1) + dual_governance.scheduleProposal(proposal_id, {"from": stranger}) + + chain.sleep(timelock.getAfterScheduleDelay() + 1) + wait_for_noon_utc_to_satisfy_time_constrains() + + dg_tx = timelock.execute(proposal_id, {"from": stranger}) + + # --- VALIDATE EXECUTION RESULTS --- + + # 1. Verify Lido Locator was upgraded + final_implementation = lido_locator_proxy.proxy__getImplementation() + assert final_implementation == LIDO_LOCATOR_IMPL, f"Locator implementation not upgraded. Expected: {LIDO_LOCATOR_IMPL}, Got: {final_implementation}" + assert final_implementation != initial_implementation, "Implementation should have changed" + + # 2. Verify validator roles were updated + assert staking_router.hasRole(REPORT_VALIDATOR_EXITING_STATUS_ROLE, contracts.validator_exit_verifier), "New verifier should have role after vote" + assert not staking_router.hasRole(REPORT_VALIDATOR_EXITING_STATUS_ROLE, OLD_VALIDATOR_EXIT_VERIFIER), "Old verifier should not have role after vote" + + # 3. Verify SUBMIT_REPORT_HASH_ROLE was granted and then revoked (final state is revoked) + assert not validators_exit_bus.hasRole(SUBMIT_REPORT_HASH_ROLE, AGENT), "Agent should not have SUBMIT_REPORT_HASH_ROLE after vote" + + # --- VALIDATE EVENTS --- + voting_events = group_voting_events_from_receipt(vote_tx) + assert len(voting_events) >= 1, "No voting events found" + + validate_dual_governance_submit_event( + voting_events[0], + proposal_id, + proposer=VOTING, + executor=DUAL_GOVERNANCE_EXECUTORS[0], + ) + + dg_execution_events = group_dg_events_from_receipt(dg_tx, timelock=TIMELOCK, admin_executor=DUAL_GOVERNANCE_EXECUTORS[0]) + expected_events = 6 # 1 proxy upgrade + 2 role grants + 1 role grant for agent + 1 hash submission + 1 role revoke + assert len(dg_execution_events) == expected_events, f"Expected {expected_events} dual governance events, got {len(dg_execution_events)}" + + event_idx = 0 + + # Step 1: Upgrade Lido Locator implementation + validate_proxy_upgrade_event( + dg_execution_events[event_idx], + expected_implementation=LIDO_LOCATOR_IMPL, + emitted_by=contracts.lido_locator + ) + event_idx += 1 + + # Step 2: Grant REPORT_VALIDATOR_EXITING_STATUS_ROLE to new validator exit verifier + validate_role_grant_event( + dg_execution_events[event_idx], + role_hash=REPORT_VALIDATOR_EXITING_STATUS_ROLE.hex(), + account=contracts.validator_exit_verifier, + emitted_by=contracts.staking_router + ) + event_idx += 1 + + # Step 3: Revoke REPORT_VALIDATOR_EXITING_STATUS_ROLE from old validator exit verifier + validate_role_revoke_event( + dg_execution_events[event_idx], + role_hash=REPORT_VALIDATOR_EXITING_STATUS_ROLE.hex(), + account=OLD_VALIDATOR_EXIT_VERIFIER, + emitted_by=contracts.staking_router + ) + event_idx += 1 + + # Step 4: Grant SUBMIT_REPORT_HASH_ROLE to agent + validate_role_grant_event( + dg_execution_events[event_idx], + role_hash=SUBMIT_REPORT_HASH_ROLE.hex(), + account=AGENT, + emitted_by=contracts.validators_exit_bus_oracle + ) + event_idx += 1 + + # Step 5: Submit exit requests hash + validate_submit_exit_requests_hash_event( + dg_execution_events[event_idx], + expected_hash=EXIT_HASH_TO_SUBMIT, + emitted_by=contracts.validators_exit_bus_oracle + ) + event_idx += 1 + + # Step 6: Revoke SUBMIT_REPORT_HASH_ROLE from agent + validate_role_revoke_event( + dg_execution_events[event_idx], + role_hash=SUBMIT_REPORT_HASH_ROLE.hex(), + account=AGENT, + emitted_by=contracts.validators_exit_bus_oracle + ) + + print("✅ Vote executed successfully:") + print(f" - Lido Locator upgraded to implementation: {LIDO_LOCATOR_IMPL}") + print(f" - REPORT_VALIDATOR_EXITING_STATUS_ROLE granted to new verifier: {contracts.validator_exit_verifier}") + print(f" - REPORT_VALIDATOR_EXITING_STATUS_ROLE revoked from old verifier: {OLD_VALIDATOR_EXIT_VERIFIER}") + print(f" - SUBMIT_REPORT_HASH_ROLE granted and revoked to/from agent") + print(f" - Exit hash {EXIT_HASH_TO_SUBMIT} submitted") + print(f" - All {expected_events} events validated correctly") diff --git a/configs/config_hoodi.py b/configs/config_hoodi.py index 24c84baaf..c4f83714c 100644 --- a/configs/config_hoodi.py +++ b/configs/config_hoodi.py @@ -101,7 +101,7 @@ # Triggerable Withdrawals Gateway TRIGGERABLE_WITHDRAWALS_GATEWAY = "0x6679090D92b08a2a686eF8614feECD8cDFE209db" -VALIDATOR_EXIT_VERIFIER = "0xFd4386A8795956f4B6D01cbb6dB116749731D7bD" +VALIDATOR_EXIT_VERIFIER = "0x7990A2F4E16E3c0D651306D26084718DB5aC9947" # CSM addresses CSM_COMMITTEE_MS = "0x4AF43Ee34a6fcD1fEcA1e1F832124C763561dA53" From 37e803c483b184789b212c29180eb73648076ea7 Mon Sep 17 00:00:00 2001 From: hweawer Date: Thu, 14 Aug 2025 11:33:43 +0200 Subject: [PATCH 12/28] Voting to exit validators on Hoodi in test NO (#467) * Voting to exit validators on Hoodi in test NO * Fix description * Fix hash * Update CID * Add verification for ExitDataProcessing * Remove debug lines * Update dates --- archive/scripts/vote_hoodi_exit_hashes_2.py | 98 +++++++++++ .../tests/test_vote_hoodi_exit_hashes_2.py | 156 ++++++++++++++++++ interfaces/ValidatorsExitBusOracle.json | 18 +- 3 files changed, 267 insertions(+), 5 deletions(-) create mode 100755 archive/scripts/vote_hoodi_exit_hashes_2.py create mode 100644 archive/tests/test_vote_hoodi_exit_hashes_2.py diff --git a/archive/scripts/vote_hoodi_exit_hashes_2.py b/archive/scripts/vote_hoodi_exit_hashes_2.py new file mode 100755 index 000000000..1c28a9aa7 --- /dev/null +++ b/archive/scripts/vote_hoodi_exit_hashes_2.py @@ -0,0 +1,98 @@ +""" +Vote August 14, 2025 at 11:09 GMT+2 - Submit Exit Requests Hash to ValidatorsExitBus Oracle + +1. Grant SUBMIT_REPORT_HASH_ROLE to the agent +2. Submit exit requests hash to ValidatorsExitBus Oracle +3. Revoke SUBMIT_REPORT_HASH_ROLE from the agent + +Vote passed & executed on August 14, 2025 at 11:09 GMT+2, block 1003997 +""" + +import time +from typing import Any, Dict, Tuple, Optional +from brownie import interface +from brownie.network.transaction import TransactionReceipt + +from utils.config import contracts +from utils.voting import confirm_vote_script, create_vote +from archive.scripts.vote_tw_csm2_hoodi import prepare_proposal +from utils.config import get_deployer_account, get_is_live, get_priority_fee +from utils.agent import agent_forward +from utils.ipfs import upload_vote_ipfs_description, calculate_vote_ipfs_description +from utils.permissions import encode_oz_grant_role, encode_oz_revoke_role + +# CID: bafkreihtr6nlijylmesqmsp3v2h7c3zbkx7bqwt5qu3jbahojnrt2qm2vy - validators data +EXIT_HASH_TO_SUBMIT = "0xd76d7dd9cb2f102583d2bafbd6deb12473838e444d0d7226773895333fe32beb" + +DESCRIPTION = "Test for Validators Exiting via Voting (HOODI)" + + +def start_vote(tx_params: Dict[str, str], silent: bool = False) -> Tuple[int, Optional[TransactionReceipt]]: + """Prepare and run voting.""" + + validators_exit_bus = interface.ValidatorsExitBusOracle(contracts.validators_exit_bus_oracle) + + vote_desc_items, call_script_items = zip( + ( + "1. Grant SUBMIT_REPORT_HASH_ROLE to the agent", + agent_forward( + [ + encode_oz_grant_role( + contract=validators_exit_bus, + role_name="SUBMIT_REPORT_HASH_ROLE", + grant_to=contracts.agent, + ) + ] + ), + ), + ( + "2. Submit exit requests hash to ValidatorsExitBus Oracle", + agent_forward( + [ + ( + contracts.validators_exit_bus_oracle.address, + validators_exit_bus.submitExitRequestsHash.encode_input(EXIT_HASH_TO_SUBMIT), + ) + ] + ), + ), + ( + "3. Revoke SUBMIT_REPORT_HASH_ROLE from the agent", + agent_forward( + [ + encode_oz_revoke_role( + contract=validators_exit_bus, + role_name="SUBMIT_REPORT_HASH_ROLE", + revoke_from=contracts.agent, + ) + ] + ), + ), + ) + + if silent: + desc_ipfs = calculate_vote_ipfs_description(DESCRIPTION) + else: + desc_ipfs = upload_vote_ipfs_description(DESCRIPTION) + + dg_vote = prepare_proposal(call_script_items, DESCRIPTION) + vote_items = {DESCRIPTION: dg_vote} + + assert confirm_vote_script(vote_items, silent, desc_ipfs) + return create_vote(vote_items, tx_params, desc_ipfs=desc_ipfs) + + +def main(): + tx_params = {"from": get_deployer_account()} + if get_is_live(): + tx_params["priority_fee"] = get_priority_fee() + + vote_id, _ = start_vote(tx_params=tx_params, silent=False) + + vote_id >= 0 and print(f"Vote created: {vote_id}.") + + time.sleep(5) # hack for waiting thread #2. + + +if __name__ == "__main__": + main() diff --git a/archive/tests/test_vote_hoodi_exit_hashes_2.py b/archive/tests/test_vote_hoodi_exit_hashes_2.py new file mode 100644 index 000000000..1eaac09a7 --- /dev/null +++ b/archive/tests/test_vote_hoodi_exit_hashes_2.py @@ -0,0 +1,156 @@ +from typing import Optional + +from eth_abi import encode + +from archive.scripts.vote_hoodi_exit_hashes_2 import start_vote, EXIT_HASH_TO_SUBMIT +from brownie import interface, chain, convert, web3 # type: ignore +from brownie.network.event import EventDict +from utils.test.tx_tracing_helpers import group_voting_events_from_receipt, group_dg_events_from_receipt +from utils.test.event_validators.dual_governance import validate_dual_governance_submit_event +from utils.dual_governance import wait_for_noon_utc_to_satisfy_time_constrains +from utils.config import ( + DUAL_GOVERNANCE, + TIMELOCK, + DUAL_GOVERNANCE_EXECUTORS, + LDO_HOLDER_ADDRESS_FOR_TESTS, + AGENT, + VOTING, + contracts, +) + + +def validate_role_grant_event(event: EventDict, role_hash: str, account: str, emitted_by: Optional[str] = None): + """Validates an OpenZeppelin AccessControl role grant event""" + assert "RoleGranted" in event, "No RoleGranted event found" + assert event["RoleGranted"][0]["role"] == role_hash, f"Wrong role hash. Expected: {role_hash}, Got: {event['RoleGranted'][0]['role']}" + assert event["RoleGranted"][0]["account"] == convert.to_address(account), f"Wrong account. Expected: {account}, Got: {event['RoleGranted'][0]['account']}" + + if emitted_by is not None: + assert convert.to_address(event["RoleGranted"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + + +def validate_role_revoke_event(event: EventDict, role_hash: str, account: str, emitted_by: Optional[str] = None): + """Validates an OpenZeppelin AccessControl role revoke event""" + assert "RoleRevoked" in event, "No RoleRevoked event found" + assert event["RoleRevoked"][0]["role"] == role_hash, f"Wrong role hash. Expected: {role_hash}, Got: {event['RoleRevoked'][0]['role']}" + assert event["RoleRevoked"][0]["account"] == convert.to_address(account), f"Wrong account. Expected: {account}, Got: {event['RoleRevoked'][0]['account']}" + + if emitted_by is not None: + assert convert.to_address(event["RoleRevoked"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + + +def validate_submit_exit_requests_hash_event(event: EventDict, expected_hash: str, emitted_by: Optional[str] = None): + """Validates RequestsHashSubmitted event from ValidatorsExitBus""" + assert "RequestsHashSubmitted" in event, "No RequestsHashSubmitted event found" + assert event["RequestsHashSubmitted"][0]["exitRequestsHash"] == expected_hash, f"Wrong hash. Expected: {expected_hash}, Got: {event['RequestsHashSubmitted'][0]['exitRequestsHash']}" + + if emitted_by is not None: + assert convert.to_address(event["RequestsHashSubmitted"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + + +def test_vote_hoodi_exit_hashes(helpers, accounts, vote_ids_from_env, stranger): + """Test the comprehensive vote that grants validator roles, submits exit hash, and manages permissions""" + # Calculate role hashes + SUBMIT_REPORT_HASH_ROLE = web3.keccak(text="SUBMIT_REPORT_HASH_ROLE") + + # Get contracts + validators_exit_bus = interface.ValidatorsExitBusOracle(contracts.validators_exit_bus_oracle) + timelock = interface.EmergencyProtectedTimelock(TIMELOCK) + dual_governance = interface.DualGovernance(DUAL_GOVERNANCE) + + # Check initial state + assert not validators_exit_bus.hasRole(SUBMIT_REPORT_HASH_ROLE, AGENT), "Agent should not have SUBMIT_REPORT_HASH_ROLE before vote" + + # START VOTE + if len(vote_ids_from_env) > 0: + (vote_id,) = vote_ids_from_env + else: + tx_params = {"from": LDO_HOLDER_ADDRESS_FOR_TESTS} + vote_id, _ = start_vote(tx_params, silent=True) + + vote_tx = helpers.execute_vote(accounts, vote_id, contracts.voting) + print(f"voteId = {vote_id}") + + proposal_id = vote_tx.events["ProposalSubmitted"][1]["proposalId"] + print(f"proposalId = {proposal_id}") + + chain.sleep(timelock.getAfterSubmitDelay() + 1) + dual_governance.scheduleProposal(proposal_id, {"from": stranger}) + + chain.sleep(timelock.getAfterScheduleDelay() + 1) + wait_for_noon_utc_to_satisfy_time_constrains() + + dg_tx = timelock.execute(proposal_id, {"from": stranger}) + + # --- VALIDATE EXECUTION RESULTS --- + + # 1. Verify SUBMIT_REPORT_HASH_ROLE was granted and then revoked (final state is revoked) + assert not validators_exit_bus.hasRole(SUBMIT_REPORT_HASH_ROLE, AGENT), "Agent should not have SUBMIT_REPORT_HASH_ROLE after vote" + + # --- VALIDATE EVENTS --- + voting_events = group_voting_events_from_receipt(vote_tx) + assert len(voting_events) >= 1, "No voting events found" + + validate_dual_governance_submit_event( + voting_events[0], + proposal_id, + proposer=VOTING, + executor=DUAL_GOVERNANCE_EXECUTORS[0], + ) + + dg_execution_events = group_dg_events_from_receipt(dg_tx, timelock=TIMELOCK, admin_executor=DUAL_GOVERNANCE_EXECUTORS[0]) + expected_events = 3 # 1 proxy upgrade + 2 role grants + 1 role grant for agent + 1 hash submission + 1 role revoke + assert len(dg_execution_events) == expected_events, f"Expected {expected_events} dual governance events, got {len(dg_execution_events)}" + + event_idx = 0 + + # Step 1: Grant SUBMIT_REPORT_HASH_ROLE to agent + validate_role_grant_event( + dg_execution_events[event_idx], + role_hash=SUBMIT_REPORT_HASH_ROLE.hex(), + account=AGENT, + emitted_by=contracts.validators_exit_bus_oracle + ) + event_idx += 1 + + # Step 2: Submit exit requests hash + validate_submit_exit_requests_hash_event( + dg_execution_events[event_idx], + expected_hash=EXIT_HASH_TO_SUBMIT, + emitted_by=contracts.validators_exit_bus_oracle + ) + event_idx += 1 + + # Step 3: Revoke SUBMIT_REPORT_HASH_ROLE from agent + validate_role_revoke_event( + dg_execution_events[event_idx], + role_hash=SUBMIT_REPORT_HASH_ROLE.hex(), + account=AGENT, + emitted_by=contracts.validators_exit_bus_oracle + ) + + predefined_data = "0x00000100000000260000000000125241a78696e5b09b8e5b5e61a49ff531b3804bd16b1f994540f40540c65605cf08ce957ad0b94e8440cbdf7f9a81444954d700000100000000260000000000125242b8a44217a0c245759175ff7aa0c06544dc88ea65ae1b4adb74607a82f91aad1c6e4b20ba609059e2e6dbd2687a43b73600000100000000260000000000125243a5fba2933049078b3b8841d6ff435004e8fe8b13e2ea166b16195eb6599a82e9f9fe737d0c6d67a25e135ea60402e7a400000100000000260000000000125244acc5a6cad5513f0a8ad300a94ffee73e0045ce9ffc91bd241724fb537c970a7584d74a8c0488d38f8cceef185a8d5383000001000000002600000000001252458fbe581b43bc4bd2e60839e0c93a3bb719aa1ff2783459efd566ea544d16537a430b4efebfb354c67c9997a8937e64a700000100000000260000000000125246812dc595e8aa81ac1abf03fedb706a9eca674c8b166c7876b3682832c55882ba72231a14164d9eece517bbd3d34e2a5200000100000000260000000000125247a2d1cbccd91f15a89738cdc6d91c167f4bec5d02f5b0887a426c6c08a5811153cadfaeaa642258791f12beeba47f27c7000001000000002600000000001252488dcfbb614f08369db636c9e3c0c827b70646022b0922a02f3d4a09e0705510d1f2a674687cc34c6603a52065cc62bdda0000010000000026000000000012524980c5f60c6636a250bd84c8e831dc359d24385fc3981d77e1c912893a3418f16aa9bf2732fc3939dae59a3b82c34ea1720000010000000026000000000012524aa20a4943ca567ec1e26e472538aa81aac2f48f6a259296d601161f54382ef61c8b2e6f96b09886713f57d0e65c59f17f0000010000000026000000000012524b8e7127fb3f799ea4ee0da058eebdfaa7f59a2db523bd20d83c25e04127ec18427229c9ff70ca0869ced0a0373e4f9b200000010000000026000000000012524ca49fda2222e09fb8281c13431fab799657d8a0410d927e52436cc3f1e62ad7c0e6296eae6ed0579b909cf587187dddc70000010000000026000000000012524db8d5df6025bba5fbbb505719d593e94b06044b73e65cd4ee8cb81a6476b4b2fe64b2b4c7a55743222548d020fed1c82c0000010000000026000000000012524e8b1a3fd059496f27bc92c3fbafd0fe1eaa8f7b4ffd02a09ec267093f3d11239268c3da08fac2f1980f7c569fb0e0d8530000010000000026000000000012524fae093eb7fb3fe5b0609148d572053b980e96dd6aa0d9612e51c9a14bbbc4b2e6958247733257879c9f64be09772bae9f00000100000000260000000000125250ab1e5e65b50e661fa6d8579d4d9067fd496feea53470442c1597c4bb8c9a24d212ef436adfa5c5421eebc5df90ca7ef100000100000000260000000000125251a0d3c6255d1f2e91f74b8faaced586142a77a87b114dca129e60695abd81b6e00f7cf88db79a9d6f570d9d44e7e732df00000100000000260000000000125252b39cfc781b9e35d6cf56860cc1630ecd5ab9e433b2c2a0efeb0dac7876ddba98d45aae8f6e79840aaf8569c43065cb45000001000000002600000000001252538c444803f6c62bd61d12db2038b1514b4e6d7130ef765df7afff590ab8580563f08aecf198b73e27c0e614b01de0b64600000100000000260000000000125254a66bc354c6763abb40b2ebbaad1d395b995f8a49c344048c277f42597bbafef474f8938e0e251ecdae6c1acf350beadf00000100000000260000000000125255896fb7e9569da617a9e21776a09ba877eca17a7cd030320f22c4613e9b5d73a64ba73ae9094e80117008406466c1583300000100000000260000000000125256b8ee455a0851ccad89d9a3dc84a49c5cd7f6984ff70352ccfa19db7b3ffe18c939cee1da80501a52f9e980f9d2412b11000001000000002600000000001252579270e84c303514095f050c8eadb67fb9f0ef1e497046ee78481cf1a52a748b0d08c539ec3ad1e718bcd4667bb04b6be500000100000000260000000000125258a72cfaa622199a84e48d59ff6531417f29d443f4d540d0627c8c740bb565d02556be7c7911e0936b667e7267d321c19900000100000000260000000000125259a077184595ade55f894aee536772c8707aba379e19db33fbe9b58c7af2604edb49eb5e940ba3e633613329040648ac1a0000010000000026000000000012525a88cd229f5d9d262e1c544504fec49b4ce161d47080962c0ba2899dc5fbfadc38bfe65e2ae079d662d4a26430b1193aa40000010000000026000000000012525b83c65d891c370600ec8d51ec12e589c01058bf2307d3e598f84b06f3df5b2cb5346e9168444afb1a49bb61f52cc671b50000010000000026000000000012525ca177be81452f6ed7d08238f14a039828fd782b2af7a3ee44852155fc3d0207bc814ad71806033886facef72a5229290e0000010000000026000000000012525d8ea55869a848900c80d73ac04cac42d918a9055f86133617b00558e2399c650d30feb4cfec3e7fcf07221d588f871d1a0000010000000026000000000012525e82778dd394c065c3d9427f181d24619c440ada4391f51bb0a307823d2d8d2880c569480bdf842fec75be529ee56ff1870000010000000026000000000012525f9256b688a3aa0efa2aee7bcf940a213576ec20dfd62d6708998d24ee5feff9136da12ed34202f45f94f3b5cd808a361500000100000000260000000000125260b30380f7fa48c163c76101abb64312925a94af3b1b3d6be493fb68acc84188341cb1c89f5a8ff4822042be0ec050142d00000100000000260000000000125261ad919b76beaf87853b1c3df4b564112e60a273cc0cc9e4a989408e496be4427ca4a50cce8d7d59ba3ae22fb5140a7ef800000100000000260000000000125262b98a4396a14edd3b6f130710903024d2871dcf9fc6daa9644237bb150533df0c545e161fa85160d48941b75f22f75b02000001000000002600000000001252638832a99211494d215bc9e0276b877ce52ed3658f8dc9bcd1258a07c3c788c6c5d4ccc61bdcbc44c1c4ed8039601ba15f00000100000000260000000000125264810340c10905d93b5cdd2031f2b104e1267f047b35c849b33ddfb7b119144c39c905fb8a1534a5070686abb42c7db2a00000010000000026000000000012526582e09256e880437f9e46cd7ef02409c2837f647a9c839a296fff91181cd00e5b719925ec4cbb114c9b5ba9a0cae6f2cf0000010000000026000000000012526684fac01191fc77d3e8f750c05a1a13923c76d5608fb2bd2567475f5df939f6d2250e06b17cac2799e632528841505274000001000000002600000000001252679987b0c13046f1de8413cdd4d33e9ff91c02381b99bcf071872cf590a0a64c62284d512ee913bb28625b302cdc53629700000100000000260000000000125268a50e1b3bd1c26c9c8d66c9980c1783bb1d0f29433e4f92059b167e35ab74fe965f2d30b5d7276e49ed0d0891c4c4ea4b0000010000000026000000000012526994d200a31d1fed7935a1335a8fac8aa7f8cfebd3e3de0c13f7144dc4ff8f973921e39db25020b4d1c65ecf5565068bed0000010000000026000000000012526ab01e220f652a6b6f9cafe8d108197de6c9c897f0f876d09a5aa235adc4358f6e6f3af14eb17c24fbbee069a6242acc630000010000000026000000000012526ba8834293737e445210aa5dfe0346d6cde463782a7f7e206810fcff42154fa86b78f36d0100c2f80390f22a5607023d110000010000000026000000000012526c83fbc633a6388244d4129ea10ccc539c689976ff1b4fecc80c4d36f9e2e0a4ac969136e478ccb1811fbf859ac38d41550000010000000026000000000012526d93be7eee97de6c0c4e562daa75aac2cc90e4ffefd4164effa9d90eff4a21c17b3bed7469701a0249c27798a3600589e00000010000000026000000000012526eb82f51c3a521e5bcc8dc0d7e7a4e2b9aa62e52686c44bd88056b4f1f7726988b50dfc4b1b623ed3c6186a5044e4e318a0000010000000026000000000012526fb66fd1cf3e2932ef26a9311c757377c12039ef65ac662a7862752e747b0b6166748dac83e6ff802b468f547fd02f251600000100000000260000000000125270b06871f106ccd62756397b225c7fde7e06fe2ba553621f19dfe7f7cd64c034aeb844f0e390caaf41fb0023c790c4520700000100000000260000000000125271ae8c39361d488067ca653ecb91c5f7403ee757d0724a074009ffbde7edcdac74f10f1509ac25aaab479a7e78d35a892b0000010000000026000000000012527281115c980926984afd742f49546c67a4433053257033ebb40e36a8c217822c7b977e3cd3b5d11739cf7de65cb1ce10da0000010000000026000000000012527391fe01afb5487303728fb5f381ec7fa5a8b194e5abf9712eb387e001da961e170aa4c34472f2c4272c383a82bdfae90900000100000000260000000000125274958533da6603bd473fedb65c418de855c71046e3c881d447278dea581fc20fb6bfd94668aebd519807ad656c83be05db000001000000002600000000001252758e4db1d403229fc8c90e374c7406ccf2d6d0e4f424bfe921bad579df183fb044bb9c5b55b9c89044357c4234c6e1cd3e00000100000000260000000000125276aabf438f83008dcd1379be449439996de274d060f80b7056fe950af9c71ae3a318a558968b4f003837debc840692711b00000100000000260000000000125277b6a063833ff1a16d4055a8db7d3cb0026f360e77134bf6a6b40f666b920e186a66139c7f77dcd13f0f2d5f8b9f24cb28000001000000002600000000001252789887ffcdcd77b56419913d22e70dbaac36b4fe6404f80c4cf2ef7cf03162bb2db49b2ce7cc3a8018104eac2f8eb6624600000100000000260000000000125279a548e8a5b434c503e682063bb4498c6e021112c2b44d6d77de4b2513e776816afef3ea21cb23ee290e4fc98008ff18cc0000010000000026000000000012527a8ab88b88bf4c93b1030e2de4ee09ee9947ec24f6fe323e8e1b1da45783a029febd91bed68ddc6f95a38d3a8b0cc620120000010000000026000000000012527bb743f4378eb045adf3a05377215c603ae42d81c4279723ae10f831606ba6a6ed77832e4a1436341c8a0b5874d78b9bf70000010000000026000000000012527c93d3ecb4efcb9bc0ea7a7b9f40a05b54d74a71a3ff9c59ab6a810039f10351ef2c86497552f99594792acf2e03b4d8060000010000000026000000000012527d8b68cf65c3f5492374b12e96383481d296fa0b7ac84859e12426b657115b039d411edf4c0de05b9343e69334330a33030000010000000026000000000012527ea71d99b3ed80c4554d2957833ee0cdf1d8b3d194772c255ebb1ac12f4fa28d0b56f90ceb1a38337e39f57474dff4359e0000010000000026000000000012527fa19f21c2f734e752d5894141966cd1cf4f14d7be6b302a0aa62050c0b0670b8ed70631e5d04bc0b18189b2b71627707400000100000000260000000000125280a575663dae8c4d447a7b5fc8969c5a9baf1fa0fb6eb629bae6177c54c66ef0edde1c9b3ea6be14939e35c56fafc4c8ae00000100000000260000000000125281a032b503d019690a723d63ca473e12522d4c533a2ca34e0cc3e880a2e208194b09c28ef5bd466dc4f130a0ef5fefa675000001000000002600000000001252829165f4cad0680fd2686255c767518b377bd1f80ce86011131f766de73198cf4cd0b36f883f9ecd1774d67b394f5cb30300000100000000260000000000125283aee2e274baa7b4e004bdb549bf10a79ee68c639c7992ff3242fe7590404bff0ec789a9a341ac534278e8c4ffe484e27200000100000000260000000000125284a4ec7c7d6984d8f3ec676ff8b8e1bca670684e322cf38e325c947091546548365bba1c07321ea76d1517d26f0c291330000001000000002600000000001252858fa51e4a642995bec93fa4bdb9c2807396c3a2de6712f69a45b5c8b3244212ee63323bf2bbd9768484ba1402f19f59a500000100000000260000000000125286b2d478d8a947d0543becc23e940cd973a33f0813bb8170be045afc8fe969ea8c0d2bcb4623ee7c06a43369a3b4383f3c00000100000000260000000000125287b080c2fc4d24aa183dd0dc8b08aebfc738d2e3a7123d8550e41f84ea54e70753fe315c6f9a39cc8b10687cb8683039e400000100000000260000000000125288838867d06185facdcc54bc7c856641f88c2ad943de3341132f38144744257a4816f83340f0ea8db2567716ec960a626d00000100000000260000000000125289a0803ca700aaf5f125e42f4f63f671cb9e035498713655b904ca4115d591ae88a5c7a169d82f1e257ee88e23490e0f7d000001000000002600000000001252d58da4818a14c457c6d57c278d7ca10c9eb82d4c3771a5fc7328e632e54a03572685844f5f43b3e40176e0bcae54327066000001000000002600000000001252d6a8ad8e507ae56926f290062069b552c24ec447f4a6381ac6afee56afb61f44de74c0c8fd6f3d1d3e2198fd01e1e1d241000001000000002600000000001252d7b68e7a1821d635e4bf3f1eb32bfc44290d632bf7d218fece3094aaf19249a500e4c6978e6eb9ec5dac220456c0d3a45a000001000000002600000000001252d8b2e96c236e58e5aa86f242e095d52a0518a78282e68df7d9852f55b540f9512d7fb91aa6337897361779494e1ca70b5e000001000000002600000000001252d993330f01ec76a986e7f8a3c0862582ffc360d42fa5befbe73970d8c7296bc30ce6b97f4793198630f909bdf5645703fa000001000000002600000000001252da871034b209a52088db33a69940c54ac0b734cc0aa1dedccceda35c86b1f22703c692fd9933f2ab34174d3076ea1c4562000001000000002600000000001252dbb517d8d04e03f6edef580380755a0328392739a94660752501e24ce3411381421ae223e81077047d3805b78fa840e165000001000000002600000000001252dcb84fe16379f2911be8fc3e47db5cce44f58a385eaf35e892c94a9b12c5b886fdd44c88ad00eac99c6e4c29255cbcd751000001000000002600000000001252ddb48c17e8da8c00923f6e6f0f5dd17f609f737eef059046bd413b4a69e5e26c25c59ca653d7d0876648d41f8407a33c15000001000000002600000000001252deb9d6487457b5d0dc6a3683b3e7e1f0d763869a69a06233d3b58d89286f52a2189d015a4e5c9b8c73ffc438051fe5812b000001000000002600000000001252df8ef70f0e8b0e8baea62288799fe2385c56604400d69682debc0014c456c74fe525a331008a3a12df5b5ff1bd67c29455000001000000002600000000001252e090b669b215f3a4dde3e56ea873d44ff57c337cbfec1867e3968be6ff2f6021254a5d6560eea88e602d1a871fdeb26e1a000001000000002600000000001252e1abe99cf4ef475b5923b27dd6e65bd5f1bc2da262bc890edc146e297b0577c6bdbadc8658186ef5335ee1bfda32766849000001000000002600000000001252e2b57d322af5dc24555f8d350375467a0555e150c7ae88c9390f516c4d5fc4d2a2acd5ef8a9fa12e60ef2d976056012ef9000001000000002600000000001252e38b3fd0cfacb06c7cd570801339ceeaea0740ac7c0b8d048784581dbb7df38cffdd8f63ba21a2bc3b6a14fda984272178000001000000002600000000001252e4a1276ccf8034214fcd2c1853af3032c778dad657b56be69dcbb8476f2fda3e33ff88ebf5c06c66758d614ebabaab2784000001000000002600000000001252e58fd3278d4cd8e5a34c3e313d31001e32b863213f7376e393c05d17be5cbdf5a2f17e2c7febcb436862ae9a8641ca8ded000001000000002600000000001252e6b9f5ab24bdaa786028b99f666184a16eb004f58fbc7470b800718a50114e2f7ba0a03a32eb8611e7f124fc378d60478f000001000000002600000000001252e78e8af884dd599351a7b6df911bffbb683a7276fb16a16565174972b01e2d20f7d8e841cd0d14bcf5d2758add730ffaac000001000000002600000000001252e8b3938a498f3793893882400b32b063b1089cc1e7feea3b7d3c41c0a2a8ce7b908e0eb3a8582fe203aa9b53755e844319000001000000002600000000001252e9a6d73751d7e509d2444fe933d910efe3d4c915d1ef338aa9314ee3e4104fdbca4fbee1eaf97fdd7a8c1142bcbaea5fd3000001000000002600000000001252ea842955a6544ce0b48988ec10bf8125642cb0afd32161a8cf3e0af3c9b8fe2c0c06a6e1094f0dbee9f235a70e93837ef5000001000000002600000000001252eb810c9cec83ef31f9da5fe44c3bbbc151d3626ab36320fcc6ee0ff013bb18451f10aeb0241157d592760d1f25782504d3000001000000002600000000001252ec95ed9ca18967a86b92018a17e0f7a5623c5ca48c2f7d9332d4a0ce27f856908fe0ee82097be8ea05d8726f72d2911579000001000000002600000000001252ed967b4d723e0be401347d26fd46600c9d4b45b85bf5f7de7bac0010bb5168424382e721bed78fb1273e640bd20f15a2a6000001000000002600000000001252ee81ffbcb1b8039361e70703a9925ac819eca6f1fbcae8dbbda31b8fa9450682351bb43c4c669a1cbb876be0bb989be9fe000001000000002600000000001252efab6375c8d70ab886861cecda83c4fde95b10c501a8ab8d0ecfc501e6fa96f598e0525cbe5c871fe7d79be42421cb81d0000001000000002600000000001252f0b212a4feab71963596686095fd1021a0cf9962d308615f54629813b14bc05524d912e1ceae98f23f8b8b38c8d4625c49000001000000002600000000001252f1b4621b66673e7cd80cbbf5b7a7a8779f5d5b763d4f1312f50a58467073bb78c898c3363f3d0d52262ec4fdccfb98aa5c000001000000002600000000001252f28a279fb389afefd8fe5b590f40e7f9c5e0b0f5b0dd056547bf2d04034fef97d42ea77bea8c211fcd4b20d76e70fa9b3f000001000000002600000000001252f3ac84b36a7c336631caf27a4ee8c1799eb3c922c4a4fa057499bd95a620b66ef42ff894875a31fd72fb3fbb97bb92633d000001000000002600000000001252f4a02da670cffbc3e6c48120b3bf9f0599b14580ee2acc20908d39f4e9b966d3e4dfa1b8db884ed67718b1e18ce85a79cb000001000000002600000000001252f5952b150bca7507cbf235b5bd4060f5ca98b387a09ee94507a4a46894c424d42db5560cde6f824021d5bddfc2773b3c99000001000000002600000000001252f69036a3f72b0d31bef883199eb026cc64b1ecb3c5d50e30f3ad833a2c15267b874eda53c77a9fcd6389f9764d40e34a77000001000000002600000000001252f7b2ecb3d145de2a21f5a59e841e353f596d0d9407151bf1ec0e08ce4818de1e509ebc4e9cf8bdc3b12032c39047db01fc000001000000002600000000001252f88610e1fc4d141d31cc60af272a5d5f2f4620d13106504f09f8e32139f3f30e20606034a3787cc6bbadc3d48689f1e611000001000000002600000000001252f9abb41acc13110a844e57a20b4d717453473460b2953cf033bb88709faa21d693a3c11e14bfd3e427f22fefbc37abf54b000001000000002600000000001252fab66a6d42a4d14348265437ddcd53a0d06ccfe93a9accb3d0667ea870c088253adfb672b585d8673c5e65f84264fa0a0f000001000000002600000000001252fb8d79e117680127c48ecfb72f6afacb9380dca7458dbc03c3e260e8bc8a22e3ebfb82161da36cffb9911925f56b7562c8000001000000002600000000001252fc90d4c053996b3eb8f9970a7b9aa125e5515b688c62d80c10bf856dbf3ed91efcb0e012eab94038cf5b1dffc33c919589000001000000002600000000001252fdab4513986d61aaa94a6bcc12ae198e786fd9d6b8a1f8b1724a5e3f994a14ccfaec06686ee0aab188fa3456547841877f000001000000002600000000001252fe866baa0d4c82a48d4750c48f28dc5405d107df0c3a2678f2ff6a7a72eaa1373f22cb64f0e60786cb238a3b4be2f5225f000001000000002600000000001252ff8b8d5192e62acdd4fc158ab83a359bef91a348c9bb57fddad2ab6bbdd4ece0d22455af700008b82967bc8b30fc68e32f00000100000000260000000000125300993f0a3ee8b26bf8c2855acc7016a7ec96b006278943b914a3c05b7998412a18546ad92231b2c7c571863d442fc3a6290000010000000026000000000012530190e93e18e232cda4b41c5dda5e1d79c701f0582c0ad981cf9c9c941784b0d597e200ea744e41c9ea3b1367339261905c00000100000000260000000000125302a6fade2e8fbb02066893893465590d5fd592797e7146a96a0629b67a7a67a05ff3a9b7d26aefef9b1f60caf993f7c744000001000000002600000000001253039930f3ef547d97f7eb7d739f1f211d16839a0864acdda100a152f8a9d7ca0d86f78079f58cec5830297e1ca599852cdf000001000000002600000000001253048a0e572061c69dd79fad173ece7d48e06a1b447a84374b3442c36912dc6b896d37808e4e8f9cd9852986ee486571dbf000000100000000260000000000125305b533dea629513eb97d16e86addb53a3137b91f2f9aac9dcd4f6341d3d51807157c92b7e91b82a93833197aecfd20283000000100000000260000000000125306a5f1e37cde85836dad93867c5a6d452558324069b68091cf619e5dcbbd26fc4212ae0377f3433fb07dd48632d19f0d02000001000000002600000000001253078557563c860785bfe3fb875dfec9e9d9968ea522898ae5ac3231750f9748dabab7fd5c66e6b22705b96786137c23736900000100000000260000000000125308a2bef14758607e02ee4ed50fcf3ea4903b942fa66e49e4a8657a6e8afbe8b2980ef3d0befbd80eb8ce211a97ef779d680000010000000026000000000012530993e2edcb9fe9c402529f7a574c0581cb3b259a941ebe36d80bdfb96fb5787683f1a16d8cbe8bc09597bfb71ee9bc8b360000010000000026000000000012530aa37b30a822e209bfd728fdaa62fa187da7946b020146730af1095d990bda30381fe9b7e808d4ab06613c4ac98be5a9a60000010000000026000000000012530bb4d2be2b22e124fd1d9ac1c71e41eaf875975491e76d1073f68bdfdfef1da2d932afe8e6883950b9c6e569b2059b9bdf0000010000000026000000000012530c96e8acf32ba89254332a831e677688358663f4bf2a227f1df295810ebf9f6ced75b3e75edfef5bcbf12a082d710c3e200000010000000026000000000012530d83a974e99dafa6b7c2a19fdaf30ddf3f8d1201ec1b0d7077705dc3bad50387d073a5ec4585040077dd31242f2af1cf890000010000000026000000000012530ea4e0044e366626dc73ca779cf1b1d76abb68b3788b1a6b66d8253eb251b07d8ae9ff548c54cfc0b8a6e5c1bc7a2349000000010000000026000000000012530fa4dbb33efa6c170797a7266822741f8d8b044bf7baa5e02c5e5c645f137a26608d3263c060107d4eb843841ce5a880ce0000010000000026000000000012531099abe403f0861ed6e9be8870522dff95f79f0d1a0dd5f5ac5fc4dbe797d75b9bea2c16b06f359e1ee20304f5c76f08220000010000000026000000000012531192d991602bc888eae305688522de28bd208af4ad1f0a50682afd0343880d374616b4f9afb734a132750d5085f0fbe8ac00000100000000260000000000125312a0658465922e8e6a15d1202c01250d8cee5f0f9a2081178e00770555a2f720d101691ce2a5d70daa79e11fe9a1e03f9c00000100000000260000000000125313afef1123260dd615f6c1e178e39041c3c6527f9ead919ac2c296d6a549d759fdc0158cf5cc734b1a04e449fb513fb5280000010000000026000000000012531497e957c69c4975f5bc08644381ed43f7cb4c5c741944d5ccbc3a312a71471d63c24e9037e1c0dfde3fd6d857821d2a870000010000000026000000000012531593a4f32fe66be5a4b23f70484a5540b9d9576fbdf59e9ad9df579625e2c1a3a1008d7c7107d5f078da1d8bc713b524750000010000000026000000000012531680c41e0b3d02df3f182039a71869563b0e90114e60f70a029d028d13fad4e52a3ded858ccf137f936d9468a7a7300b9300000100000000260000000000125317a3dd2a397f55e3e67b8e39f73d3e94fcd77a43348bef6b60647dbc0a36917fb241374038caba0850684ea4c4d715a28c00000100000000260000000000125318b71965e8b0ef9b4702af5bc26a18c50ac7143953eb08ad8fc9758fcc4b375801d63081f0bc80fdc13f502c4b7020ce480000010000000026000000000012531996b9a68023ba1d801192585fabfe4581fe21c43e9b638d9edc8f1601e0ac0a74bac89ebda386aa374ba5fab3bdc3c1180000010000000026000000000012531a8ec90a68ad2b4b0daa88e376acec3dd5b7e25f38dd8b4ad8db50c502d42fdf44739e251b6224801b1c06829ef7a7eb720000010000000026000000000012531bb00b7d10d1079fb411b6bc09b6a61c47a84063e43fc28ee43c7241368451c249624f1c28bf5ec9ac2ae3dadffff5381e0000010000000026000000000012531c9290e3cdac716fbaa130803738d3f641dad19c902acb721994671e8a682fc9ca6f5ccba79201150a93975e248b6ff99e0000010000000026000000000012531da914956195cebeed7928298f274e1b573b842d3b9d82d432c3fa59734fc163c733bc5fa22bccf37d14387e5fee15563a0000010000000026000000000012531eb9cdf3a87fb344a1884e29156c8d1d3b6e7f41cc265575ca95918df9ff5d65e5a570274ecabf3bd66c3642a789de26090000010000000026000000000012531f8fc84a7f1a6b3574a784f53fa3a044277d1f3631a1d800df2141154424f61f1a1869836305b1e4a6a7d29ad484ccbc400000010000000026000000000012536ba41ed3cb258e2c38db6e1646ab8cda121bc80b9e6a2be68a8b051e2fa8a46aea79055557551bcd407f5537a8c3ca597e0000010000000026000000000012536ca5b4df6b47b9236b1cbb16bace7210da26c08e68ae78b98572d5f55ec5d90a90069d76d59166f3cd3e93fbda5ff0f38c0000010000000026000000000012536da398f2f24c767ac2773a7d376e8a1c70930171c925640874c836c2ed009860466722ccc756155bcd7235bd460dbe14db0000010000000026000000000012536eb145f878984b71dab654e2c3395c6ea7f5d368d3c71cde818d7de6f142e8c26d8e4a92c234f6dee17ad101a124e307b70000010000000026000000000012536fb441ef22d54fdf3229b44c64138dbc6aa42fc0cdb6d49c39595a8abceaab010f242159ae8d04c42a1f54cc24a5d39d0400000100000000260000000000125370978e3802fd36e469dc56d0f7e54c69a81d065a964f2b3da829b5f70e8bc45dfd9adaaf764c26fda8a53ccf8d4caffdd100000100000000260000000000125371a5a4b7f63691f6cd60c2095c220aa3366cfb824f801a7588a5bbd6d549bb3e45df989bc678df8bf2b816101242b57a8d00000100000000260000000000125372813d1155a185812ab5d7387c10e2699a68b7d6c6466b7e60e3af4f202cda1e5be7b963d1a27b6882e10d97d0b782f29900000100000000260000000000125373ab88e1684b3e301c6124e243ecec4bda5707fa32e2eba855db76b22ae5e38fb8a929bce45ad1c03899b4a6050528209200000100000000260000000000125374a7f67f303548e467b3e9584c72a38b44223cb67d30aa2fa5a5ff52cf316e856770770cc9a83399fda8bb0a28b66956fe000001000000002600000000001253759115d220d9a9d4c4c8bc5b658404115db571e388041f60a5b95fc8bb59a0d7bc2b6ab98332ca015e1d048e2a1e63f49e0000010000000026000000000012537685b6aafb4c061ec026b9e19d24dd2e1eb7b99060a9b7acc107e40604c62e66311a66633138a94a8901cf6ba5e1d3198400000100000000260000000000125377969ea527c3daf826d344a18410abd910a1b5dc3047a6ff1a3544aa28a3ca64c6836149bba18752bbf166a85d5f73338b00000100000000260000000000125378884f9fa82facb8d5e1432c80cb8600dad663259aacf0d1fae0dca6fd40b9857d0aca3f1c3d0c5e15b489e8356184588800000100000000260000000000125379868c12072d9f59f1919e13a24ab6ae29a147a4bddab7707db0259144c60365daed03dc29b6789e457603b84b991776d90000010000000026000000000012537a8dc8b9ee7291a4c813133fac04062845e070f6e2f549429289909c295dc94381b320b39e9b5f07489ba2a2066cbbfc280000010000000026000000000012537b95e673d8044e88cf729cf1adcae60e5bdae743a3dac242292c80bca2d40a3cb2ad8d3ce4db3e1e37567070e12231cff90000010000000026000000000012537c992939aeb33b0c20b959e487a4a15fbbf915c21f68d9255ea2afbb731fa7aa50ff881a6e53a72d832cd2aa1d0fc2a3a60000010000000026000000000012537db35022a8df87733f4c727c833611f6a71dad923dcacafae7c8f1832133440d47d4be9ba9b0f6f60c10e498a0a83790db0000010000000026000000000012537eaf90ba3fe882574df9bad08ada5d65f27918d8168252a5c1d1c2247c3f4178a7b699c348fc249b6dbd42ca81618298330000010000000026000000000012537fb7bead53a247e16df6ee5bf5075b608c4b91cdb36bf644765ce46afd84a1d88e51126ac84edb82b3d1b855d8ed83dc5f00000100000000260000000000125380b90a7101ce7e6daa5ef6ff44c73411ab4d3b58f0f9d017fcc6156cc12b5fccd772a7c289847e5db98f0966390832ad3600000100000000260000000000125381b7d9ed530f3b95546799d1b76102d98d52cbaac57e0d4ef30c07317e0874a55bb55b675249e8c559b06cee5c4f4a1cd900000100000000260000000000125382a2c4c57915f591c61ace00d255912c182944736e2aa14d2db955cf49b0d622b6214c2885e03c28adaf9b7ac37d15d2470000010000000026000000000012538393faa2e95d3863de843700295301c06bedc90b6c2e0dabf82f9ecd67640580f6997a227619f6d16573c54f4c209e472d00000100000000260000000000125384a0177fb6201cf752bfe136fffb7060e1e6bca7bcbb3a0197e950c5df1a44cd0ede00c7e40c41e8844a20428b56a845810000010000000026000000000012538592b41260af27ed932cafe353cc13f76771b22a164953ef4324dfd0babe52e0634ba266754713ab0a979e6354335f391c000001000000002600000000001253868ea8505a936579d19ba604a28ead4848fd9482b4f28b9583b71babc86923f2e8a9e73b4117babfafb67ad9137c53530800000100000000260000000000125387819278a7097131d1a4d946f148f9fcc72f0fccdee8b0bc8c499cd585d11e3644957d844944c88e7f6f8a2ecd1c3e5fda00000100000000260000000000125388ad7ca88c0c39d6220d0aa7aec6f250d15f8c3a28899a416cb68110dcf9c0a0e102e91a7e638a61037b6e7b3329084bd000000100000000260000000000125389a0c2f85679dc8a106d3e49917f1f4dedeef46509c6d794e0918e438865790a8cfca40c4adb856c165f44956f3917a5490000010000000026000000000012538a8204a664ad52fb72d6c319873755fa3d84300a4f7361305069684902ef968e5b3e71bd701b08a9bccd4084b8c969078e0000010000000026000000000012538b953b83eddf635e2ff37ea7c33f286f27827068039a650fbd3d2831f6a9ae3e46a23a66a0eb8f2a84d8fafc4c7b4b78f60000010000000026000000000012538c829e482b083370a195663218c0aad3c62a5d3738b580e685cf2b8a1bc4b71584312b226977fe67091978cbf5eaa83e4e0000010000000026000000000012538da4f872fe9112b71535d3861e4ef21c4a491a8153766a09732410d10a67766989fed20aa5e82400ccd59a2a724c7a7caa0000010000000026000000000012538eb2fb15a9510e6f34a0a3a856496fa7c5dc7124656571d66aa98648f9c57dc4fb12b7549d42784e2da098aecd47ca04d70000010000000026000000000012538f8b6ddf077dc6cb847f62026e734420527d767ea17ccfd649986515298b7665b1113c1e3ed20e970acbd14647137155f40000010000000026000000000012539089baac2c151854774a0c24504f13b9c7f016474b51a3133b347a47b1d6db3922931ada37050f6339020798c6e1498988000001000000002600000000001253918128c6eae35338d2737f940a32f5cf32ffe1c9fec24c691e4a4abcfcd95bcc91afee777c7d24bdfd77e0424a2b365a5f000001000000002600000000001253928e4625362db0994c2a334e9ff17b82bd93367480a4ecd6ed9c31bf9b2fa9137ef3de782c4ad78e3dd13ead4d35752aa200000100000000260000000000125393a5bbaec0e7a10b5a25c3e9bdce2d9cb657acb07fccced27f68d4a8d10af3d67705e7a0b51301c843281df2fa2820e47a00000100000000260000000000125394a8467e87b2f2e551f16e38495d95c24ab3ad510d62cd2fa6411121f0b95de2099c3712a1c26fbe838d5751acaa24293200000100000000260000000000125395b16c66d949a116145486d3788a2fdf97026bda69aeec7707d1c607f4fe2c68cff34f9b00ea950d34e8f1a6fffed183d60000010000000026000000000012539692d0f778470936826d14d51ca1b8aecdbadd531c5e7fe300c6d4e240d2351bd65122e3d3f7c24d34c54cab4bf8c57eb500000100000000260000000000125397a6388fecea629844d79ed6a3b15ecdd4f042669bc740deef25f340efc6ac8862225e8585008644fdae8ce40939487dc100000100000000260000000000125398b8032433a7023d80c3b0c26977d6251d80fd8db6987bfb1ed881564e84d77dcdc9aadfded45ad6e2a4539361d47043e400000100000000260000000000125399b8e4da452d5f33ff2e54454542fad711cf1eea9b9c8f15e03b72af6f8f7a4ea3314ba28482d218f30e672d6c481a49e50000010000000026000000000012539a8e5ed67a580b751d42fa372077ea1196f45f2c90e02956d7421f86f09f2b34248e8ca630be35cedbc7e27e3571fbaab40000010000000026000000000012539b8c46c1d0aaa0947fe9dda1f6da325d4849d7b27bd473808121cfa763229a8119364b5e80bee904bbcdabe96faada77a10000010000000026000000000012539caf279599c0c592ccae11685bd5c525985f475474261423ee90e0b5f014cb8003d7fcefbbaa0828dfeed6a6dfa7814d590000010000000026000000000012539d8b68661d07bd11cc371da4691c6c858f540952bbfeeaa561b7c10f8c2f7992d6ba63b51f93429bfd23330bec8c712d410000010000000026000000000012539eadf816c2386f6554c1d6cec874de7a7beabbfd2ed7b6550e25586f9fec41a6a13eb719c241aa8b48d59b979a8957197f0000010000000026000000000012539fad0cccb3a61ac475bb20afe3563cad24e041121dd1668cf28cdc6bb0d5998c5002cf511f23da19240c9c33ce71cf0c30000001000000002600000000001253a08669ab1a36ec42c5b8c5bd0c6319a2fad6ad7f0221634cb8142d45c14a3bb0cee46f4ed5dcc905031969075ceb13e7a7000001000000002600000000001253a1b5a08348792adbc84674eb8a776bffca397711efece3ef2e55eac2575f6e3757f882c6a662b4e1aeccd3b0b95b096eaa000001000000002600000000001253a28a1bfd5056efd86f348e9c781c0d038fa71476ca23eebcd31a4eb6308c2c38a72ea3bcf532770c9ae02c8d0fe064cf35000001000000002600000000001253a38b33de08aba83c3dd1b812970307d5dd260e57cf94a9ea8e7c12a36cf0c1e792cbfef9ecae147b0dc2c6d858717c0127000001000000002600000000001253a4a86e1184a57b98610860a36906bbe7217caed69ebcb69f548d80372adb2301650c170fc5d4be05120aa5be367321ddd5000001000000002600000000001253a5ab9a4310b9c75dcde8946715497cb923637f6d117dfc102113c17244aabc798d880daa3ab59aefb4b5cd15cc23aed945000001000000002600000000001253a6ac475546aca8b6b1f4601a6c8f43e788189871f9b3ea4ebc45e5d07e86724871aa5522ff99436dc42a6ad89997315591000001000000002600000000001253a7aa4fa9adccee325fe16d359c72a152783ef93f2c228fcf7a6df04c25ef307b910944ab9c2863e7d8b302a9c20f17bfac000001000000002600000000001253a8a526972c7c11404f4dcb0cbf83b515e313689d73069010373600639b62bb211dfe357e882096fc83345b3e741d325cde000001000000002600000000001253a9853e34d6b0d78bf059430ec46a4399f7de035d3ff2a73ebe24ce9b1b1135350a52133cfecd6066ae5af3603f83113758000001000000002600000000001253aa9182e2549164c4247cdafb8d2399f24c1bb5a1afd3384ebe928d7c8abd0bb059e11c302f3fbe1af5208b0fffaa8780f0000001000000002600000000001253ab94ca6cb61182885770cca517562d6fba26f79667b2c6a59b73cda31e3d9ac0075d6ee4dce6ddd9b47d34562b87178f3d000001000000002600000000001253aca9fadd9e1bdae121432cbc2150fae65a993e740ee10cec8db8108d410fef6b2e66bbc8c1b6f2a623dad8586f20c4274b000001000000002600000000001253adacf620f53d5b878e032aa907a734236865d8971b2c47e059007b2d852a92d202b61180ba737eae8876572840414afdd0000001000000002600000000001253ae98d650e83ed9f7b9af693888338286ea2ffc8716cba4c2f51980f54fcbb35e03c00bb947db8a211045e4dfabd858c111000001000000002600000000001253af9340b90e1985c7c0a42e1ac73bc26acfcb9dd6aab738069d5cbba3bdbf7776323e9911f10041ece6de8952d55b31cc0b000001000000002600000000001253b08c12ab4c408e74ec3bed5fa2aabb7ad0913e410e29a9140f9d052dd9f2483a78962dcda7dce07b6d2701a2f89c92dc76000001000000002600000000001253b1b62ecca984d7fcc086bbcbb5bbab3a9a208ce275cd91fa27716b88a60ff31ab2c80a3fb37ab3bf4f8304a387ab32bcaf000001000000002600000000001253b2a1f8e86762b40e8495c83b5b515c8b5750376871bbed3f0737323d4168592c28a08ce3fe59644cb4c79e4004a0d0b2ad000001000000002600000000001253b3b5ecb24743103565a804401a3073c6f4370508c880ebcfaab3b431a13b76a68bb363ba18da428c233479d964919d3136000001000000002600000000001253b4927ec20bd63e9e1a5336634b03263b15172b5e28f5c86336651221031bdfc8368f5a2e3dec088436d78cc13bb2e43e93000001000000002600000000001253b5aa59153933922f6ff46b1cdd1b61fc728355effd3566aff9c7bfbc8779eb2bb72303c9b94ec4a2afd41e7ed586b1cca90000010000000026000000000012540181a9575808cf495823a9f87e55f1eeda10fdeafe59d8a91cd75bcfa23cd3f7e0137fd80a6726bdecaeaf20619dd27f2c00000100000000260000000000125402a4f7a30dfee8b8ea40a19f15e07632b29d53b7ebd160b5433f365aa3267944e3feda161ca1e1c78dd984a9505118a55200000100000000260000000000125403a9f316bc3e207a5b406c8ddb9c1d9882b3649a3b7eb8a6603d7400e4fb8536f96be4a74474e3fd6b6a9aacb9b3c53484000001000000002600000000001254048bbe717af81bc5f585bd28f310d71141bc135693b5ed5c731ec96a03e8765d2f05e922c35e4227e61656fabe04d4a84800000100000000260000000000125405b5c4895431d9204190bad05f697a1761c4e9f865204e53a546e9f46763f8cea076ba6bf464315a890b810348ea4eea530000010000000026000000000012540694c4f519da9abdd90e14a591f4531dc29014e4d39c69d2dbdbe9d74cfbf471792ff3407ded6c545223cb0837c3b0d83100000100000000260000000000125407abfac725ab93aa99f910628f8aee5d93d39b76e1b65b2952c09ae05c475d88f806559a928541e5ba7bc672b0cbe30821000001000000002600000000001254088c5bd11eafa0bd3b06d994532c107288cba2999fd397e6bf87f653ca12b42ec4d113ea5a2e6b429249ee94a39d949741000001000000002600000000001254098f31331bbf81101124ffd64a5759507b82f9bd090c96d0cf0cc7cd4f9bc9eb2b29a7c7e5a3d06a04dc35df9d5f6153710000010000000026000000000012540ab8d4d296caab8b8f803270279e21624d6b6101821cfe279ea588da3283a9d65d8e52801a5d6851fcb7fd4d3ecba8ad0c0000010000000026000000000012540ba8bbe18a52037a3cc96870c4aa2f96ce505df0217d9dc8c2210fc9fe33f16285a74da0461b6b2eefe7881a456c987d220000010000000026000000000012540ca0c1a8804f85ac54fc9bc7a74f588a955735bf98114b75c19e46ac353414360c4c2af575c3bb98e47bc3de3935dd4e570000010000000026000000000012540db368e50f3c76bc7a80ff7f60903260f6f8194c6fd8e513af92a0cb4f4d5f4ca2766ce819f91d15b5082cb394bcaed4c70000010000000026000000000012540eb83abf1d1ac8769efea5f31bd0b4ff5e4d8a1e2c8b4c2539acefcccc8165bf8631bbd5dfbf0cf375f813cfe8d2d15b3c0000010000000026000000000012540f87527a0ff7135a05b6fa54fb7dd2728a17b04a99b564c56de33fba9d00ab8c0dadbe166a797b879615313af4251ad5f7000001000000002600000000001254108a898a2393753acfe388238c125367499ba5c50039a01bcd95366d66948375fbe9b3f2ece7ad07bf2dd68b391d81cfd600000100000000260000000000125411ac9450d470fba74fae27e4a0f4351ed83d0ec369f33bcfd98c64030196d316b1ce7dd35f78278ab92f8868b7211a791500000100000000260000000000125412861c3888729f5b533c99bd5dfee0249cb1335fc3db39ba83527197299d5551f13b6249acac162d6c0db3758ca87619d800000100000000260000000000125413b31a1748c123370360046564aebe43a536ef68caae41230c6534e5197ccc5e65363dfe82990606c5b85c19439d7575c000000100000000260000000000125414a9ac731120d82ad7dddac5d85fe326d734021f1926a8609ba2b96336f3879a77d0440d1afd472a51e30d1d36b2aaa63f0000010000000026000000000012541587fede409841144870524f19145229e3795286ad1db13dbd5d9144ce3024f276443aef3454f6ef22e978a8260c8ff067000001000000002600000000001254168f1092aec5e6bf58cad03801148b3b2a9a59eb42e61d98ce812ae2284010a986f43867afef8a65dd55f55658b99da190000001000000002600000000001254178352daddba0c1ae104290e657fa330d85d589dbf13f17dadb37455a6d87a60071da7eb93db2a3acf5bb3a83db669d0d600000100000000260000000000125418a7cc7ee8ad8c59a3998d36495f219dc9e4631ff6256c97bf91edd29536873b3d5910a6be1333373302d0c174baa34547000001000000002600000000001254198f08dacb75d16448bfc094d18c74d8fd91de11f3dedfde085e5f18c96a2568483c22b15ee0ec85ce2d0f7f5136eac71b0000010000000026000000000012541a84cd8aec48a289dc628d355dd68622cb6a7c9c8926a1333b35470d9ae831f7ca1d10bde244f3bc9e01176d75630bd7fe0000010000000026000000000012541b9447e07c302302c36f17b5841e891a10bcb29fea4bf7da46dbc56de237aa0294567f90878253e48088d54d15c9d4f4880000010000000026000000000012541cae16e40da4d05d7beb33d1034cb9ab5cb95cc5532eb72ca6789c7d34d6769110fc0468eeee77635b2cb023648c3e19d00000010000000026000000000012541d90710706acc05561b33093fab5628290cd453a3da2da91e5df6f0ba869fdf65533173da65b940ae675b314db491f33740000010000000026000000000012541eb89fddaa66b7e4213c7f29749dd0b49dd02c2e11d9a6fd189fe591bad68c6d54bf9c68f8d91a9fa801b9f628f3cad0a50000010000000026000000000012541f8dac4152116994d4f8d53202792daf9f454391f7fcefbfef800d0011633c5130e18ca8a77801063eaf8cdab2942f060a00000100000000260000000000125420816b73170c6895746a800f49ed854c90f05a6000eb8ea7ac73122cedcc0667cb44e3b950e3424146ce335827b366624200000100000000260000000000125421a42a618b4b4aa66e0e683c9e0e75de7175b3eb9ebad79deaa140ee183cfb580a8b9d49d528a68edb2c1a1b25514e77fb0000010000000026000000000012542286238a917777a354e5db95621a8ae6b52b7342597add52da805fb4370f1bb473eb75e97a4219aee7908928cab78e1762000001000000002600000000001254238d28800b512702289839ee4066b45333813cb193ecd280999aceb955bc41dae8e0507e28964a29284c6645a3803dbd2600000100000000260000000000125424b4b2c903f5abeed19f5dea72ad28857dacff854ee1a0f12ba907432b577739b69dbb2ccb08e819fec694274e8f745d0b000001000000002600000000001254258e9f6a142bdf0d7d06425965ab334ba4ae06c649fcc31cc52e0561eadcc394f0c67a3f9961e2ae9261323639e8453a190000010000000026000000000012542692f9975759ba65cd4d0e63a94e913a8211ee349455dac2b5ccaffd6ee00eecd2c048c01fd37d663d3c83644e3616c15d00000100000000260000000000125427abaf9d1b9e6400a64b708c79fb0d2dbe918e7ff879ff06a31f446fde4f0357df099a690c77e3530033987cd29691c3fc0000010000000026000000000012542880edf81c57be4a43f268e3d1225e4916475c20f89d37798d02659ef3bac040196172cd9ed630165838fa0c24a713033400000100000000260000000000125429888ac2e9ca43d147f12e183edc30ac72e1870161a253371e18fd3b3f43169f1ee148f6aba4308d912b19d60d9d0a3e420000010000000026000000000012542a8b6dbfb35397e2ce05927f9c8eab1ef4179b80fa50b6667e24d8e143ac6553479c819c9022a0aabf1352dfcb66985a940000010000000026000000000012542bad4ec33fabbb4f5931c04b268ca7ad74c4589443dd89e0e49b028681f9f2e2eacfb18183ce148a8dfbdc9ff3cb73fe6d0000010000000026000000000012542cb92e1b3ab0f6da31817c5ddcdf2f374853e4c31eeeda834044efb02f7961c696521e6e48e2423937f5d40d3c4acf9b4a0000010000000026000000000012542d807fc1a925b4648d740d0c275075e8f3f2f24a28cfca56aa4993ee345862f0ea6b83ee3318300f5ec42d41006e779cdd0000010000000026000000000012542e8b93afdc10c3bb9f5c02008b41601a777b71594e8dbb23b2be42cab8a321575177b0b93d0a9a868401cc15b77f531adf0000010000000026000000000012542fb1d0d1bf0b7a6e13f495737516dd3c49037efa2e97beabb67be0e4838e7fbc86b4b416c0fcf485eed931e55aee1571c600000100000000260000000000125430857c3f55d0159e00dc5d0a9abc11b442c63f528fe1c4a3cbba0a8ff88bf70e8abf3a83f6332680078e2ccd0450d8cb7c00000100000000260000000000125431a8f014e13a3acc41b8989bbc713187638e054d2e0eb3a104c7b1fb2f958db9b6a831cec39c6e41b6725c3ed0b33decf900000100000000260000000000125432b0e79d3d7d25d1f6f9a912dbdd451d36b76ebc7149ac56811e62e082ffd0b40fe067decee9d3c6ac319e79e18a9103d600000100000000260000000000125433842092872417a46c893d71f78d6b04877d8686fbdcd896084a081a76c6866dd5b8bec07b4afc038257679f64dac0548700000100000000260000000000125434b58e1b30ca7d6c7ed8bebe9aee4a6f43aa91647fa803cc393788da55f4aedb0599c47d8e831395971733846c4132567a00000100000000260000000000125435b747466e6fbf93625f4f2561072dc7cdde65fc5fb31a74b07ca47ba4846b734cde2ac47259ad90ad024670ff0f5ed63500000100000000260000000000125436a1e8bb25cf7fd429f15ee5ef4e93731fe9e6efaa349daec5e8e6d92b63050616e54f3997d72d26fb6f84035ba780a3bc000001000000002600000000001254378cc1ac486df576c65bcadbe60f72e3e4d723896b31ae99621a985e677663aa13e2dddcf133f614415ad56713d0c8edc3000001000000002600000000001254388027e3c5f52f6b9916f863ccc92e43406eef45d1d63037951f945629e28b2f233840757f2bad642a2cd59151a7d7c25d00000100000000260000000000125439b0bb597e685498d8f33f096a22f2cd5f940b3db0e061a5a949f9acaeaa3f9df102efc085dbd5d68e43b5354acdec628f0000010000000026000000000012543aa65a60e2eaddcc5a7eeef21675f0510644c85e30ec3ef079b75eb988d468e5385b8a6ca6887d662ea29503ff5d8f79c00000010000000026000000000012543b98c7ae2e4ad41856807040348ca2ea8f0645971a07a09d5d4e890d8826d2ec1bfc9f6b16f157bfca960a0bc2dcf4d1190000010000000026000000000012543cb966e6718bf9a3e1d1c60d26751c68c869025ea782f69c5c233ca49e85de7c458c78cd0558c33ab26300238fdb5c19500000010000000026000000000012543da1bf66d3837a22eff43da051ff05364e593104ff862360b5947a3cd5478ac6ffd052df0d512e5f901a18ee87aab2edd50000010000000026000000000012543e89e4852346a2744b2ac1f45edde8ed8d24994384972fe8831fd6e18e3fdf20a61d614bd9e01621048d6e05a537f7bc630000010000000026000000000012543fb11ebd65a16c755d290909d1b0ed567bc2c5ecb9b66da4fc7565a2c8dacbebc0ba67c54336dcfe37c869aaf76609ce1d00000100000000260000000000125440ae7c5b5152240e5e15196bac030213fbabf4d5bd319630ccd6ce9199ee089dbe38d94120d51501cf78c4b5c9bdb0fa9f0000010000000026000000000012544194ec9629b3401bf404bffc15397cf79c9b68881789d18f8077cfa24d7d142999ea4c26c3b92c7900decb33bc26312ccd0000010000000026000000000012544288072b56333c6eee547145df28620868b062a6cae98412a0aae55142bae38fbf48724536323873ec172593095e1ee2ed00000100000000260000000000125443b6cacd593811770048f4e655138cf744bfe1e0603f7168f83cd66e3ff0a6d04963084da4e8751b11fb9764de6747b82d0000010000000026000000000012544494c510f254868cdfe5bf14688bb23f70eaf6a29273ec0961f12e9c1e849489f6d9e3902881b0ce3297e9d3dbe7c60bbc0000010000000026000000000012544580b9451f159feb7d55035ff60dfa363db55968641505f25e39a6e429387f6282fd6674aec570cd3fb661fb6d9c7300a700000100000000260000000000125446a89f681f74b6e94b4117b9cc84e036aff81dcbb69498901d1a806655090a303315d16dbcbde7ce1569d09804b0c3918100000100000000260000000000125447a741f5c5e26b348b7a3ce164a7a57e665efeb9bf385f24ac5644e7dc0442b2b90309a28d4c1205bf3888271571679562000001000000002600000000001254488ef19ade7caf3d38a505489b01d8f44835d0ea9626e91dbf58498221f8e9f15c932de1751f817e0ac422c7f19045b2a70000010000000026000000000012544980eeeb731a5acdbd44bd847e2472031f9ce9b4cae8da69290ef9989c5f66dcf6b3c167d99369f681753df44461a7d9e90000010000000026000000000012544ab343122f001c8f83e0c1c644b0762e815dd93b15b7bde17a17a6bed23aba1436510b7bfb3f090d0ad32b83f2e1552c6f0000010000000026000000000012544b91a20f52e7f3f873518388f8f3f0da4a0ff20c0655ae86d380f62d890de61a566250eed392215bd97fca310a0cda0ba40000010000000026000000000012549797c26c80b1dfc5495cca4acdf5c1e7f1a24c646395c29e1fba6f0aa0811a0d66d11578a995a180353bb8b569925b7b2600000100000000260000000000125498b3b465a5573ed57483ce3d6d9ee96c828cd8c582355f5144fffef24710f1a4e1ba0c813adf74d914a0969ef973a0ed5a0000010000000026000000000012549992316c48e9c8170cd2f3c82a9e6acf8b26e8dc06f13730598c87185905fdaa4af1d0067d483282d1c6237d885db654c00000010000000026000000000012549a88651d98dc7c0d6349c87793ab4763e39c681f095ebeb2a5c589e0a0dff6dd14f93376dacdabda173d24b49f361e9b830000010000000026000000000012549b85ad2e2fd8a4e4098c6e5db626034b1b4f204096510119a28e4294fead35573fc4384c5581789be494024cfdd7279ed40000010000000026000000000012549c92bad5d2256c09cebe8b147432a8ef381f09138b12fa0a0f77806e3f8eda715878804746c5215eb3bd8a45929c3b8fc10000010000000026000000000012549db46aa3ca6b7aa40a7c2f4c29458eab81ca8efef99b83544ddb89007b97af474ea8907bce5a71af9936a53a975cb091500000010000000026000000000012549e8282c26c2962f9593cf85ecce6ce464b8a07d66d5f1881ef1089f207b036f731ecbc1484001bc47e6428667e29ec40d30000010000000026000000000012549f97dff96873c94ecb8bd747be38ffcb7ccb349425331e3a6b6f8bf7cdf6b7c2e3c6eba37a2f7ae97fe26820a4f6d25d85000001000000002600000000001254a0a6a8a5afc37a329c97446e5649fa149a7b2757ef72a4bae3e628b162477727a836ee380ebbd131f167cd533cd7a75ca4000001000000002600000000001254a1a4367605b0ef4503951b46f4054c4708561cbec0392ade4e54ae850b918b18092ba929d9437a342a897dc7f45066d6a4000001000000002600000000001254a2b0d87cecb4f4e95b86f2736a581db3b2f9db669644dd3eef1f5b740982d7c4d3266ad837b9d62d1ec6c85ef2bb33ca70000001000000002600000000001254a380b19eea655ee3d2cf8ed6d793f5296c9ee3deb73a5e3f85eed9a3f832ce6a3bef11c691a876dd16798c6def74d2da65000001000000002600000000001254a4a581656447de1e7ced921ded1c8a873328b1e4ce1225a770d711453eb144a1ebf1848ac063f597429594513df4d57d17000001000000002600000000001254a59721b2273b07dcc46a6581e04f27e425c58a50462b15149c0903a526e01c86fd4b4c74aca952a8b871887d93b00e4bf7000001000000002600000000001254a690e98b9817009213f8d15f4455952f0991574df70f2781302d9592b8c6714451213151affe541ee35ae502b20e2311bd000001000000002600000000001254a7b46a6095180acbc982422857afe3eb1e57d13e6eaa9da9bdc3d37f5913a8a2803f33e18ef2bf071bf88d4136037d0a77000001000000002600000000001254a8a500b239769c9e23115d131d90c6cb2983a6b126a7a8f1296dff8984a8ae6072b679b637e0e6fdf89d1d7cb36a12a51a000001000000002600000000001254a98c5915361bae2c75d7b2a4db5752386e4a5d54ce92294b0af5044f4ed203f0846e8fde34e4b77c789220aa4e4aa460d1000001000000002600000000001254aab8744d02b427c98e2ccbd2a51c688e9c3038ab1ffd0bc6043b1cc29ef8f04213e6aa4d92ff6071ffed8334b2a534bfbb000001000000002600000000001254ab8d5e2ee30af57fb3e9c4828907a9dd50d93a93154f988b6f9ad5bc3909344833c322a9517d56cc6b585e10696fadf98d000001000000002600000000001254ac859965580b0c32c4c6cf936c6ba5e2754d9e4527e7e76ace0b142626e63fb4e4a59483ad00799005eb5c6865b45cd4b2000001000000002600000000001254ad966e2bfecbc7a44a3b297140d4f5eef2e0b7a2ae0908e25894acb7e0722d26412e4a67c86864ac164092ea719d16fc04000001000000002600000000001254aea32b1cba7d40d57d21028b3b2df3dce52ab696935dc889663695787ecb4846a11dc26049997f1769cbcd74cab86dfc2f000001000000002600000000001254af8725a974c6f5d7b7b9e5f09c2b539d61b9920aaa6a0e9dcedfe3a9c9fc23fa08bb39e267b5ac769bb1f2ac8f27956979000001000000002600000000001254b0a1bbd29f5931e75a3e6a74d2fbd9c661582780c27da20112c236e4b167b58e85b1431b698a90e6a3a9152eb2949911a1000001000000002600000000001254b1b354ba8802d070d55a34d67105a41931fbb9ef6b893c92ad5cfa051967e5a2618b072ce34cf2aa4316a81a953dfff7c0000001000000002600000000001254b29187d20881e6cc3dd3fdadf014f2ed4c29f55736519bc6c400b907a2a6915256c8c0ca29d042cdf14b7589170e563dcd000001000000002600000000001254b3ab08733b8437e052113decacff8fd0c09a0f84ec56c8b67244a14e89e577b5f7c18bc6ce225131081bcdd29583657c53000001000000002600000000001254b4956c4b15abb52637959ca3eb6f826b782681009c8dd33bd3f6eeffa69b7d9291ca68eb7751cb56ba8f8c88945ed7bc92000001000000002600000000001254b5a6963ab073a0291e02ae49115ede0aa187dc22f2370c77332bc01efb7bed12a5ea40e44daa3d87df55c097fd7a2011b0000001000000002600000000001254b69441c1ee1774aed9485c3b977bb86dce05fe4f96167100db25d435986964a57f41f72511ab401d56a8a3e9a93a7fb29f000001000000002600000000001254b7a2089e1261401ff3b0f3a74ff09a66eae8c1aeff89e7b44129e205217e31b76975e32f73e092651f8fb04cc93164ce21000001000000002600000000001254b8923690cc080f16deab4e059dd8e8c4a6fce954b138d333acf5ad8f0dc157dad22d869ac04fa02c7564bf4a82d0d783a2000001000000002600000000001254b9b980448431b96f849a2283b4ae73342a97f07f9b83f109b4b4bfc207950346b5870ecc2485de712c99c3f662c67b715a000001000000002600000000001254baa9d7507b8161b41db1b946dcfcd7c9bba04739b6d175191cf431ee880b75f238f28760ee076dcebf5c410f87d19b2120000001000000002600000000001254bb8d40d98f2cc491e09531e32d9f7d50ff7073a651593a54d1a4ac91c18d13a932fd3e4cc1b12387179844484d8901c725000001000000002600000000001254bca75f4c2d85dc9b72a7fef4b6c4b90b52f1dabd453092b7c4891078a8348d807415709be9a25b164d06d90c9b1c90d97d000001000000002600000000001254bd82e6908ce6d783413d41c572f9f44140be8eebf14562c3e3e800665f9815839dc0b890ec257f7f5f422990dff5c2d124000001000000002600000000001254beb33d556c842ede1bf2ed96c44a68fe85a85a1056af629864c3f0717ae186bfe7b7faf3ac92e16c42069566f0d6390d4f000001000000002600000000001254bf89d6a64ef94fb4903342abe24c096b429df4e1eb3d3ae9dbe0c848a5f3bcd2bda86c8e2fbfd5a0cbd4c297ceabfcd0d3000001000000002600000000001254c0ae78c0124cd6a0406fae222f6c5a8115b5d5b15a78cf64f89460c79cdb16d36e7b2f019e2b581646be225eddb8d4819b000001000000002600000000001254c1932179f1ceb853487122bf3696cfffea2a61fd33768fe6710e32a03886181481ba1acd4ffa2402e3a7e6c3767813cf3c000001000000002600000000001254c291281814932f8125a67f796291dd6a2d39a3b1be7265da6a766a0b44074eaf4aa3952116c0780dbeb55127ab85d6fbc7000001000000002600000000001254c385ea846bb74d508b03a81786e54952c0229eca487946d552334d114e7be35da09b759660f879d0ae575914dbfcb7713b000001000000002600000000001254c49896638a1c341d7fa823aed1c76aa59204a56f017c232cc082d783a0fcdce190314b86ee8590793da807c3c8fdab67dd000001000000002600000000001254c5ade628b8fe85f0a283f296663af388cc1c7ebe79f4bb0625c9ca4837bed53dca9be120c61a0778cd9332d425f2a82bfd000001000000002600000000001254c6b3406a1787fbc1104f14942e42bc2193539bc6f2050dfd1c0570293dd5c0776475392e69ef0a39bea064d632cfbed8b9000001000000002600000000001254c7811b1bfaf8232ecc9fdd6ae567f9eca36091de63a16d3c96d7c6e0e30b3f018354bf5dd1c778f80c59564b9f4091509a000001000000002600000000001254c884f00302c907d3380bbcdd5e94b671a696343f73cede232c724c25eec235c6ad9eed2b2b851cef0154aa010e358ccc77000001000000002600000000001254c9b29e7bf5d415f32570854280d263338052f010554b7da8f655053dc0a533cf56c4249766bc18cc7ddf67750ad611e5fa000001000000002600000000001254ca9230d23e9e516d950be5ade42ae270021062628cea83b6a8a5207e5e6fe36af320545257306b968556d9f9a4648a2f9e000001000000002600000000001254cb823d374bb143955ae8b40a5a7e15037965b5a466530eeb53c4684e36e8c73491408150b0cebcec3f12c4337b0ede5061000001000000002600000000001254ccb591509efb38e15980301e046fe0f98bb8d8dfdf0bfba326d3cc61ae04f8dec453eb13f39cba1d4d9466a7661d722c82000001000000002600000000001254cd80f5a35fc0c2dfe3888d328fcd0dc349f9bfdae2ece291812132ed3c57b5898a60a3795c13fa4b648448875026dee862000001000000002600000000001254ceb438c7ebf17fdc41c1e3f00ce0dab075924b7f9f0efae2fe85602d38176cf6bcf2cc73ee5e6e1e89251983fc908573cc000001000000002600000000001254cfad3d3cb8ba2561ecc0ac3414ce9d862788667d702768d287f093f5c8cc0e422d86d8d346670fa07abc85154c5e2c98c4000001000000002600000000001254d0949ebd3730bebda125848396e2103559f309913eb27581ef0541ecdd9bc68566ff9fe8e0d50ff84e4ceac3f0a7b98703000001000000002600000000001254d1ad894bce23f6493806075efba7c6f24454d0c5f02811575740f34af62640b4ad80192d853e55509e20b2927f60e707ea000001000000002600000000001254d2904f4c2612c6c6a3595a91670da9315175fee399f05938448077bb66fa2fd36af29cd6e4bb78b2e12353e71e0dd2aa11000001000000002600000000001254d3b2d1b45c6798235c07635d0edcb25a53f171a5ee4f48ff84dd0081446b45e8ba3cf25d948a113ad1626dbb6ad556b8e6000001000000002600000000001254d48a7056f33af2023db5ca9b32c5df15434a434fda24249c81ce94c2c9e64c51231fe23f3a3a601c53bf11475feb42c37f000001000000002600000000001254d5ad3f99e9a4114acd1373101d507ba750b1cce68cef7da76de250c58844cfb2aabbaed793b336651249024f49bc14b7aa000001000000002600000000001254d6986fb11d676e44cdb19c33c3cfcdae7635c149a7c60c5d2ac6b450c758f3b2ffe1eb7225af3bcf324fca1a23528502c0000001000000002600000000001254d7a8cdb8e91a9a1eba3a717155493fc430074739a654b7cd5809df35c75cb908e92bfc9eb9185312f9e0e007a8bfa50d8b000001000000002600000000001254d8aa0b01fee37ebaff3f74ac390a96e0b97296573b4035bbb066c6a5fd10a3e1efbf5ebf08f5366e07f12ffc76a179fa7a000001000000002600000000001254d9a10aba446fd604df9e674dad1041aca21b7287ea44e551406861897000e36d5f1cb383707d6fff23eacdc2bdc5bb35f9000001000000002600000000001254daa3e08ab89eb7b2023a4f76d05a4399f1c30866f2d37e68072a10355073bdc4c2ea06060db75796f8cc5d8555e0d4ec5b000001000000002600000000001254db882b9ca39ff598093d6fc3439dcbf227eda5d9271fb8b9a6eebd5e11138b96d6be04b880165172237df0f85c4b7250f4000001000000002600000000001254dcb6ab88d8c4e0c4bfd074403e563d153abcf569084bf5943be821c688a8230ae9c347b05b56b46a628edb3cd1d3ec88a0000001000000002600000000001254ddaba75bd077888cd393b0ca76c386bf2a336d4dec78f1460962ff8bf8c71a65d47dc159df76971b873f863899addd3fa0000001000000002600000000001254de82a8b8cf9476070a8418905bf69f92b8822659ddaf2953cc3e99dcc7262149a2e2f18d3ad365ae4f8a5c7d61353e35d7000001000000002600000000001254dfa8829de1dec9e5565109bae2d84d58165ad6a212d1605d6a3e2535ec16aa2eeeae7bdc34b2feb49f1de5e2566dfe59c7000001000000002600000000001254e0b0ed9c366eef1c171970a71f42cfa808398affda2071d5b90ed6b78511e0384cbb73ce26ef4c3eff2b0fb88dd04358a3000001000000002600000000001254e18154a70a36c201ee51c05b60b26a86eb64c92f43b049d4979b8aa91e7478e775eec450f249a5ba77e05e6449d66011c800000100000000260000000000125540b175b9925400c12e09d0477ac4c035f6087406e83b0af0d908adc7a269b7b15a534167cd43a61af058d0fd0bb122faef00000100000000260000000000125541981f0e27fd0ef2bb405adad6913749d570c1471a69c48fde48d1f32fc83746afefe4b950fb34ce857599e60cd77dc6720000010000000026000000000012554284cdb164d8c65da6f3174fd34fe496fc0a619724b1de69829a7a18da8ff42545a80b6e6823bfbfc8ea6a0d99d501ca7b00000100000000260000000000125543b430ff5b360a924cc7bcb640b85396e9c70396135ae0ecca898aedd84f04f32ead016af37e9efda320d6fdec31f6bd4400000100000000260000000000125544992e8141c1caddf8ad7a0cf4421ae88f5cdcd8e10ccf0a1d1619dac01f73c74594b6fa3913005a04f9c71f04ec446d59000001000000002600000000001255458bf22ac07cda73b4a2e3d7d7531914fb27b5d4610c40619f214ea9453563336af6ec8252d7f02ed698594448b593d47500000100000000260000000000125546999a96c117f22be52fd44ff082f31e5b72c0e372fbc628ad0d8844088c6751038e9dab15cffbc7df8bdd620171c2a5f7000001000000002600000000001255478ab270c892fbaf33b09913c4d06db0025a1844af861a1d04e3c8c4c7a5ecb518c4b6992d9966f76294c2fd6ee6bb8d3800000100000000260000000000125548b8b10942b8f142dfd4942e0680344e036e54a5efb8131d0ccb04a716ed2d50aa91349a15ea3441783852a97d8333122400000100000000260000000000125549a39d40d1173c9a70533fe1c10a56e2328ad0545553c35f931ecd4f353ef8e53a9be595cfc8d4d122365bd16eadc1f14c0000010000000026000000000012554a82248cb08b59fd5e44f34114b24d0827236a7a9475218db1defbee8f12c6f55998421b2e3d4bbc4ce034f66c091c0d600000010000000026000000000012554ba4a54c24651e7655e2aecff5ad75eac7951e65b1921e279e7b884ed476bf5d78139c50f0497ac6daedd7dcc4a231ab230000010000000026000000000012554ca1d348aa4407a1116a0eeb3f8637f63b7c1fa1a63a4254a15e18d9959e9f5c982d6b8a0af1dac4eae2e4ffb352fd81550000010000000026000000000012554da19dc6815b94c410e29a4f326a5e82c8ec8186db8ab808c084c41ca1ce36d1d525fe5ba21fa1ed30294645b36b4503250000010000000026000000000012554e888d16804900f36ec5674fde61e0c800d4ebb65144734e6b5b884f18f0cbc8e88b21063acf467558fe623eed0a19a63e0000010000000026000000000012554f8c0ef849ee89e2e63f1323f665849112c2973868a2e8d50cd2cb0c12daa27aba319fdb3e3206d8a7ba88a2f82975d30e00000100000000260000000000125550ad29ee5a62035ec3eaad283ab84562a3a7c47b3c5d82a601e89b077d2f15db80204f406b0e066de1d636c9a1f545bcff00000100000000260000000000125551b678d6b56a8d7f16818d414b54f0f4227d26b0bb3dc02accd0ca13fec6da1b8ae1f53847da4f59e0adc9ec200389dee800000100000000260000000000125552b636ca9e4d64fee334c601ab74a0a902fdb335a6a302849375f2e7a7293ee5f507e36bdf5e5ba869a0cb896c6ab8f6f8000001000000002600000000001255538c16f49d7860cc4d9aefe1328c85e4a6ecca85730e766b4b2789849a9c1f0975cc078feab24cb808b787729aa57de45b00000100000000260000000000125554ae55731fd49dc5ff63c5178d078ebfcf8c43f35ebf455bb12cc50a23b16f698a04c51dbd2949d1669144217bf873dafd00000100000000260000000000125555a7b4c0f2c1536d029cd1c7fe75c54552132b49a5766952cad8056102732545d06a6f00b4a35dc40d86d3594f14b96d6a00000100000000260000000000125556b085660ce93695b61207820cd79ed8e1d84ca42ce73a5222987edd0f8eab96a6190b9648df06801cf8456fe289cb6da100000100000000260000000000125557a61049476631b1af773f74d51ac6d0fa877c1dea5a345c8516f78a143474360d38582ac4bd33e445ccc3a21cdc26e50300000100000000260000000000125558826e55ad5a66cf52eaf2bd23511f92efa848ed265bee86008eb27ecbc79c17077958e937585c18fe4b016d50d3b57b38000001000000002600000000001255598072c1ebb1d34e88577353fbc0bc92a515bbe02d88e29457a8732fe133ceab3f8cebbe7bc4da0f71a4751ecc13d5786e0000010000000026000000000012555ab81bab4d8aa4ac70410d4115149ce250ea701398fcfa7aac313df685f64a167e647ec9b938cc83981019bc6878d6372e0000010000000026000000000012555ba0f4602056e0007e6e9fcf57c108bb78e80de9dbea4c8e10b039db2a9d2c88deef2b0336a2b7d5792f1c6d6e6241b6460000010000000026000000000012555c933067cc494028483152bed85636acfe5cbb61d9dc1885b664f63bcdc1b65fa69c77a7e0fd38d55163b00680d53ed5330000010000000026000000000012555da31f45656a6456808328071e1e17ffcbb67cbb7b3b89b849eb3115c49777751b87619799b32a36689ae2da7a82e60e4f0000010000000026000000000012555e8e933f32fa8f42f7bf4cc6db65051ce41a3f0ec1bbfc1909e4b09c04f6ed5f7cd702fa9f66499d8884b90a1b542f1b0e0000010000000026000000000012555f8e865e06503ace9b02fd8ec0e31bfc474dedf2a40c4e2abcba860969727527d61f999890d5876b235a614ce402ddfa5200000100000000260000000000125560b27388608d49c6e861594f161c9fa0e34b45b9598d8638aa219525c40da12112b3165ac015b3ba40158ea9ec455b3820000001000000002600000000001255618dbe1e0b181b60ad28fc442bdbcf300791d3b90d25582cfee8794c229df4c9f90d5f0da497b3fe70b8b6771953f7a17f00000100000000260000000000125562b1f6a84a83b36277a3be4fe9587478cb776be3063ddf8f7648180e18785c91a8628ebd361d105576d1e876777eb26eb900000100000000260000000000125563ad47baf3047d4ca6508580ab91c72f1132e238854ac1b0b54b2bd825a3543e332029716a1e0c4be41bd516522f3daded00000100000000260000000000125564a41e785d279956cb2bd5b559c9c2dcedf143667f2662579846241c44cafc8349a623f4bd5d6bcd49182ed9967fc9c03200000100000000260000000000125565976bd8387c917640a2b25ea14f158ce1b29985105dbf0fa28a10439f13350a27fc5073b52685abaab570250d9ff5e36600000100000000260000000000125566823781dbb530c95f606f019d5410f9528618b222743ef513ec009f45a1f507d80fabfd18ae6c828342eafb3bd3eeca8c00000100000000260000000000125567a86ad94611d466e10397efbb5fd2fdf93aa64f6dbdb14178e5f5f45b3d8669ee2a39727f787ed08615653bc78b070e88000001000000002600000000001255688698f441efd1690a479523fe451961e6f4cd4d741a0cb54caae54ad692184cb005eaebc3b877fd6d209de879034edeac000001000000002600000000001255698a854c9c5a1b5b49d713c7496bfe7dcabf031f30254e0b1f7f76af8c3e6a76b196c82ab84318e07c7d0e7ab4f78a5ed30000010000000026000000000012556ab63b0502b1839f7a65852e7da06447c2d848762dd07b236723051eb2ffac7108676d93b10bb704378824d6f1aac6b1b30000010000000026000000000012556bb96a65d1372aad67d5ca180c22146899923717becdc7a37b3882fff232d1d9c7e35d66b1d0c3f8e2dbbe26c13fe33e020000010000000026000000000012556c9323f30a7068a53d4d97c11abae057651af8aa0e9673fd35b0087376d8e4552429ed4859a5542c9ef9bf77cbf34d62f20000010000000026000000000012556d83115ea25c2f317b12a995ccc21c2e8b967fe98d23e8a454b2a5d28d3211a3d26f8a7550a81a18f0d5ab95bae60dcfaf0000010000000026000000000012556eae5f08788f3b2db98fb40796a333c764d08198ffcbe6da80279bc9de09e94775e16f707f6d0164fc82d47998aae8e5940000010000000026000000000012556f93be88b25b8c47cb1e532bb15affc5d3258e8d76566a8cea7294b84f34e7426a2d88985e3dd25dd3b576bfdb1a7b758800000100000000260000000000125570b4875ebb577c6a8eb06557449b71dc3029d75410f412ce60bd36a4e256d89c3e6bdec07feb0ffa923bbf81d6670fb44f0000010000000026000000000012557198fe1259a55c47a3547ab97c41614628b56a9909cde9649e75a6469e000638903c6406c7c9002f700cabb8e55759cee100000100000000260000000000125572a7fcfb1d8d585e8602aa7c7fda9b1a87d1da3bb2c775fd2cbe403e2e57f0669139a2cdc905ed278eeb64ffe932de06760000010000000026000000000012557395b84c560905cfa55b4772b4d28d5312791eae150b6aca556c937350f51e1bbe69bc3227b03b61911da656870e381e3c0000010000000026000000000012557491a93e1d22e054b0a261659cc9195429f8a06c300fa6acc0a5229eec0de949bf6c046d6b7bba532e277217938398fa760000010000000026000000000012557591c6eb9a960920350e8c3e7b3364506b133f0a3ff6b17c6a7da081fb9daa33491c47556de2ae3b6ab0c1cd00a5b74f9400000100000000260000000000125576972f92649e21c1aecc22ca755562c5541248dd615df0a34c49646aa55706858fc431e81c80124e440b93fce2115fa22000000100000000260000000000125577af6922c8e29983918ff2f63867bb48260fe43de150d5cd8a82cf0fe9fb3b84376ee84f9d98e3756451a9f93e4d81921200000100000000260000000000125578a7eb567a0003c26dbf771ce042c9a25bf3eda92a814c660bafd5ed1de7777e287276920ecea86e6c49f894598c9374b3000001000000002600000000001255dd801d9f7a7891cabd842a5d8e62dfcb2b666e60d5f43e95d6dfe37e74dccb50b5b0eed4c39ecaad6e46eafe6433ed1f4b000001000000002600000000001255dea62a3e11165c2a863fe1514da709ea197461870d2de3ae506b1b617a4a4b4c89cd17583da33d09342dbee92096dcb858000001000000002600000000001255dfacfb9dcda5bf7d38a090e2e7fff691c71f40fa61c99e9e71a60eef058df981518362ed9e0c5cec3329b02188a6b54fc3000001000000002600000000001255e094c328da8e7a79343b46c83dc8cd12e00372de52062eaa2ab85cffe3e0ed8044d3b16d97ce2ffd827ec6c2054c425aac000001000000002600000000001255e18548104f32b95a814fa691029f48e3f26f2b97b589a100e7ac3c4aa6a79ac601a1c5828183260e9641ca188976b8f14a000001000000002600000000001255e2b2e654d36e3131ffebebcfe20827030eaf6ca3f783e6b6127950d0a1f949dabc1f027778e39052e276593dd4165a06d0000001000000002600000000001255e38379f751ac1ccaf0049c6ec88b77bed0d98e22a750d99cea7e3a6a09ffc723b9f79835327487244aa09f8c2ecf14a4f1000001000000002600000000001255e48c5a5b353810c9df1ec4d97a34e63c4ee9c538a43935e5789ba5ebb3f13437b49ba913deb3d04e375311d12f857b89d5000001000000002600000000001255e5b29ff9edb404193b89373c7c5597094eafd322027193e605ce17ae07252d562a7db0ef8611df7167aa7db35fcaefb2fb000001000000002600000000001255e6a5ab2ddde5ed309c2a8abe9b6709cf352dd97df1af0677c41e99accf3d8c60e43f80296a0df982d9362f62f72af110b1000001000000002600000000001255e7b76ca2526a828cf0a2276873385058d3f5fa61a69b7560bb6059641887cd5006378c806d1287f5bc02dcfabe274fea1d000001000000002600000000001255e8b61a27d9725cbea16425336614477029ca69f90e8954f7eca776fc29e62ff616b320570bc6ba042487bb13e84ab00064000001000000002600000000001255e98b500e94c7adf791c55d95d0351440c1488393326e75c9948bd05370f1c8c01276080e8bb36ec9f7e9d615ab0ef20176000001000000002600000000001255ea87406b84d5bb0b54d70956e6029a205f2b717f0269eaf0f2887f4bb9d5d6217ec0233a9901f2ecaa444542a287330eab000001000000002600000000001255eb87ef4341f2cd97a3d1dde3472a9b85b1498940655253445f545dd7462d31948150ad13622c46bf51725f0aa8f96012a3000001000000002600000000001255ec87679a8e4949a1728e02d78f7e40b557da365ebc39cf53f179c327fbc8a86d3dac718aac41e6f9652af09a72216c8715000001000000002600000000001255ed84943b7031e488e63c3444f686e6d1477d2981b7d88658a8c6c551808ccc69ceaa3d568434a23025dfeeb5bbf9c1760f000001000000002600000000001255eeb49306b0ea528daab96d6f6510ded47380c2bb66b3d911cb8bfa52c422f0a8293d940e08c177763be3e122e2777037cb000001000000002600000000001255ef995b2bc670268720f822f8e16844e8c414c082786363858270475ed8c11ec985586ad0075be987e08ef9fdb158b1b3c5000001000000002600000000001255f0a97bd89703cf368dbb03eac560a24938d42c4440ee5ff0a3bb740668a7cf5954cfb3a59ba1fcf75f47ba5af1d93df7ef000001000000002600000000001255f18a4d3f3edcfebe930b60bf8b8df3c805d26b1b4cff4a2c7dfaf82b35d88c5eb60502ba33a355415a217235049d1ca0fc000001000000002600000000001255f2b01ce0f0c6f913ebf11c34284a5fe6ddc82329feb8acef1d7ff257cd0351d3a6f82b84a603b322b7a1a96ffcbc10c0b4000001000000002600000000001255f3b0d0f61a2e97b68d2549c607223b82976a9596292d4fe76cf0589ff5cf0d98ef3d3a7ee00370231e57086b6a7fe28fe7000001000000002600000000001255f4804fe168873cbe598054887b7afd9c7d58a9a830ab756cca21b493ea5ef5185373841f65b1792f4c2be16bfc43ee1213000001000000002600000000001255f5ac8eb57823abb9ef87dbe345b403b1a40921aae8ed7b7325c69fa7016c737919460d1acf993c666321a50bd09bb96ccb000001000000002600000000001255f68554024883e9d4a5f30a1136cdbca731b70fdfd82242ade21f167639cb90705a90eb527667aa3fd23a3c613c124025c3000001000000002600000000001255f78bc517f49e682941ab3a34f4b92242cfc84fab498d3f2f01f536259241578e0ae07bf8e195778fe731f42c0fe684ad6c000001000000002600000000001255f8aee3b9fa11b7988b9e10b6cd67713ad3d70b54bffb6106ffee46bcbb8eff3fc5f9081653752d7d23ef0e67de6d027ac2000001000000002600000000001255f98982ee033546513dd4c6de472abbf98c0d1143bc9070a805a70349ed45fce6f42eaefbbf3b52723fb8f70356a503e007000001000000002600000000001255fab1b6b5adaafd8823d9b41e4bfd622f56be076a107435dcb22663e7a1f8994f84b46d8a87d9d03e8943fc937d8c84a2d7000001000000002600000000001255fb8590e0fe7a7ac0da01eda0d02db5550e8fd68deb07b71246a1f29c4e48a1bbd9b46feccb253a9660155cbb1182e2a7c3000001000000002600000000001255fcb1006634aa54cc5d79470940158f6c049c2ce42f4d32f05740e57b0218e7e360dadc16060ea783899f65fcbb8f080254000001000000002600000000001255fdb52088efdbea72224fafc5fb53c6aa4f19fb1f280d2a42b1ec8c90e8fd98f096ea00acf7ddd6fa5261307ee97f63a362000001000000002600000000001255fea2cf2aeb067c2afd40114af34e843e79634ad56ba34b9c3987f15f01f9016b3b2f0f39885a2509b75eb1ee9c64ca11ae000001000000002600000000001255ffaca7c4e5f59a0277ccff71a8113b9f4242a841d9fd0a605d42f3056b843f3dcd2ad629c50e28ce62d536973ff2d4d65600000100000000260000000000125600b6f7b901be59959c3d62927ea63b25a2f7e65888f07d49979b3cf28bee6df2b5304e0c583fb67f943f86fb7cd8968e68000001000000002600000000001256018f7350d83bb319c82e183fa76d52c366d63d6073b33f4ab851c4db2c2320e615d6f934e51984fcced7a8fc918898a4c700000100000000260000000000125602b9966e9646aa9abb3a5f8c074acbbc11331530656d5bea3b9b38c3460095f4cb3ce01cbb8ac807365bf3e035b74f290300000100000000260000000000125603a62a82a98de514813f2561768da7d3137ada9c693574b4a598213019eb72ea3599e78eeafdc21f50651d39487277e121000001000000002600000000001256048057c89cecc854c9d4e0dbe1b67d6f2caad9222c4fa0924280464a57c6c9839e2b2e2ba881e88c0c4406098ea9350369000001000000002600000000001256058cda74c4c5d020897b8a78ad1f40748217629a9735280e3d2a0e12d7c7443a40cc7d7e0d0fbd302830fde6bf08101b8d000001000000002600000000001256068265f6790e40ba1b868eb19b3d81fa9d5a3752ec0eb01ffe1fa1ff390322ac74eacadada4ac2b44f018c31f0b2c9e3900000010000000026000000000012560799be8c19533bd6b41e74ad8708472d697b054bfb053699401bcb2cd34cc3be985798771580c0947f9e0e7591d8eb850000000100000000260000000000125608a033aa2e214ae21c5349750af2ebb2a4f0830651b1934e1de4fac0d4c7c0fbea7d48fce52eea46b7c4feb508326f4d6a00000100000000260000000000125609996c85d22cae35359fc38f1314dd06242c483884a9747fbdd605520cd11801ab0f7b80be71515d18b3614dcf0724c1590000010000000026000000000012560a910dabe6dc6be40a69571d1bca6e299c543fe22273994253767757c6be84aa4b56907c068e20b3bf0b43f316c4383f3c0000010000000026000000000012560ba1b911ed430e142b4056bdf23db005237c1ec5648a29eceb98766cc37945b38822719d14b76b7cbdae48118a9aac679e0000010000000026000000000012560c846e1a9116ca87a25d677be95a6b43a6422c31cd4ef61c79b3983abd2ccc679e324a8f74f0a5de0c004e8eaaf03401d70000010000000026000000000012560d843445a4c36ccca5c00b48fc9c5bd0f1ab98253edace64e75f62dbf476186dc6f155dc108569d6ae7d0a250cb1ba8afb0000010000000026000000000012560e95354296bf0c6081368c8ec7b2002f91788714bee69472685b6a04dd60e93fb9d5979df256e82194c6ab3aba278ba0e500000100000000260000000000125665b7b539daaa76bf018ac7976e4cc1775f56950a52b6a226535a8ee43e07b4bb874402eea6a2a10e3786c4bcea820f131f00000100000000260000000000125666a2f0f1c765c69397c78b9d95bed59560ccaaff031bde9d82e4f54459b9b54954ab4618fe046137bd2386505b6de5f56300000100000000260000000000125667a7b59099829a83766f27e448b3ce995cb86e4190896026ee650d8bcd5c441c0392db0d89f1d599b3362e906a54a6507e00000100000000260000000000125668954decd501ccc57f31942a5321343e9e6e368357df42916cefa4e12adcbef87d87dd62b9a20e3439d77f5ec039fe915000000100000000260000000000125669b6e2296b4b40a0889165d69f965014901e373533a85dbf22df443345b98e3cf09536420461f41eaba9a53443de41b7d50000010000000026000000000012566aa3959564677163d985e2c289bf9d9c3738120c14fa7ac261c913f74ff4c71c13234b43008d35b231ac3396e1ff59d45d0000010000000026000000000012566b98d2b52f33a5104dd3d85ed27a4e34bf7ef075ba9ef7f20e8413341217be06b3823a9310aac47b824f97468ace61bfef0000010000000026000000000012566c8a93976baefd49aa28ad2219517a69fa494db5b7a45de810ce8e542cd80ca586db6e1880bd8a4524dab9ae36987a54620000010000000026000000000012566db700c8a8b5c39416601fc7a05a6928895ac169a746af9aed5731a4d6db25cc58faf0f136860bfa447c26431dbb80f4aa0000010000000026000000000012566eb03cd3c511601fe5f9a83e71e532f101f34922d8547bb51582b7238ad7074eb4796d927870da03a905d911f229d02e160000010000000026000000000012566f8b04adeffd67742fcf5523f5f1814d1da833a3c674e2ae074e5e2207aa90ea27f4abf8ba0820c67c445baacf7dfe1a7a0000010000000026000000000012567081f0338938bd97a3d7ef498f1a551206a5d0db2624993c73b8b89c5731710b184793e84af78134a826ed8c80eb0aad6900000100000000260000000000125671836785ba600a734cae0dba3bbf1ba93bb93430050e84f34b9487c268e56c3b66f076dcb2bfbcec1dcb732eac28ea4e2e000001000000002600000000001256728488d9ac07eef29bfac65ce8757495b4325381b965ab3b3422b0502d009c4cdc047430715bb75f2ea6598a7181072b07000001000000002600000000001256739874c620c18210f32563d08bea9384d87ae3ae05f92157da2995dc5e5cc73c874f75385ed0041118d4fde06abb3955fc00000100000000260000000000125674a1e9e12650ad23357238687bf872f4c7f795c4159e64337d170da38c2a5aafc465434ad69795c565d7e065958804f98600000100000000260000000000125675aca0d5457bdc9e13beb2efdaa09c28206dd5a64a7ccf56da80b7a31158aa638c14925ad04e4abd4b44f98023f7eaaeaf00000100000000260000000000125676a5f8a9f091c21ba8c123e23f174e8dc865d09418b430b6bd2226a959e9579ff27caf94f05d7c9662322f01a28659437100000100000000260000000000125677a7fc380e5cdc74cbdbe8da4278062c2cd5da4181593fe67336d0d51949a6b5b7eb704c35d46b450c8e22d53ef7cb705c000001000000002600000000001256788e2b1d3a780f4e79d7738ab207bab8ec5fa7daa70bf1d276a9e61aca82d5a41d50f78f20735408d9926a4bf0e1b0948a000001000000002600000000001256798230c21edbff826c415badc1e1b03d0e3d3a3b276b9dfc796f6de8c70fb69707e8e999c1e666c3014f07d820db065ee90000010000000026000000000012567ab6f7f3744d72ecfde719ed3517716910c0109ec4aa705fbb650b0e6bbab15a2137e80e3838b9f9a5a6626ae0c6275f1a0000010000000026000000000012567ba8ecea746f2e71dc854132125554e0acfb2bc5900c5dab3ff94c0286a353ca98a343d9aeff989829d3af3294a6f57b980000010000000026000000000012567cb504ed973dfc40c8d071a7ebe14ac9716a7dfe170b8f2b990e81451c1fddd8f8bb9df8aab4640cf4c4f53b4b2b068b090000010000000026000000000012567d87b6fbbcef97fbee49297dee23345dd16a615c135394838cae8b72b577fa8655af9c784d6a6362a150029b51efe89ef20000010000000026000000000012567e923ace4dee9601e6f3b8cee780cc29a54fefd23247cb7042ec0262307e7ab16e939c53981a27d0538a575ca4d4c782870000010000000026000000000012567f90533176762a56692a599d7ab8bb325b2fd537af03990d0478254c890f3e2625c4a5acbf658de27a4452d5ed4e1649ab00000100000000260000000000125680aee77c661dcf96eab83cc64d4bcc527a9625977c48ccb458dc9d596a4fcb2634096bcf8cf9f11ea56bbcef676d933f6900000100000000260000000000125681b700854ebd1ff92034752180a3149d48680c23d2a5bf1b33c6dff35d85366b3ac85a5d8bf245bc7f3a7439e5a7fbafa600000100000000260000000000125682863d74f8619d37855f7c52d846775c58447e504513f2dcb84177ff0f251d6f69c106cf872173859754fb94badc6dc477000001000000002600000000001256838a15ec3bbc8dfb0897ed128d855cf101e6515b5151168af070ab9af56f1618f8d7b46762246888ffafe36edaf8bdfde10000010000000026000000000012568490096bde9cacb6a9bbd28c86e4308d7f635f3f7c9bd203577be0f0a72582f796ec5aaa9a2d8cf0cf67cf01511df2daae00000100000000260000000000125685822ec8f954c0acd324298c473ca7f730395a3aa7de7a031efc00bff9af5f8f4777dc43c937ba3a3add6c015c4dac8e8000000100000000260000000000125686b7ebfcd697a05706b722371f4a4d693888d1fae924418fec25cd0b2d06dc627f119470f2e425db8f8f3ad11427a3794900000100000000260000000000125687820ee2a7ae862273ff52631fb80a24c16cd1f0c7285fa0f297313df25f61ce6787fd51d884f2a715c4fe4efc467baa94000001000000002600000000001256888eb2ba0010067308ee82746bfd68cbeae3e90d53f6d1d6d4977594502d559ee82cfe4a5de8a350dfdc95c3e8b9caac3100000100000000260000000000125689a2055e3ff7bd74aa540ce3b980045045647ba3aac7087f59cf6fb46e484bd3f99339a2ad155034417ffe80c7eb86b4ad0000010000000026000000000012568aae375bd415b4e7941b61896aa3e7c4417811f6759c5985e3cf7c9717a4db63a4c1659f2618455a18abe1acd3833c7d4a0000010000000026000000000012568b955484f9e9ed78a88d92cd164b4dcc25ff2d43f56c1d6c9827bca53dbff17f0e4f6f9e56e6d6d598d7697dcf15d5c5a80000010000000026000000000012568c8a710afea922a7d688605e4c13471df004dc252ee883f0fe550d2b1a4ca9c8a6770f29f8d6fd841baa85f442562741a70000010000000026000000000012568d98fca9c0428d431a0f9263e65e528230b6cc6a5842b94c3b4facd84dca05bf0d5a3fe422f54a95258f9eb98ebca4dbd80000010000000026000000000012568eac260dea7bc5181e78a6511f73d76aeb8bafff41a7cb49abb3ac79b04a0546e7f515836cbf0cfda0b77466396c1f33e10000010000000026000000000012568f885b94a1e8ccdf5b9806cc24afdba51a9140ad2563b5c97061c10dd8ccd94bc12410a4d778855ec7359c61edf01a93cd00000100000000260000000000125690ae4fe9d2346f8b480a8bd4f280e902ac10f034d1a26254a06f96b61ea1853f1bf6430817d57c4bd5eed2486848211178000001000000002600000000001256918ead7af7b379a48475f5600a1cf7da9aa66d1bb4623527a4f0f3df71b1ae778034b848dba98c5efa93a89bfa5327b54600000100000000260000000000125692b4084a1237a047611e2cbc0b50a6323608b768e58ade5e9eee82d32401ed037eb8fabfedcb83ecda02402a537d9c4e2c00000100000000260000000000125693af6399cc772a7f8424585872bd141b8ea7dbfac04f1476951c77bd5397bb9d9eb24daab4f980d79d9fe103b5bca50f440000010000000026000000000012569480cb2e28d3dc13dcb4df529564724616cb36df24cc158397e4df5c394eda1be365ced4a2c67df00a28dd825b2e95345000000100000000260000000000125695b23b6f0716300b6a957fa156b24bee053ef04a8d42fb8db1943b9fb09cc7edfd001e0f100820a9c7b289d2f57fc237530000010000000026000000000012569680afcaf87064017ccb0d1c2771b7ee9a1f867e442bd71246950bee60ec34b627e0f5d8bfc478b1f863095c6f63bd456900000100000000260000000000125697a6b7d83cd7a5a30eb1484fe0d95ba1e53ddaefa084e8c0394652600cc2595df9da7b60f4e7154122c8fb0e4650baf36e0000010000000026000000000012569898b06c1b3d1a0c5056be1d7bc8277f3ae580759b275a61a131f7c97ca5e36cfd4ebc1b81aa91cba63d1751d585bcfbff00000100000000260000000000125699a4761dc74609745be116145c9d1b3d80d191c663d0adc25101aaf46a349e23ba7b6bd7f7c8908473ba565f575b408a4d0000010000000026000000000012569ab737844ca9bb56a28b32217d697d76e15355b37a47b8d328fab2dbb57127673ca056dd1773f767ba4c4abb1c7fc41d390000010000000026000000000012569b9502ea631dcb2337a1d1c5ae9d69b65ba034e41c10a220ad31eff05629334db3254b0c4e5dc8b67d75b1f1c2f4008ecb0000010000000026000000000012569cae9ced8ebb3fceb4e67ee67bc02a3bc0a99fed7ae3118fc8b58f70025d3396bb768a74d741626425b9e438826c40ac430000010000000026000000000012569d8840ea05d5d75cb2e478f6a8dc4e23d229afa9a836928d21807c5cdaace39bec22b3b63dc5ff0f7dd96c5be49053bbd00000010000000026000000000012569e9557933f007aad3a2a234e89e0bcd629b9491767753f0cd04e6f6b048a2911538a84acd98d8b8838cc0f0c39b4dc54250000010000000026000000000012569f8422d58fa1f28a2186345e88c810560cedcc29deb2629d09053c0623ea44f6e78ad2da694df8b695f601dfea27fb2c7d000001000000002600000000001256a0819cbeb315cddcadbbe52a783dc2ebb2e6ebeb611352af863b706e45f94a766523fbba0a648f86d42519ea2ccb1e7a8b000001000000002600000000001256a1a5e63ea2bfd60861e688cf093c2253f5c0d00fccdc60d087f4f2a932d2bf3c911a3812c5c8ab317d2f6d93b66a70bac0000001000000002600000000001256a2b4b53e64c2433dbe6fb00e1ce2e1c6323f1da7755a0249434006821a57d71fff1ce02b9e64b0744667dd5b937ffe8cd9000001000000002600000000001256a3a2d2899c6776003961b0c161b9821f7a9dc6be1226e7b6997b4c0c1ffdd4671becc770602f76b8eb3ffe27e4fc40b905000001000000002600000000001256a48451d597174752d92d4ea7894d4ccf0d6d8e11c93528906c926395c5fb0a3e3d4e16420f478f86e4ad4dc16ea633bcb4000001000000002600000000001256a5a3def6a870514f9257bf1237bf5b3c4420fed8947202624c3b233f4aa16d44ab7132f02b1a5e6a0ec1cb11a5f94aa549000001000000002600000000001256f3ad153045f72b9ced59ca2de34bca8cddb901a3f557911eb1a5cfe3b98f0e92382640ddc7d81ef5b761a3e7b6d75be3be000001000000002600000000001256f48a48d8fcf60a014931331c4c5963d807e4c6f26513138e80393cb46480d96d4edf94a86871a069441c3a1faaf3ca4503000001000000002600000000001256f5b3beb4a273b11365c521e94faf496ef76d077392a67ced2c1557c714524fa3e8000c463d81b6f02d5fd162eb3c4c9608000001000000002600000000001256f6b0b634474bf2ec4e2dc00524848c4243bca807359631dbe16b280f01ddf535f2a6395a7d321456bd3e6d626a9c98a8d9000001000000002600000000001256f7ad91eb47fdcf8901b146ed23fca97a34a427aabddc7603a94221543dd55b5b02ed07edbcd54330662530ef909d1dc9e5000001000000002600000000001256f8abd4b2d96a388021fa3f240685f0beb6cd234492a22395d8a601475858dee19854d57f0aa51deec11c32eed298fa3f48000001000000002600000000001256f994151fe21c19dd0ba6093ef768dd2aa9f3da8fcf346d4affc3ff9bee33882d1f7456e604239bd687d072fb3dc8e05d9a000001000000002600000000001256fa879182e1b6efc1b27c35913e244c62c0644caf835edc93b42e9a8f29fb0eaa0bfc73609f0bd7df3c1812538b5b7d4383000001000000002600000000001256fbb569d1f9d288404e265b08af1d2ca234d8d2ce728a4643982137acdce563ff29f748e9db490d9466ab8d062b2b7ebc4c000001000000002600000000001256fcb3992f43f899bcfcfd279f6aa894ca08001df6b43859134f0216167e96be98c5e2ffcb62f24db209b7e15aeb745c07c0000001000000002600000000001256fda2fe1bf9bf5dffedee7eb3ba89dc3e5add4f8e4eb25b7e6efa8948d1071c38e91a42e2fb9c68a106c4d6fc2cdba10760000001000000002600000000001256fe8e19af5b0cb159b720155fedd62a0b5d89b26983d20407764b09fed82a3f076047f7db560a6ec548fa01a7817336b932000001000000002600000000001256ffb899b5292fc71e76a81e0775fac19a1ab994e7b62bed2cf5f45d61b78c5e097889fa0c5c869569cd8565a3a8970f21c80000010000000026000000000012570093e8cf2fc485519473009b24e2d9418387780db1da50fa8f8f49ad923da83157ac9cf7d5986f0074f95aa44db4e4294700000100000000260000000000125701935f7971be8ecbef748d61455bcd88b82187c8b86d3e037f1503b5790aae099f02e9defbe7ad3951dcfc3d055d1efb8a00000100000000260000000000125702aced3601f295a5e92bbf4a70a2b6456214a5dba2cae8104cc325fe65f0ff402f358750f5131e605b6cc5ee20322a2eea00000100000000260000000000125703a13be3d5b04037958befbb7548396d1a421e7aafe138e70688a81051aff09bcb95dbd38ef0db5451b527409d855d192a00000100000000260000000000125704ab3e22f6459d7cf0628f7dfe8d1459907a94832da66fcde8524b9400160c56efe543c14ee48e52364dd1496383f589700000010000000026000000000012570588bba74a2d23f03524497aff029e1f879911a34cef8943ebe84205ed85d2cc00486c1805b4271417dd263d6e3bf4a3db00000100000000260000000000125706b0fa089545f4713a92d9152eb14ab3a89cc0be8ffcff11b4d00f0102feaecbfeb7f1ee23d4ded1f0fb087646243195d200000100000000260000000000125707a47e1a08e87f3f98ad9e36fe433297303792f06c7664b85219470447cee7fa22ecaf910be934c47e8bb3b0373e378158000001000000002600000000001257088788e31582cd2c39e41889088489b9b78bb2ed0e73f179e190559ed547efbba8cef57175635cd8e4769c2ad0b0f186fe00000100000000260000000000125709a86d6007554f154c70cb3aa6260e20775b3e98302ffaba52c400c9f42ba98e4fbe179b6e20682ffe43c6bc64e164a7240000010000000026000000000012570a96d56b1422f95705196da995c1e2ff8187312c1cb91d51ee43dbdab60c60580ce87d92e4375997e7a88c1c9d90fd571a0000010000000026000000000012570b88df46edd4e3a23064014346ddc18a99ea472204793d3e7c7f01f07eab150a1b31afcaa283073d02bfd6ec7f84d8312d0000010000000026000000000012570ca9dcd180ea55fc312c3d65ec3fba659120dfb6a44b4ce4476c70a075c4e4fc60ad793ff0622e2102d07da6bc126ff9b60000010000000026000000000012570db0d5ed006554afc3f67321bbbb4532dbf5e873d4b18827ab81f7c0643c579d1e7a52379b92aaedb0e4b4e7e87302f0d30000010000000026000000000012570ea663dc9011084da45ff48e2dc4dbeb90b8a60a4dd1187e94b3f652aa5745f5dca8cc4d02921b8ddc9d541355a039cbaf0000010000000026000000000012570fa32d77796abe95ed81b1f7bf982279aeb07903a061a53ab83e9ed9ffdac814a618acb53db40e2f79a62797fae7b3275c0000010000000026000000000012571091c809faf055607bc68eed76eb4d18040cda859a7416492600617ba184c4bec3c5511f6da86db49f188647c9b0bab38000000100000000260000000000125711b6759fde5fbbbe671f4446630a402c520938e39d01fb6d5f611055c15b40ac50ec73d5d40732d5796e6f906d437bd04c000001000000002600000000001257128c445bbe62d747ba52abc8407ea2d3bf76c2ce994e5a0de992d85bd2260247d06bf698b08ec3e94a3476846be3a6336000000100000000260000000000125713837523b298e9c926132ce8c85b9619ead5ea2ff6ed1ffeca94fa9fd4dc7915d16d330cfb79510b662798474e134fd1ae000001000000002600000000001257148f2813734a70d6faa27b63ca6c272a54eccf61cf4bb24736425fae0e46c17409ed36c34de51fbfb17c13219143ae5ff500000100000000260000000000125715a8184001dbc35b24da6be33d1db9620cde0e952e34555202af1e0dad8a30cf5bcd1721325382843dad608ce059e0c50600000100000000260000000000125716a84ff8038592b20ed17e72d72188dd7eb9b8d1cd11990220ee95866fb4557600baa460d9f84e506426d8d3d352bf1fb000000100000000260000000000125717af7f7107b92b5acf636df217b3245b0129de5b8cc1e7d014f5b09d11cbd0b2f992e38ed810b60993d6ec03216231e0e80000010000000026000000000012571895bddbabfc022b1eb8a36dde7a0090697bb446ac9417c00c96c8045eef144562342f0eb06be3172c3a31cb0c2678c510000001000000002600000000001257198924956e9d67a871f6bd919060cc4398fea46472a98134f0741eab09863da0b24038f4074b8a9ad5f9feeb4ea26836e10000010000000026000000000012571a9935f5e1b1e8ff7aa96c135a31302a74107407b3578478688f90ccd1e42e2fd73ff1a0b9090581296809cfd1b039a1390000010000000026000000000012571b987e6700dc5c715390f27a0acf5dad71c9ab573ad9823cd01010718da20f6b35e3e6628c4439c20a10938d67abccafc90000010000000026000000000012571ca529efbc11ea0db3dcb827575a59200e3990073ec0e3af3c9506651a6e02d472a4c98f8a589c52a17d6bc3395b3d18980000010000000026000000000012571d8b5a8e7db0bac6f76b6d73e14931cca7437b1d4e2133bc46cfb8f80b9cf5f34cfebea0216b0b527807ea3b39e842510e0000010000000026000000000012571e935c82dde7f699c6cdb119a0eb58735ff26e57ea52c7dcd67dab8f23980c7fec3f05d194113fe7b2faf059aa004feb310000010000000026000000000012571fa7f7adef23c971ad60207e7547609406951b43776ea00cf82f67d22a95235910066625f0c8187d1bb7aa64b899332eaa00000100000000260000000000125720b303bc1005184d37cf8336746a10816f5125edd6a4b5033903ba8d00a9435411d07ebce22af24e9d7ea0f64e2cd1eabe00000100000000260000000000125721aa845e87e828ee240d15b13e87d8e82dec97d66ea00359b156cfc6911e830de9e4bf656e1ce163529b65022ded49f85d00000100000000260000000000125722a728ae94a63e35ee47d5dbf850272bfc187e0e6158689d5348125f9b5641fd169d363e081e2585bf5876f736b035f53d000001000000002600000000001257238a13e8163e251ac6358332bd1cfd4d6402c55220ba7e4724253929a36a3abc81543909118303c5fc818f43788e9823d100000100000000260000000000125724880c53d3f58610710a9c2e988f78b037e68d81ac80824030a82f94209ce50497a1d4637e087afe5c3687f94ee29377b500000100000000260000000000125725a37700a63c292d670b267dc56379f2e1048afb10a487d7eb5992f4674742ef3b351f7d636a74d6a0f00905e6cdc6fa9a00000100000000260000000000125726a71422dc10626e9f880370dc3c33b4d1fece95d8ed0a938f8c0683e172d3691e84f49ddeb01fd0e1a639a9a053afd7b800000100000000260000000000125727814670bacfe28958efc42e05813dc33c72893f34c77d44c2332e4fac9c4133919e6bcac11856abe33b0e18322ec25d9600000100000000260000000000125728a2956da4b61955e4008c5acaffef05937c88a997c6c85b7ca83bcc11b69fa8d677301bde5915bbd11139d8dca0ef94c4000001000000002600000000001257298b0519379449b86501e87617d564b70f27d8749eb6c7668ece6ba762373989c25c6b90a3ecea3ed272021109c57e42b0" + predefined_data_format = 1 + + # Call submitExitRequestsData + tx = validators_exit_bus.submitExitRequestsData( + (predefined_data, predefined_data_format), + {"from": stranger} + ) + + # Validate ExitDataProcessing event + matching_events = [] + target = web3.keccak(text="ExitDataProcessing(bytes32)").hex() + for log in tx.logs: + if log['topics'][0].hex() == target: + matching_events.append(log) + exit_requests_hash = log['data'] + predefined_data_bytes = bytes.fromhex(predefined_data[2:]) + assert exit_requests_hash == web3.keccak(encode(['bytes', 'uint256'], [predefined_data_bytes, predefined_data_format])) + + assert len(matching_events) == 1, f"Expected exactly 1 ExitDataProcessing event, found {len(matching_events)}" + + print("✅ Vote executed successfully:") + print(f" - SUBMIT_REPORT_HASH_ROLE granted and revoked to/from agent") + print(f" - Exit hash {EXIT_HASH_TO_SUBMIT} submitted") + print(f" - All {expected_events} events validated correctly") diff --git a/interfaces/ValidatorsExitBusOracle.json b/interfaces/ValidatorsExitBusOracle.json index 837da4724..6d07ffd00 100644 --- a/interfaces/ValidatorsExitBusOracle.json +++ b/interfaces/ValidatorsExitBusOracle.json @@ -35,11 +35,6 @@ "name": "AdminCannotBeZero", "type": "error" }, - { - "inputs": [], - "name": "ArgumentOutOfBounds", - "type": "error" - }, { "inputs": [ { @@ -632,6 +627,19 @@ "name": "RoleRevoked", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "maxValidatorsPerReport", + "type": "uint256" + } + ], + "name": "SetMaxValidatorsPerReport", + "type": "event" + }, { "anonymous": false, "inputs": [ From c5ccda8967e940111310d61fe8f1fa6f5ce917a8 Mon Sep 17 00:00:00 2001 From: hweawer Date: Tue, 2 Sep 2025 16:34:13 +0200 Subject: [PATCH 13/28] Upgrade verifier (#471) * Upgrade verifier * Move to archieve --- .../scripts/vote_tw_upgrade_verifier_hoodi.py | 94 +++++++++++ .../test_vote_tw_upgrade_verifier_hoodi.py | 151 ++++++++++++++++++ configs/config_hoodi.py | 2 +- 3 files changed, 246 insertions(+), 1 deletion(-) create mode 100644 archive/scripts/vote_tw_upgrade_verifier_hoodi.py create mode 100644 archive/tests/test_vote_tw_upgrade_verifier_hoodi.py diff --git a/archive/scripts/vote_tw_upgrade_verifier_hoodi.py b/archive/scripts/vote_tw_upgrade_verifier_hoodi.py new file mode 100644 index 000000000..4ede84c06 --- /dev/null +++ b/archive/scripts/vote_tw_upgrade_verifier_hoodi.py @@ -0,0 +1,94 @@ +""" +Vote 2025-09-02 - TW Upgrade Validator Exit Verifier + +1. Upgrade Lido Locator implementation +2. Grant REPORT_VALIDATOR_EXITING_STATUS_ROLE to new validator exit verifier +3. Revoke REPORT_VALIDATOR_EXITING_STATUS_ROLE from old validator exit verifier + +Vote passed & executed on Sep 02, 2025, 03:47 PM GMT+2, block 1130827 +""" + +import time +from typing import Any, Dict, Tuple, Optional +from brownie import interface +from brownie.network.transaction import TransactionReceipt + +from utils.config import contracts +from utils.voting import confirm_vote_script, create_vote +from archive.scripts.vote_tw_csm2_hoodi import prepare_proposal +from utils.config import get_deployer_account, get_is_live, get_priority_fee +from utils.agent import agent_forward +from utils.ipfs import upload_vote_ipfs_description, calculate_vote_ipfs_description +from utils.permissions import encode_oz_grant_role, encode_oz_revoke_role + +OLD_VALIDATOR_EXIT_VERIFIER = "0x7990A2F4E16E3c0D651306D26084718DB5aC9947" +LIDO_LOCATOR_IMPL = "0x47975A61067a4CE41BeB730cf6c57378E55b849A" + +DESCRIPTION = "TW Upgrade Validator Exit Verifier (HOODI)" + + +def encode_proxy_upgrade_to(proxy: Any, implementation: str) -> Tuple[str, str]: + proxy = interface.OssifiableProxy(proxy) + return proxy.address, proxy.proxy__upgradeTo.encode_input(implementation) + + +def start_vote(tx_params: Dict[str, str], silent: bool = False) -> Tuple[int, Optional[TransactionReceipt]]: + """Prepare and run voting.""" + + vote_desc_items, call_script_items = zip( + ( + "1. Upgrade Lido Locator implementation", + agent_forward([encode_proxy_upgrade_to(contracts.lido_locator, LIDO_LOCATOR_IMPL)]), + ), + ( + "2. Grant REPORT_VALIDATOR_EXITING_STATUS_ROLE to new validator exit verifier", + agent_forward( + [ + encode_oz_grant_role( + contract=contracts.staking_router, + role_name="REPORT_VALIDATOR_EXITING_STATUS_ROLE", + grant_to=contracts.validator_exit_verifier, + ) + ] + ), + ), + ( + "3. Revoke REPORT_VALIDATOR_EXITING_STATUS_ROLE from old validator exit verifier", + agent_forward( + [ + encode_oz_revoke_role( + contract=contracts.staking_router, + role_name="REPORT_VALIDATOR_EXITING_STATUS_ROLE", + revoke_from=OLD_VALIDATOR_EXIT_VERIFIER, + ) + ] + ), + ), + ) + + if silent: + desc_ipfs = calculate_vote_ipfs_description(DESCRIPTION) + else: + desc_ipfs = upload_vote_ipfs_description(DESCRIPTION) + + dg_desc = "\n".join(vote_desc_items) + dg_vote = prepare_proposal(call_script_items, dg_desc) + vote_items = {dg_desc: dg_vote} + assert confirm_vote_script(vote_items, silent, desc_ipfs) + return create_vote(vote_items, tx_params, desc_ipfs=desc_ipfs) + + +def main(): + tx_params = {"from": get_deployer_account()} + if get_is_live(): + tx_params["priority_fee"] = get_priority_fee() + + vote_id, _ = start_vote(tx_params=tx_params, silent=False) + + vote_id >= 0 and print(f"Vote created: {vote_id}.") + + time.sleep(5) # hack for waiting thread #2. + + +if __name__ == "__main__": + main() diff --git a/archive/tests/test_vote_tw_upgrade_verifier_hoodi.py b/archive/tests/test_vote_tw_upgrade_verifier_hoodi.py new file mode 100644 index 000000000..e29493748 --- /dev/null +++ b/archive/tests/test_vote_tw_upgrade_verifier_hoodi.py @@ -0,0 +1,151 @@ +from typing import Optional +from archive.scripts.vote_tw_upgrade_verifier_hoodi import start_vote, OLD_VALIDATOR_EXIT_VERIFIER, LIDO_LOCATOR_IMPL +from brownie import interface, chain, convert, web3 # type: ignore +from brownie.network.event import EventDict +from utils.test.tx_tracing_helpers import group_voting_events_from_receipt, group_dg_events_from_receipt +from utils.test.event_validators.dual_governance import validate_dual_governance_submit_event +from utils.dual_governance import wait_for_noon_utc_to_satisfy_time_constrains +from utils.config import ( + DUAL_GOVERNANCE, + TIMELOCK, + DUAL_GOVERNANCE_EXECUTORS, + LDO_HOLDER_ADDRESS_FOR_TESTS, + VOTING, + contracts, +) + + +def validate_role_grant_event(event: EventDict, role_hash: str, account: str, emitted_by: Optional[str] = None): + """Validates an OpenZeppelin AccessControl role grant event""" + assert "RoleGranted" in event, "No RoleGranted event found" + assert event["RoleGranted"][0]["role"] == role_hash, f"Wrong role hash. Expected: {role_hash}, Got: {event['RoleGranted'][0]['role']}" + assert event["RoleGranted"][0]["account"] == convert.to_address(account), f"Wrong account. Expected: {account}, Got: {event['RoleGranted'][0]['account']}" + + if emitted_by is not None: + assert convert.to_address(event["RoleGranted"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + + +def validate_role_revoke_event(event: EventDict, role_hash: str, account: str, emitted_by: Optional[str] = None): + """Validates an OpenZeppelin AccessControl role revoke event""" + assert "RoleRevoked" in event, "No RoleRevoked event found" + assert event["RoleRevoked"][0]["role"] == role_hash, f"Wrong role hash. Expected: {role_hash}, Got: {event['RoleRevoked'][0]['role']}" + assert event["RoleRevoked"][0]["account"] == convert.to_address(account), f"Wrong account. Expected: {account}, Got: {event['RoleRevoked'][0]['account']}" + + if emitted_by is not None: + assert convert.to_address(event["RoleRevoked"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + + +def validate_proxy_upgrade_event(event: EventDict, expected_implementation: str, emitted_by: Optional[str] = None): + """Validates Upgraded event from OssifiableProxy""" + assert "Upgraded" in event, "No Upgraded event found" + assert event["Upgraded"][0]["implementation"] == convert.to_address(expected_implementation), f"Wrong implementation. Expected: {expected_implementation}, Got: {event['Upgraded'][0]['implementation']}" + + if emitted_by is not None: + assert convert.to_address(event["Upgraded"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + + +def test_vote_tw_upgrade_verifier_hoodi(helpers, accounts, vote_ids_from_env, stranger): + """Test the TW upgrade validator exit verifier vote that upgrades locator and manages validator roles""" + + # Calculate role hash + REPORT_VALIDATOR_EXITING_STATUS_ROLE = web3.keccak(text="REPORT_VALIDATOR_EXITING_STATUS_ROLE") + + # Get contracts + staking_router = interface.StakingRouter(contracts.staking_router) + lido_locator_proxy = interface.OssifiableProxy(contracts.lido_locator) + timelock = interface.EmergencyProtectedTimelock(TIMELOCK) + dual_governance = interface.DualGovernance(DUAL_GOVERNANCE) + + # Check initial state + initial_implementation = lido_locator_proxy.proxy__getImplementation() + + # Check role states before vote + old_verifier_has_role_before = staking_router.hasRole(REPORT_VALIDATOR_EXITING_STATUS_ROLE, OLD_VALIDATOR_EXIT_VERIFIER) + new_verifier_has_role_before = staking_router.hasRole(REPORT_VALIDATOR_EXITING_STATUS_ROLE, contracts.validator_exit_verifier) + + print(f"Initial Lido Locator implementation: {initial_implementation}") + print(f"Old validator exit verifier ({OLD_VALIDATOR_EXIT_VERIFIER}) has role before vote: {old_verifier_has_role_before}") + print(f"New validator exit verifier ({contracts.validator_exit_verifier}) has role before vote: {new_verifier_has_role_before}") + + # START VOTE + if len(vote_ids_from_env) > 0: + (vote_id,) = vote_ids_from_env + else: + tx_params = {"from": LDO_HOLDER_ADDRESS_FOR_TESTS} + vote_id, _ = start_vote(tx_params, silent=True) + + vote_tx = helpers.execute_vote(accounts, vote_id, contracts.voting) + print(f"voteId = {vote_id}") + + proposal_id = vote_tx.events["ProposalSubmitted"][1]["proposalId"] + print(f"proposalId = {proposal_id}") + + chain.sleep(timelock.getAfterSubmitDelay() + 1) + dual_governance.scheduleProposal(proposal_id, {"from": stranger}) + + chain.sleep(timelock.getAfterScheduleDelay() + 1) + wait_for_noon_utc_to_satisfy_time_constrains() + + dg_tx = timelock.execute(proposal_id, {"from": stranger}) + + # --- VALIDATE EXECUTION RESULTS --- + + # 1. Verify Lido Locator was upgraded + final_implementation = lido_locator_proxy.proxy__getImplementation() + assert final_implementation == LIDO_LOCATOR_IMPL, f"Locator implementation not upgraded. Expected: {LIDO_LOCATOR_IMPL}, Got: {final_implementation}" + assert final_implementation != initial_implementation, "Implementation should have changed" + + # 2. Verify validator roles were updated + new_verifier_has_role_after = staking_router.hasRole(REPORT_VALIDATOR_EXITING_STATUS_ROLE, contracts.validator_exit_verifier) + old_verifier_has_role_after = staking_router.hasRole(REPORT_VALIDATOR_EXITING_STATUS_ROLE, OLD_VALIDATOR_EXIT_VERIFIER) + + assert new_verifier_has_role_after, f"New verifier ({contracts.validator_exit_verifier}) should have role after vote" + assert not old_verifier_has_role_after, f"Old verifier ({OLD_VALIDATOR_EXIT_VERIFIER}) should not have role after vote" + + # --- VALIDATE EVENTS --- + voting_events = group_voting_events_from_receipt(vote_tx) + assert len(voting_events) >= 1, "No voting events found" + + validate_dual_governance_submit_event( + voting_events[0], + proposal_id, + proposer=VOTING, + executor=DUAL_GOVERNANCE_EXECUTORS[0], + ) + + dg_execution_events = group_dg_events_from_receipt(dg_tx, timelock=TIMELOCK, admin_executor=DUAL_GOVERNANCE_EXECUTORS[0]) + expected_events = 3 # 1 proxy upgrade + 1 role grant + 1 role revoke + assert len(dg_execution_events) == expected_events, f"Expected {expected_events} dual governance events, got {len(dg_execution_events)}" + + event_idx = 0 + + # Step 1: Upgrade Lido Locator implementation + validate_proxy_upgrade_event( + dg_execution_events[event_idx], + expected_implementation=LIDO_LOCATOR_IMPL, + emitted_by=contracts.lido_locator + ) + event_idx += 1 + + # Step 2: Grant REPORT_VALIDATOR_EXITING_STATUS_ROLE to new validator exit verifier + validate_role_grant_event( + dg_execution_events[event_idx], + role_hash=REPORT_VALIDATOR_EXITING_STATUS_ROLE.hex(), + account=contracts.validator_exit_verifier, + emitted_by=contracts.staking_router + ) + event_idx += 1 + + # Step 3: Revoke REPORT_VALIDATOR_EXITING_STATUS_ROLE from old validator exit verifier + validate_role_revoke_event( + dg_execution_events[event_idx], + role_hash=REPORT_VALIDATOR_EXITING_STATUS_ROLE.hex(), + account=OLD_VALIDATOR_EXIT_VERIFIER, + emitted_by=contracts.staking_router + ) + + print("✅ Vote executed successfully:") + print(f" - Lido Locator upgraded from {initial_implementation} to {LIDO_LOCATOR_IMPL}") + print(f" - REPORT_VALIDATOR_EXITING_STATUS_ROLE granted to new verifier: {contracts.validator_exit_verifier}") + print(f" - REPORT_VALIDATOR_EXITING_STATUS_ROLE revoked from old verifier: {OLD_VALIDATOR_EXIT_VERIFIER}") + print(f" - All {expected_events} events validated correctly") diff --git a/configs/config_hoodi.py b/configs/config_hoodi.py index c4f83714c..417ec86e0 100644 --- a/configs/config_hoodi.py +++ b/configs/config_hoodi.py @@ -101,7 +101,7 @@ # Triggerable Withdrawals Gateway TRIGGERABLE_WITHDRAWALS_GATEWAY = "0x6679090D92b08a2a686eF8614feECD8cDFE209db" -VALIDATOR_EXIT_VERIFIER = "0x7990A2F4E16E3c0D651306D26084718DB5aC9947" +VALIDATOR_EXIT_VERIFIER = "0xa5F5A9360275390fF9728262a29384399f38d2f0" # CSM addresses CSM_COMMITTEE_MS = "0x4AF43Ee34a6fcD1fEcA1e1F832124C763561dA53" From 59860741fbe9b1344d620620cb81da9028a388cd Mon Sep 17 00:00:00 2001 From: hweawer Date: Thu, 11 Sep 2025 08:51:08 +0200 Subject: [PATCH 14/28] Fix old addresses mainnet --- scripts/vote_tw_csm2_mainnet.py | 8 ++++---- tests/test_vote_tw_csm2_mainnet.py | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/scripts/vote_tw_csm2_mainnet.py b/scripts/vote_tw_csm2_mainnet.py index 28f7c3674..3d1a6aae9 100644 --- a/scripts/vote_tw_csm2_mainnet.py +++ b/scripts/vote_tw_csm2_mainnet.py @@ -165,10 +165,10 @@ CS_ICS_GATE_BOND_CURVE = ([1, 1.5 * 10**18], [2, 1.3 * 10**18]) # Identified Community Stakers Gate Bond Curve # Add missing constants -OLD_GATE_SEAL_ADDRESS = "0x2168Ea6D948Ab49c3D34c667A7e02F92369F3A9C" -NEW_WQ_GATE_SEAL = "0x73d76Bd3D589B2b2185c402da82cdAfbc18b958D" -NEW_TW_GATE_SEAL = "0x368f2fcb593170823cc844F1B29e75E3d26879A1" -RESEAL_MANAGER = "0x05172CbCDb7307228F781436b327679e4DAE166B" +OLD_GATE_SEAL_ADDRESS = "0xf9C9fDB4A5D2AA1D836D5370AB9b28BC1847e178" +NEW_WQ_GATE_SEAL = "0x8A854C4E750CDf24f138f34A9061b2f556066912" +NEW_TW_GATE_SEAL = "0xA6BC802fAa064414AA62117B4a53D27fFfF741F1" +RESEAL_MANAGER = "0x7914b5a1539b97Bd0bbd155757F25FD79A522d24" # Add EasyTrack constants EASYTRACK_EVMSCRIPT_EXECUTOR = "0x79a20FD0FA36453B2F45eAbab19bfef43575Ba9E" diff --git a/tests/test_vote_tw_csm2_mainnet.py b/tests/test_vote_tw_csm2_mainnet.py index b5c97071a..327e3adcd 100644 --- a/tests/test_vote_tw_csm2_mainnet.py +++ b/tests/test_vote_tw_csm2_mainnet.py @@ -167,10 +167,10 @@ def check_proxy_implementation(proxy_address, expected_impl): VALIDATOR_EXIT_VERIFIER = "0xFd4386A8795956f4B6D01cbb6dB116749731D7bD" # Add missing constants -OLD_GATE_SEAL_ADDRESS = "0x2168Ea6D948Ab49c3D34c667A7e02F92369F3A9C" -NEW_WQ_GATE_SEAL = "0x73d76Bd3D589B2b2185c402da82cdAfbc18b958D" -NEW_TW_GATE_SEAL = "0x368f2fcb593170823cc844F1B29e75E3d26879A1" -RESEAL_MANAGER = "0x05172CbCDb7307228F781436b327679e4DAE166B" +OLD_GATE_SEAL_ADDRESS = "0xf9C9fDB4A5D2AA1D836D5370AB9b28BC1847e178" +NEW_WQ_GATE_SEAL = "0x8A854C4E750CDf24f138f34A9061b2f556066912" +NEW_TW_GATE_SEAL = "0xA6BC802fAa064414AA62117B4a53D27fFfF741F1" +RESEAL_MANAGER = "0x7914b5a1539b97Bd0bbd155757F25FD79A522d24" # Add EasyTrack constants EASYTRACK_EVMSCRIPT_EXECUTOR = "0x79a20FD0FA36453B2F45eAbab19bfef43575Ba9E" From a288c4262638963e44ee9cd82ddab47bdd5a6c3e Mon Sep 17 00:00:00 2001 From: hweawer Date: Mon, 15 Sep 2025 09:36:54 +0200 Subject: [PATCH 15/28] Remove redundant vote --- scripts/vote_hoodi_exit_hashes.py | 122 ------------------------- tests/test_vote_hoodi_exit_hashes.py | 128 --------------------------- 2 files changed, 250 deletions(-) delete mode 100644 scripts/vote_hoodi_exit_hashes.py delete mode 100644 tests/test_vote_hoodi_exit_hashes.py diff --git a/scripts/vote_hoodi_exit_hashes.py b/scripts/vote_hoodi_exit_hashes.py deleted file mode 100644 index d6d4f06f1..000000000 --- a/scripts/vote_hoodi_exit_hashes.py +++ /dev/null @@ -1,122 +0,0 @@ -""" -Vote [DATE] - Grant and Revoke SUBMIT_REPORT_HASH_ROLE for ValidatorsExitBus Oracle - -1. Grant SUBMIT_REPORT_HASH_ROLE to the agent -2. Perform oracle operations with predefined data -3. Revoke SUBMIT_REPORT_HASH_ROLE from the agent - -Vote passed & executed on [DATE], block [BLOCK_NUMBER] -""" - -DESCRIPTION = "Update Sandbox Module Implementation (HOODI)" - -import time -from typing import Dict, Tuple, Optional -from brownie import interface, web3, convert -from brownie.network.transaction import TransactionReceipt - -from utils.config import ( - ARAGON_KERNEL, - AGENT, -) -from utils.config import contracts - -from utils.voting import confirm_vote_script, create_vote -from utils.evm_script import encode_call_script -from archive.scripts.vote_tw_csm2_hoodi import prepare_proposal -from utils.config import get_deployer_account, get_is_live, get_priority_fee -from utils.agent import agent_forward -from utils.ipfs import upload_vote_ipfs_description, calculate_vote_ipfs_description -from utils.voting import confirm_vote_script, create_vote -from utils.permissions import encode_oz_grant_role, encode_oz_revoke_role - -EXIT_HASH_TO_SUBMIT = "0x4e72449ac50f5fa83bc2d642f2c95a63f72f1b87ad292f52c0fe5c28f3cf6e47" -VOTE_DESCRIPTION = "Run ValidatorsExitBus Oracle submitExitRequestsHash on Hoodi" - - -def start_vote(tx_params: Dict[str, str], silent: bool = False) -> Tuple[int, Optional[TransactionReceipt]]: - """Prepare and run voting.""" - - # Grant SUBMIT_REPORT_HASH_ROLE to agent, perform operations, then revoke - validators_exit_bus = interface.ValidatorsExitBusOracle(contracts.validators_exit_bus_oracle) - calldata = validators_exit_bus.submitExitRequestsHash.encode_input(EXIT_HASH_TO_SUBMIT) - - vote_desc_items, call_script_items = zip( - ( - f"1. Grant APP_MANAGER_ROLE role to the AGENT", - agent_forward( - [ - ( - contracts.acl.address, - contracts.acl.grantPermission.encode_input( - AGENT, ARAGON_KERNEL, convert.to_uint(web3.keccak(text="APP_MANAGER_ROLE")) - ), - ) - ] - ), - ), - ( - "2. Grant SUBMIT_REPORT_HASH_ROLE to the agent", - agent_forward( - [ - encode_oz_grant_role( - contract=validators_exit_bus, role_name="SUBMIT_REPORT_HASH_ROLE", grant_to=contracts.agent - ) - ] - ), - ), - ( - "3. Perform your contract calls with predefined data", - agent_forward([(contracts.validators_exit_bus_oracle.address, calldata)]), - ), - ( - "4. Revoke SUBMIT_REPORT_HASH_ROLE from the agent", - agent_forward( - [ - encode_oz_revoke_role( - contract=validators_exit_bus, role_name="SUBMIT_REPORT_HASH_ROLE", revoke_from=contracts.agent - ) - ] - ), - ), - ( - f"5. Revoke APP_MANAGER_ROLE role from the AGENT", - agent_forward([( - contracts.acl.address, - contracts.acl.revokePermission.encode_input( - AGENT, - ARAGON_KERNEL, - convert.to_uint(web3.keccak(text="APP_MANAGER_ROLE")) - ) - )]), - ), - ) - - if silent: - desc_ipfs = calculate_vote_ipfs_description(DESCRIPTION) - else: - desc_ipfs = upload_vote_ipfs_description(DESCRIPTION) - - dg_desc = "\n".join(vote_desc_items) - dg_vote = prepare_proposal(call_script_items, dg_desc) - vote_items = {dg_desc: dg_vote} - - return confirm_vote_script(vote_items, silent, desc_ipfs) and create_vote( - vote_items, tx_params, desc_ipfs=desc_ipfs - ) - - -def main(): - tx_params = {"from": get_deployer_account()} - if get_is_live(): - tx_params["priority_fee"] = get_priority_fee() - - vote_id, _ = start_vote(tx_params=tx_params, silent=False) - - vote_id >= 0 and print(f"Vote created: {vote_id}.") - - time.sleep(5) # hack for waiting thread #2. - - -if __name__ == "__main__": - main() diff --git a/tests/test_vote_hoodi_exit_hashes.py b/tests/test_vote_hoodi_exit_hashes.py deleted file mode 100644 index 470985518..000000000 --- a/tests/test_vote_hoodi_exit_hashes.py +++ /dev/null @@ -1,128 +0,0 @@ -from typing import Optional -from scripts.vote_hoodi_exit_hashes import start_vote, EXIT_HASH_TO_SUBMIT -from brownie import interface, chain, convert, web3 # type: ignore -from brownie.network.event import EventDict -from utils.test.tx_tracing_helpers import group_voting_events_from_receipt, group_dg_events_from_receipt -from utils.test.event_validators.dual_governance import validate_dual_governance_submit_event -from utils.dual_governance import wait_for_noon_utc_to_satisfy_time_constrains -from utils.config import ( - DUAL_GOVERNANCE, - TIMELOCK, - DUAL_GOVERNANCE_EXECUTORS, - LDO_HOLDER_ADDRESS_FOR_TESTS, - AGENT, - VOTING, - contracts, -) - - -def validate_role_grant_event(event: EventDict, role_hash: str, account: str, emitted_by: Optional[str] = None): - """Validates an OpenZeppelin AccessControl role grant event""" - assert "RoleGranted" in event, "No RoleGranted event found" - assert event["RoleGranted"][0]["role"] == role_hash, f"Wrong role hash. Expected: {role_hash}, Got: {event['RoleGranted'][0]['role']}" - assert event["RoleGranted"][0]["account"] == convert.to_address(account), f"Wrong account. Expected: {account}, Got: {event['RoleGranted'][0]['account']}" - - if emitted_by is not None: - assert convert.to_address(event["RoleGranted"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" - - -def validate_role_revoke_event(event: EventDict, role_hash: str, account: str, emitted_by: Optional[str] = None): - """Validates an OpenZeppelin AccessControl role revoke event""" - assert "RoleRevoked" in event, "No RoleRevoked event found" - assert event["RoleRevoked"][0]["role"] == role_hash, f"Wrong role hash. Expected: {role_hash}, Got: {event['RoleRevoked'][0]['role']}" - assert event["RoleRevoked"][0]["account"] == convert.to_address(account), f"Wrong account. Expected: {account}, Got: {event['RoleRevoked'][0]['account']}" - - if emitted_by is not None: - assert convert.to_address(event["RoleRevoked"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" - - -def validate_submit_exit_requests_hash_event(event: EventDict, expected_hash: str, emitted_by: Optional[str] = None): - """Validates RequestsHashSubmitted event from ValidatorsExitBus""" - assert "RequestsHashSubmitted" in event, "No RequestsHashSubmitted event found" - assert event["RequestsHashSubmitted"][0]["exitRequestsHash"] == expected_hash, f"Wrong hash. Expected: {expected_hash}, Got: {event['RequestsHashSubmitted'][0]['exitRequestsHash']}" - - if emitted_by is not None: - assert convert.to_address(event["RequestsHashSubmitted"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" - - -def test_vote_hoodi_exit_hashes(helpers, accounts, vote_ids_from_env, stranger): - """Test the vote that grants SUBMIT_REPORT_HASH_ROLE temporarily to agent, uses it, then revokes it""" - - # Calculate the role hash for SUBMIT_REPORT_HASH_ROLE - SUBMIT_REPORT_HASH_ROLE = web3.keccak(text="SUBMIT_REPORT_HASH_ROLE") - - # Get contracts - validators_exit_bus = interface.ValidatorsExitBusOracle(contracts.validators_exit_bus_oracle) - timelock = interface.EmergencyProtectedTimelock(TIMELOCK) - dual_governance = interface.DualGovernance(DUAL_GOVERNANCE) - - # Check initial state - agent should not have the role - assert not validators_exit_bus.hasRole(SUBMIT_REPORT_HASH_ROLE, AGENT), "Agent should not have SUBMIT_REPORT_HASH_ROLE before vote" - - # START VOTE - if len(vote_ids_from_env) > 0: - (vote_id,) = vote_ids_from_env - else: - tx_params = {"from": LDO_HOLDER_ADDRESS_FOR_TESTS} - vote_id, _ = start_vote(tx_params, silent=True) - - vote_tx = helpers.execute_vote(accounts, vote_id, contracts.voting) - print(f"voteId = {vote_id}") - - proposal_id = vote_tx.events["ProposalSubmitted"][1]["proposalId"] - print(f"proposalId = {proposal_id}") - - chain.sleep(timelock.getAfterSubmitDelay() + 1) - dual_governance.scheduleProposal(proposal_id, {"from": stranger}) - - chain.sleep(timelock.getAfterScheduleDelay() + 1) - wait_for_noon_utc_to_satisfy_time_constrains() - - dg_tx = timelock.execute(proposal_id, {"from": stranger}) - - # --- VALIDATE EXECUTION RESULTS --- - - # 1. Verify SUBMIT_REPORT_HASH_ROLE was granted and then revoked (final state is revoked) - assert not validators_exit_bus.hasRole(SUBMIT_REPORT_HASH_ROLE, AGENT), "Agent should not have SUBMIT_REPORT_HASH_ROLE after vote" - - # --- VALIDATE EVENTS --- - voting_events = group_voting_events_from_receipt(vote_tx) - assert len(voting_events) >= 1, "No voting events found" - - validate_dual_governance_submit_event( - voting_events[0], - proposal_id, - proposer=VOTING, - executor=DUAL_GOVERNANCE_EXECUTORS[0], - ) - - dg_execution_events = group_dg_events_from_receipt(dg_tx, timelock=TIMELOCK, admin_executor=DUAL_GOVERNANCE_EXECUTORS[0]) - assert len(dg_execution_events) == 3, f"Expected 3 dual governance events, got {len(dg_execution_events)}" - - # 0. Grant SUBMIT_REPORT_HASH_ROLE to agent - validate_role_grant_event( - dg_execution_events[0], - role_hash=SUBMIT_REPORT_HASH_ROLE.hex(), - account=AGENT, - emitted_by=contracts.validators_exit_bus_oracle - ) - - # 1. Submit exit requests hash - validate_submit_exit_requests_hash_event( - dg_execution_events[1], - expected_hash=EXIT_HASH_TO_SUBMIT, - emitted_by=contracts.validators_exit_bus_oracle - ) - - # 2. Revoke SUBMIT_REPORT_HASH_ROLE from agent - validate_role_revoke_event( - dg_execution_events[2], - role_hash=SUBMIT_REPORT_HASH_ROLE.hex(), - account=AGENT, - emitted_by=contracts.validators_exit_bus_oracle - ) - - print("✅ Vote executed successfully:") - print(f" - SUBMIT_REPORT_HASH_ROLE granted and revoked to/from agent") - print(f" - Exit hash {EXIT_HASH_TO_SUBMIT} submitted") - print(f" - All events validated correctly") \ No newline at end of file From 0bc1a7497d238b7cecc954a645e560bdf01458a7 Mon Sep 17 00:00:00 2001 From: hweawer Date: Mon, 15 Sep 2025 10:39:21 +0200 Subject: [PATCH 16/28] Allign with vote template --- scripts/vote_tw_csm2_mainnet.py | 717 ++++++++++++++++++-------------- 1 file changed, 410 insertions(+), 307 deletions(-) diff --git a/scripts/vote_tw_csm2_mainnet.py b/scripts/vote_tw_csm2_mainnet.py index 3d1a6aae9..e16927158 100644 --- a/scripts/vote_tw_csm2_mainnet.py +++ b/scripts/vote_tw_csm2_mainnet.py @@ -1,5 +1,5 @@ """ -Vote 23/09/2025 [MAINNET] +Vote 2025__
[MAINNET] --- Locator 1. Update locator implementation @@ -83,7 +83,10 @@ 67. Add CSSetVettedGateTree factory to EasyTrack with permissions 68. Add `SubmitValidatorsExitRequestHashes` (SDVT) EVM script factory to Easy Track 69. Add `SubmitValidatorsExitRequestHashes` (Curated Module) EVM script factory to Easy Track + +# TODO (after vote) Vote #{vote number} passed & executed on ${date+time}, block ${blockNumber}. """ + import time from typing import TYPE_CHECKING, Any, Dict @@ -112,11 +115,12 @@ add_evmscript_factory, create_permissions, ) -from utils.voting import confirm_vote_script, create_vote +from utils.voting import bake_vote_items, confirm_vote_script, create_vote +from utils.dual_governance import submit_proposals +from utils.mainnet_fork import pass_and_exec_dao_vote from utils.config import get_deployer_account, get_priority_fee, get_is_live -DESCRIPTION = "Triggerable withdrawals and CSM v2 upgrade voting (HOODI)" - +# ============================== Addresses =================================== # New core contracts implementations LIDO_LOCATOR_IMPL = "0x003f20CD17e7683A7F88A7AfF004f0C44F0cfB31" ACCOUNTING_ORACLE_IMPL = "0x2341c9BE0E639f262f8170f9ef1efeCC92cCF617" @@ -176,6 +180,9 @@ EASYTRACK_CURATED_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY = "0x397206ecdbdcb1A55A75e60Fc4D054feC72E5f63" EASYTRACK_CS_SET_VETTED_GATE_TREE_FACTORY = "0xa890fc73e1b771Ee6073e2402E631c312FF92Cd9" +# ============================= Description ================================== +IPFS_DESCRIPTION = "Triggerable withdrawals and CSM v2 upgrade voting" + def encode_staking_router_proxy_update(implementation: str) -> Tuple[str, str]: proxy = interface.OssifiableProxy(contracts.staking_router) @@ -190,7 +197,7 @@ def encode_proxy_upgrade_to(proxy: Any, implementation: str) -> Tuple[str, str]: def encode_wv_proxy_upgrade_to(proxy: Any, implementation: str) -> Tuple[str, str]: proxy = interface.WithdrawalContractProxy(proxy) - return proxy.address, proxy.proxy_upgradeTo.encode_input(implementation, b'') + return proxy.address, proxy.proxy_upgradeTo.encode_input(implementation, b"") def encode_oracle_upgrade_consensus(proxy: Any, consensus_version: int) -> Tuple[str, str]: @@ -210,7 +217,7 @@ def encode_staking_router_update_csm_module_share() -> Tuple[str, str]: CS_MODULE_TREASURY_FEE_BP, CS_MODULE_MAX_DEPOSITS_PER_BLOCK, CS_MODULE_MIN_DEPOSIT_BLOCK_DISTANCE, - ) + ), ) @@ -221,657 +228,743 @@ def to_percent(bp: int) -> float: return bp / 10000 * 100 -def start_vote(tx_params: Dict[str, str], silent: bool) -> Tuple[int, Optional[Any]]: - vote_desc_items, call_script_items = zip( +def get_vote_items(): + dg_items = [ # --- locator - ( - "1. Update locator implementation", - agent_forward([encode_proxy_upgrade_to(contracts.lido_locator, LIDO_LOCATOR_IMPL)]) - ), + # "1. Update locator implementation", + agent_forward([encode_proxy_upgrade_to(contracts.lido_locator, LIDO_LOCATOR_IMPL)]), # --- VEB - ( - "2. Update VEBO implementation", - agent_forward([encode_proxy_upgrade_to(contracts.validators_exit_bus_oracle, VALIDATORS_EXIT_BUS_ORACLE_IMPL)]) - ), - ( - "3. Call finalizeUpgrade_v2 on VEBO", - agent_forward([ + # "2. Update VEBO implementation", + agent_forward([encode_proxy_upgrade_to(contracts.validators_exit_bus_oracle, VALIDATORS_EXIT_BUS_ORACLE_IMPL)]), + # "3. Call finalizeUpgrade_v2 on VEBO", + agent_forward( + [ ( contracts.validators_exit_bus_oracle.address, contracts.validators_exit_bus_oracle.finalizeUpgrade_v2.encode_input( MAX_VALIDATORS_PER_REPORT, MAX_EXIT_REQUESTS_LIMIT, EXITS_PER_FRAME, FRAME_DURATION_IN_SEC ), ) - ]) + ] ), - ( - "4. Grant VEBO role MANAGE_CONSENSUS_VERSION_ROLE to the AGENT", - agent_forward([ + # "4. Grant VEBO role MANAGE_CONSENSUS_VERSION_ROLE to the AGENT", + agent_forward( + [ encode_oz_grant_role( contract=contracts.validators_exit_bus_oracle, role_name="MANAGE_CONSENSUS_VERSION_ROLE", grant_to=contracts.agent, ) - ]) + ] ), - ( - "5. Bump VEBO consensus version to `4`", - agent_forward([encode_oracle_upgrade_consensus(contracts.validators_exit_bus_oracle, VEBO_CONSENSUS_VERSION)]) - ), - ( - "6. Revoke VEBO role MANAGE_CONSENSUS_VERSION_ROLE from the AGENT", - agent_forward([ + # "5. Bump VEBO consensus version to `4`", + agent_forward([encode_oracle_upgrade_consensus(contracts.validators_exit_bus_oracle, VEBO_CONSENSUS_VERSION)]), + # "6. Revoke VEBO role MANAGE_CONSENSUS_VERSION_ROLE from the AGENT", + agent_forward( + [ encode_oz_revoke_role( contract=contracts.validators_exit_bus_oracle, role_name="MANAGE_CONSENSUS_VERSION_ROLE", revoke_from=contracts.agent, ) - ]) + ] ), - ( - "7. Grant SUBMIT_REPORT_HASH_ROLE on Validator Exit Bus Oracle to the EasyTrack EVM Script Executor", - agent_forward([ + # "7. Grant SUBMIT_REPORT_HASH_ROLE on Validator Exit Bus Oracle to the EasyTrack EVM Script Executor", + agent_forward( + [ encode_oz_grant_role( contract=contracts.validators_exit_bus_oracle, role_name="SUBMIT_REPORT_HASH_ROLE", grant_to=EASYTRACK_EVMSCRIPT_EXECUTOR, ) - ]) + ] ), # --- Triggerable Withdrawals Gateway (TWG) - ( - "8. Grant TWG role ADD_FULL_WITHDRAWAL_REQUEST_ROLE to the CS Ejector", - agent_forward([ + # "8. Grant TWG role ADD_FULL_WITHDRAWAL_REQUEST_ROLE to the CS Ejector", + agent_forward( + [ encode_oz_grant_role( contract=interface.TriggerableWithdrawalsGateway(TRIGGERABLE_WITHDRAWALS_GATEWAY), role_name="ADD_FULL_WITHDRAWAL_REQUEST_ROLE", grant_to=CS_EJECTOR_ADDRESS, ) - ]) + ] ), - ( - "9. Grant TWG role ADD_FULL_WITHDRAWAL_REQUEST_ROLE to the VEB", - agent_forward([ + # "9. Grant TWG role ADD_FULL_WITHDRAWAL_REQUEST_ROLE to the VEB", + agent_forward( + [ encode_oz_grant_role( contract=interface.TriggerableWithdrawalsGateway(TRIGGERABLE_WITHDRAWALS_GATEWAY), role_name="ADD_FULL_WITHDRAWAL_REQUEST_ROLE", grant_to=contracts.validators_exit_bus_oracle, ) - ]) + ] ), + # "10. Connect TRIGGERABLE_WITHDRAWALS_GATEWAY to Dual Governance tiebreaker", ( - "10. Connect TRIGGERABLE_WITHDRAWALS_GATEWAY to Dual Governance tiebreaker", - ( - contracts.dual_governance.address, - contracts.dual_governance.addTiebreakerSealableWithdrawalBlocker.encode_input( - TRIGGERABLE_WITHDRAWALS_GATEWAY - ), - ) + contracts.dual_governance.address, + contracts.dual_governance.addTiebreakerSealableWithdrawalBlocker.encode_input( + TRIGGERABLE_WITHDRAWALS_GATEWAY + ), ), # --- WV - ( - "11. Update WithdrawalVault implementation", - agent_forward([encode_wv_proxy_upgrade_to(contracts.withdrawal_vault, WITHDRAWAL_VAULT_IMPL)]) - ), - ( - "12. Call finalizeUpgrade_v2 on WithdrawalVault", - agent_forward([ + # "11. Update WithdrawalVault implementation", + agent_forward([encode_wv_proxy_upgrade_to(contracts.withdrawal_vault, WITHDRAWAL_VAULT_IMPL)]), + # "12. Call finalizeUpgrade_v2 on WithdrawalVault", + agent_forward( + [ ( contracts.withdrawal_vault.address, contracts.withdrawal_vault.finalizeUpgrade_v2.encode_input(), ) - ]) + ] ), # --- AO - ( - "13. Update Accounting Oracle implementation", - agent_forward([encode_proxy_upgrade_to(contracts.accounting_oracle, ACCOUNTING_ORACLE_IMPL)]) - ), - ( - "14. Grant AO MANAGE_CONSENSUS_VERSION_ROLE to the AGENT", - agent_forward([ + # "13. Update Accounting Oracle implementation", + agent_forward([encode_proxy_upgrade_to(contracts.accounting_oracle, ACCOUNTING_ORACLE_IMPL)]), + # "14. Grant AO MANAGE_CONSENSUS_VERSION_ROLE to the AGENT", + agent_forward( + [ encode_oz_grant_role( contract=contracts.accounting_oracle, role_name="MANAGE_CONSENSUS_VERSION_ROLE", grant_to=contracts.agent, ) - ]) + ] ), - ( - "15. Bump AO consensus version to `4`", - agent_forward([encode_oracle_upgrade_consensus(contracts.accounting_oracle, AO_CONSENSUS_VERSION)]) - ), - ( - "16. Revoke AO MANAGE_CONSENSUS_VERSION_ROLE from the AGENT", - agent_forward([ + # "15. Bump AO consensus version to `4`", + agent_forward([encode_oracle_upgrade_consensus(contracts.accounting_oracle, AO_CONSENSUS_VERSION)]), + # "16. Revoke AO MANAGE_CONSENSUS_VERSION_ROLE from the AGENT", + agent_forward( + [ encode_oz_revoke_role( contract=contracts.accounting_oracle, role_name="MANAGE_CONSENSUS_VERSION_ROLE", revoke_from=contracts.agent, ) - ]) + ] ), - ( - "17. Call finalizeUpgrade_v3() on AO", - agent_forward([ + # "17. Call finalizeUpgrade_v3() on AO", + agent_forward( + [ ( contracts.accounting_oracle.address, contracts.accounting_oracle.finalizeUpgrade_v3.encode_input(), ) - ]) + ] ), # --- SR - ( - "18. Update SR implementation", - agent_forward([encode_staking_router_proxy_update(STAKING_ROUTER_IMPL)]) - ), - ( - "19. Call finalizeUpgrade_v3() on SR", - agent_forward([( + # "18. Update SR implementation", + agent_forward([encode_staking_router_proxy_update(STAKING_ROUTER_IMPL)]), + # "19. Call finalizeUpgrade_v3() on SR", + agent_forward( + [ + ( contracts.staking_router.address, contracts.staking_router.finalizeUpgrade_v3.encode_input(), - )]) + ) + ] ), - ( - "20. Grant SR role REPORT_VALIDATOR_EXITING_STATUS_ROLE to ValidatorExitDelayVerifier", - agent_forward([ + # "20. Grant SR role REPORT_VALIDATOR_EXITING_STATUS_ROLE to ValidatorExitDelayVerifier", + agent_forward( + [ encode_oz_grant_role( contract=contracts.staking_router, role_name="REPORT_VALIDATOR_EXITING_STATUS_ROLE", grant_to=VALIDATOR_EXIT_VERIFIER, ) - ]) + ] ), - ( - "21. Grant SR role REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE to TWG", - agent_forward([ + # "21. Grant SR role REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE to TWG", + agent_forward( + [ encode_oz_grant_role( contract=contracts.staking_router, role_name="REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE", - grant_to=interface.TriggerableWithdrawalsGateway(TRIGGERABLE_WITHDRAWALS_GATEWAY), # FIXME: simply use the address + grant_to=interface.TriggerableWithdrawalsGateway( + TRIGGERABLE_WITHDRAWALS_GATEWAY + ), # FIXME: simply use the address ) - ]) + ] ), # --- Curated Staking Module and sDVT - ( - "22. Grant APP_MANAGER_ROLE role to the AGENT", - agent_forward([ + # "22. Grant APP_MANAGER_ROLE role to the AGENT", + agent_forward( + [ ( contracts.acl.address, contracts.acl.grantPermission.encode_input( AGENT, ARAGON_KERNEL, - convert.to_uint(web3.keccak(text="APP_MANAGER_ROLE")) # FIXME: no need for to_uint I guess - ) + convert.to_uint(web3.keccak(text="APP_MANAGER_ROLE")), # FIXME: no need for to_uint I guess + ), ) - ]) + ] ), - ( - "23. Update `NodeOperatorsRegistry` implementation", - agent_forward([ + # "23. Update `NodeOperatorsRegistry` implementation", + agent_forward( + [ ( contracts.kernel.address, contracts.kernel.setApp.encode_input( contracts.kernel.APP_BASES_NAMESPACE(), NODE_OPERATORS_REGISTRY_ARAGON_APP_ID, - NODE_OPERATORS_REGISTRY_IMPL - ) + NODE_OPERATORS_REGISTRY_IMPL, + ), ) - ]) + ] ), - ( - "24. Call finalizeUpgrade_v4 on Curated Staking Module", - agent_forward([ + # "24. Call finalizeUpgrade_v4 on Curated Staking Module", + agent_forward( + [ ( interface.NodeOperatorsRegistry(contracts.node_operators_registry).address, interface.NodeOperatorsRegistry(contracts.node_operators_registry).finalizeUpgrade_v4.encode_input( NOR_EXIT_DEADLINE_IN_SEC - ) + ), ) - ]) + ] ), - ( - "25. Update `SDVT` implementation", - agent_forward([ + # "25. Update `SDVT` implementation", + agent_forward( + [ ( contracts.kernel.address, contracts.kernel.setApp.encode_input( contracts.kernel.APP_BASES_NAMESPACE(), SIMPLE_DVT_ARAGON_APP_ID, - NODE_OPERATORS_REGISTRY_IMPL - ) + NODE_OPERATORS_REGISTRY_IMPL, + ), ) - ]) + ] ), - ( - "26. Call finalizeUpgrade_v4 on SDVT", - agent_forward([ + # "26. Call finalizeUpgrade_v4 on SDVT", + agent_forward( + [ ( interface.NodeOperatorsRegistry(contracts.simple_dvt).address, interface.NodeOperatorsRegistry(contracts.simple_dvt).finalizeUpgrade_v4.encode_input( NOR_EXIT_DEADLINE_IN_SEC - ) + ), ) - ]) + ] ), - ( - "27. Revoke APP_MANAGER_ROLE role from the AGENT", - agent_forward([ + # "27. Revoke APP_MANAGER_ROLE role from the AGENT", + agent_forward( + [ ( contracts.acl.address, contracts.acl.revokePermission.encode_input( AGENT, ARAGON_KERNEL, - convert.to_uint(web3.keccak(text="APP_MANAGER_ROLE")) # FIXME: remove to_uint - ) + convert.to_uint(web3.keccak(text="APP_MANAGER_ROLE")), # FIXME: remove to_uint + ), ) - ]) + ] ), # --- Oracle configs - ( - "28. Grant CONFIG_MANAGER_ROLE role to the AGENT", - agent_forward([ + # "28. Grant CONFIG_MANAGER_ROLE role to the AGENT", + agent_forward( + [ encode_oz_grant_role( contract=contracts.oracle_daemon_config, role_name="CONFIG_MANAGER_ROLE", - grant_to=contracts.agent, # FIXME: misleading usage of contract + grant_to=contracts.agent, # FIXME: misleading usage of contract ) - ]) + ] ), - ( - "29. Remove NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP variable from OracleDaemonConfig", - agent_forward([ + # "29. Remove NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP variable from OracleDaemonConfig", + agent_forward( + [ ( contracts.oracle_daemon_config.address, - contracts.oracle_daemon_config.unset.encode_input('NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP'), + contracts.oracle_daemon_config.unset.encode_input("NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP"), ) - ]) + ] ), - ( - "30. Remove VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS variable from OracleDaemonConfig", - agent_forward([ + # "30. Remove VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS variable from OracleDaemonConfig", + agent_forward( + [ ( contracts.oracle_daemon_config.address, - contracts.oracle_daemon_config.unset.encode_input('VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS'), + contracts.oracle_daemon_config.unset.encode_input("VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS"), ) - ]) + ] ), - ( - "31. Remove VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS variable from OracleDaemonConfig", - agent_forward([ + # "31. Remove VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS variable from OracleDaemonConfig", + agent_forward( + [ ( contracts.oracle_daemon_config.address, - contracts.oracle_daemon_config.unset.encode_input('VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS'), + contracts.oracle_daemon_config.unset.encode_input("VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS"), ) - ]) + ] ), - ( - "32. Add EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS variable to OracleDaemonConfig", - agent_forward([ + # "32. Add EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS variable to OracleDaemonConfig", + agent_forward( + [ ( contracts.oracle_daemon_config.address, - contracts.oracle_daemon_config.set.encode_input('EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS', EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS), + contracts.oracle_daemon_config.set.encode_input( + "EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS", EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS + ), ) - ]) + ] ), - ( - "33. Revoke CONFIG_MANAGER_ROLE role from the AGENT", - agent_forward([ + # "33. Revoke CONFIG_MANAGER_ROLE role from the AGENT", + agent_forward( + [ encode_oz_revoke_role( contract=contracts.oracle_daemon_config, role_name="CONFIG_MANAGER_ROLE", - revoke_from=contracts.agent, # FIXME: typing says its str + revoke_from=contracts.agent, # FIXME: typing says its str ) - ]) + ] ), # --- CSM - ( - "34. Upgrade CSM implementation on proxy", - agent_forward([ + # "34. Upgrade CSM implementation on proxy", + agent_forward( + [ encode_proxy_upgrade_to( contracts.csm, CSM_IMPL_V2_ADDRESS, ) - ]) + ] ), - ( - "35. Call `finalizeUpgradeV2()` on CSM contract", - agent_forward([ + # "35. Call `finalizeUpgradeV2()` on CSM contract", + agent_forward( + [ ( contracts.csm.address, contracts.csm.finalizeUpgradeV2.encode_input(), ) - ]) + ] ), - ( - "36. Upgrade CSAccounting implementation on proxy", - agent_forward([ + # "36. Upgrade CSAccounting implementation on proxy", + agent_forward( + [ encode_proxy_upgrade_to( contracts.cs_accounting, CS_ACCOUNTING_IMPL_V2_ADDRESS, ) - ]) + ] ), - ( - "37. Call `finalizeUpgradeV2(bondCurves)` on CSAccounting contract", - agent_forward([ + # "37. Call `finalizeUpgradeV2(bondCurves)` on CSAccounting contract", + agent_forward( + [ ( contracts.cs_accounting.address, contracts.cs_accounting.finalizeUpgradeV2.encode_input(CS_CURVES), ) - ]) + ] ), - ( - "38. Upgrade CSFeeOracle implementation on proxy", - agent_forward([ + # "38. Upgrade CSFeeOracle implementation on proxy", + agent_forward( + [ encode_proxy_upgrade_to( contracts.cs_fee_oracle, CS_FEE_ORACLE_IMPL_V2_ADDRESS, ) - ]) + ] ), - ( - "39. Call `finalizeUpgradeV2(consensusVersion)` on CSFeeOracle contract", - agent_forward([ + # "39. Call `finalizeUpgradeV2(consensusVersion)` on CSFeeOracle contract", + agent_forward( + [ ( contracts.cs_fee_oracle.address, contracts.cs_fee_oracle.finalizeUpgradeV2.encode_input(CSM_CONSENSUS_VERSION), ) - ]) + ] ), - ( - "40. Upgrade CSFeeDistributor implementation on proxy", - agent_forward([ + # "40. Upgrade CSFeeDistributor implementation on proxy", + agent_forward( + [ encode_proxy_upgrade_to( contracts.cs_fee_distributor, CS_FEE_DISTRIBUTOR_IMPL_V2_ADDRESS, ) - ]) + ] ), - ( - "41. Call `finalizeUpgradeV2(admin)` on CSFeeDistributor contract", - agent_forward([ + # "41. Call `finalizeUpgradeV2(admin)` on CSFeeDistributor contract", + agent_forward( + [ ( contracts.cs_fee_distributor.address, contracts.cs_fee_distributor.finalizeUpgradeV2.encode_input(contracts.agent), ) - ]) + ] ), - ( - "42. Revoke CSAccounting role SET_BOND_CURVE_ROLE from the CSM contract", - agent_forward([ + # "42. Revoke CSAccounting role SET_BOND_CURVE_ROLE from the CSM contract", + agent_forward( + [ encode_oz_revoke_role( contract=contracts.cs_accounting, role_name="SET_BOND_CURVE_ROLE", revoke_from=contracts.csm, ) - ]) + ] ), - ( - "43. Revoke CSAccounting role RESET_BOND_CURVE_ROLE from the CSM contract", - agent_forward([ + # "43. Revoke CSAccounting role RESET_BOND_CURVE_ROLE from the CSM contract", + agent_forward( + [ encode_oz_revoke_role( contract=contracts.cs_accounting, role_name="RESET_BOND_CURVE_ROLE", revoke_from=contracts.csm, ) - ]) + ] ), - ( - "44. Revoke CSAccounting role RESET_BOND_CURVE_ROLE from the CSM committee", - agent_forward([ + # "44. Revoke CSAccounting role RESET_BOND_CURVE_ROLE from the CSM committee", + agent_forward( + [ encode_oz_revoke_role( contract=contracts.cs_accounting, role_name="RESET_BOND_CURVE_ROLE", revoke_from=CSM_COMMITTEE_MS, ) - ]) + ] ), - ( - "45. Grant CSM role CREATE_NODE_OPERATOR_ROLE for the permissionless gate", - agent_forward([ + # "45. Grant CSM role CREATE_NODE_OPERATOR_ROLE for the permissionless gate", + agent_forward( + [ encode_oz_grant_role( contract=contracts.csm, role_name="CREATE_NODE_OPERATOR_ROLE", grant_to=CS_PERMISSIONLESS_GATE_ADDRESS, ) - ]) + ] ), - ( - "46. Grant CSM role CREATE_NODE_OPERATOR_ROLE for the vetted gate", - agent_forward([ + # "46. Grant CSM role CREATE_NODE_OPERATOR_ROLE for the vetted gate", + agent_forward( + [ encode_oz_grant_role( contract=contracts.csm, role_name="CREATE_NODE_OPERATOR_ROLE", grant_to=CS_VETTED_GATE_ADDRESS, ) - ]) + ] ), - ( - "47. Grant CSAccounting role SET_BOND_CURVE_ROLE for the vetted gate", - agent_forward([ + # "47. Grant CSAccounting role SET_BOND_CURVE_ROLE for the vetted gate", + agent_forward( + [ encode_oz_grant_role( contract=contracts.cs_accounting, role_name="SET_BOND_CURVE_ROLE", grant_to=CS_VETTED_GATE_ADDRESS, ) - ]) + ] ), - ( - "48. Revoke role VERIFIER_ROLE from the previous instance of the Verifier contract", - agent_forward([ + # "48. Revoke role VERIFIER_ROLE from the previous instance of the Verifier contract", + agent_forward( + [ encode_oz_revoke_role( contract=contracts.csm, role_name="VERIFIER_ROLE", revoke_from=contracts.cs_verifier, ) - ]) + ] ), - ( - "49. Grant role VERIFIER_ROLE to the new instance of the Verifier contract", - agent_forward([ + # "49. Grant role VERIFIER_ROLE to the new instance of the Verifier contract", + agent_forward( + [ encode_oz_grant_role( contract=contracts.csm, role_name="VERIFIER_ROLE", grant_to=CS_VERIFIER_V2_ADDRESS, ) - ]) + ] ), - ( - "50. Revoke CSM role PAUSE_ROLE from the previous GateSeal instance", - agent_forward([ + # "50. Revoke CSM role PAUSE_ROLE from the previous GateSeal instance", + agent_forward( + [ encode_oz_revoke_role( contract=contracts.csm, role_name="PAUSE_ROLE", revoke_from=CS_GATE_SEAL_ADDRESS, ) - ]) + ] ), - ( - "51. Revoke CSAccounting role PAUSE_ROLE from the previous GateSeal instance", - agent_forward([ + # "51. Revoke CSAccounting role PAUSE_ROLE from the previous GateSeal instance", + agent_forward( + [ encode_oz_revoke_role( contract=contracts.cs_accounting, role_name="PAUSE_ROLE", revoke_from=CS_GATE_SEAL_ADDRESS, ) - ]) + ] ), - ( - "52. Revoke CSFeeOracle role PAUSE_ROLE from the previous GateSeal instance", - agent_forward([ + # "52. Revoke CSFeeOracle role PAUSE_ROLE from the previous GateSeal instance", + agent_forward( + [ encode_oz_revoke_role( contract=contracts.cs_fee_oracle, role_name="PAUSE_ROLE", revoke_from=CS_GATE_SEAL_ADDRESS, ) - ]) + ] ), - ( - "53. Grant CSM role PAUSE_ROLE for the new GateSeal instance", - agent_forward([ + # "53. Grant CSM role PAUSE_ROLE for the new GateSeal instance", + agent_forward( + [ encode_oz_grant_role( contract=contracts.csm, role_name="PAUSE_ROLE", grant_to=CS_GATE_SEAL_V2_ADDRESS, ) - ]) + ] ), - ( - "54. Grant CSAccounting role PAUSE_ROLE for the new GateSeal instance", - agent_forward([ + # "54. Grant CSAccounting role PAUSE_ROLE for the new GateSeal instance", + agent_forward( + [ encode_oz_grant_role( contract=contracts.cs_accounting, role_name="PAUSE_ROLE", grant_to=CS_GATE_SEAL_V2_ADDRESS, ) - ]) + ] ), - ( - "55. Grant CSFeeOracle role PAUSE_ROLE for the new GateSeal instance", - agent_forward([ + # "55. Grant CSFeeOracle role PAUSE_ROLE for the new GateSeal instance", + agent_forward( + [ encode_oz_grant_role( contract=contracts.cs_fee_oracle, role_name="PAUSE_ROLE", grant_to=CS_GATE_SEAL_V2_ADDRESS, ) - ]) + ] ), - ( - "56. Grant MANAGE_BOND_CURVES_ROLE to the AGENT", - agent_forward([ + # "56. Grant MANAGE_BOND_CURVES_ROLE to the AGENT", + agent_forward( + [ encode_oz_grant_role( contract=contracts.cs_accounting, role_name="MANAGE_BOND_CURVES_ROLE", grant_to=contracts.agent, ) - ]) + ] ), - ( - "57. Add Identified Community Stakers Gate Bond Curve", - agent_forward([ + # "57. Add Identified Community Stakers Gate Bond Curve", + agent_forward( + [ ( contracts.cs_accounting.address, contracts.cs_accounting.addBondCurve.encode_input(CS_ICS_GATE_BOND_CURVE), ) - ]) + ] ), - ( - "58. Revoke MANAGE_BOND_CURVES_ROLE from the AGENT", - agent_forward([ + # "58. Revoke MANAGE_BOND_CURVES_ROLE from the AGENT", + agent_forward( + [ encode_oz_revoke_role( contract=contracts.cs_accounting, role_name="MANAGE_BOND_CURVES_ROLE", revoke_from=contracts.agent, ) - ]) - ), - ( - "59. Increase CSM share in Staking Router from 15% to 16%", - agent_forward([encode_staking_router_update_csm_module_share()]) + ] ), + # "59. Increase CSM share in Staking Router from 15% to 16%", + agent_forward([encode_staking_router_update_csm_module_share()]), # --- Gate Seals - ( - "60. Revoke PAUSE_ROLE on WithdrawalQueue from the old GateSeal", - agent_forward([ + # "60. Revoke PAUSE_ROLE on WithdrawalQueue from the old GateSeal", + agent_forward( + [ encode_oz_revoke_role( contract=contracts.withdrawal_queue, role_name="PAUSE_ROLE", revoke_from=OLD_GATE_SEAL_ADDRESS, ) - ]) + ] ), - ( - "61. Revoke PAUSE_ROLE on ValidatorsExitBusOracle from the old GateSeal", - agent_forward([ + # "61. Revoke PAUSE_ROLE on ValidatorsExitBusOracle from the old GateSeal", + agent_forward( + [ encode_oz_revoke_role( contract=contracts.validators_exit_bus_oracle, role_name="PAUSE_ROLE", revoke_from=OLD_GATE_SEAL_ADDRESS, ) - ]) + ] ), - ( - "62. Grant PAUSE_ROLE on WithdrawalQueue to the new WithdrawalQueue GateSeal", - agent_forward([ + # "62. Grant PAUSE_ROLE on WithdrawalQueue to the new WithdrawalQueue GateSeal", + agent_forward( + [ encode_oz_grant_role( contract=contracts.withdrawal_queue, role_name="PAUSE_ROLE", grant_to=NEW_WQ_GATE_SEAL, ) - ]) + ] ), - ( - "63. Grant PAUSE_ROLE on ValidatorsExitBusOracle to the new Triggerable Withdrawals GateSeal", - agent_forward([ + # "63. Grant PAUSE_ROLE on ValidatorsExitBusOracle to the new Triggerable Withdrawals GateSeal", + agent_forward( + [ encode_oz_grant_role( contract=contracts.validators_exit_bus_oracle, role_name="PAUSE_ROLE", grant_to=NEW_TW_GATE_SEAL, ) - ]) + ] ), - ( - "64. Grant PAUSE_ROLE on TriggerableWithdrawalsGateway to the new Triggerable Withdrawals GateSeal", - agent_forward([ + # "64. Grant PAUSE_ROLE on TriggerableWithdrawalsGateway to the new Triggerable Withdrawals GateSeal", + agent_forward( + [ encode_oz_grant_role( contract=interface.TriggerableWithdrawalsGateway(TRIGGERABLE_WITHDRAWALS_GATEWAY), role_name="PAUSE_ROLE", grant_to=NEW_TW_GATE_SEAL, ) - ]) + ] ), - ( - "65. Grant PAUSE_ROLE on TriggerableWithdrawalsGateway to ResealManager", - agent_forward([ + # "65. Grant PAUSE_ROLE on TriggerableWithdrawalsGateway to ResealManager", + agent_forward( + [ encode_oz_grant_role( contract=interface.TriggerableWithdrawalsGateway(TRIGGERABLE_WITHDRAWALS_GATEWAY), role_name="PAUSE_ROLE", grant_to=RESEAL_MANAGER, ) - ]) + ] ), - ( - "66. Grant RESUME_ROLE on TriggerableWithdrawalsGateway to ResealManager", - agent_forward([ + # "66. Grant RESUME_ROLE on TriggerableWithdrawalsGateway to ResealManager", + agent_forward( + [ encode_oz_grant_role( contract=interface.TriggerableWithdrawalsGateway(TRIGGERABLE_WITHDRAWALS_GATEWAY), role_name="RESUME_ROLE", grant_to=RESEAL_MANAGER, ) - ]) + ] ), + ] + dg_call_script = submit_proposals( + [ + ( + dg_items, + "Upgrade to CSM v2 and Triggerable Withdrawals", + ) + ] ) - dg_bypass_item = { - "67. Add CSSetVettedGateTree factory to EasyTrack with permissions": add_evmscript_factory( + vote_desc_items, call_script_items = zip( + (""" +--- Locator +1. Update locator implementation +--- VEB +2. Update VEBO implementation +3. Call finalizeUpgrade_v2(maxValidatorsPerReport, maxExitRequestsLimit, exitsPerFrame, frameDurationInSec) on VEBO +4. Grant VEBO role MANAGE_CONSENSUS_VERSION_ROLE to the AGENT +5. Bump VEBO consensus version to `4` +6. Revoke VEBO role MANAGE_CONSENSUS_VERSION_ROLE from the AGENT +7. Grant SUBMIT_REPORT_HASH_ROLE on Validator Exit Bus Oracle to the EasyTrack EVM Script Executor +--- Triggerable Withdrawals Gateway (TWG) +8. Grant TWG role ADD_FULL_WITHDRAWAL_REQUEST_ROLE to the CS Ejector +9. Grant TWG role ADD_FULL_WITHDRAWAL_REQUEST_ROLE to the VEB +10. Connect TRIGGERABLE_WITHDRAWALS_GATEWAY to Dual Governance tiebreaker +--- WV +11. Update WithdrawalVault implementation +12. Call finalizeUpgrade_v2() on WithdrawalVault +--- AO +13. Update Accounting Oracle implementation +14. Grant AO MANAGE_CONSENSUS_VERSION_ROLE to the AGENT +15. Bump AO consensus version to `4` +16. Revoke AO MANAGE_CONSENSUS_VERSION_ROLE from the AGENT +17. Call finalizeUpgrade_v3() on AO +--- SR +18. Update SR implementation +19. Call finalizeUpgrade_v3() on SR +20. Grant SR role REPORT_VALIDATOR_EXITING_STATUS_ROLE to ValidatorExitVerifier +21. Grant SR role REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE to TWG +--- Curated Staking Module +22. Grant APP_MANAGER_ROLE role to the AGENT on Kernel +23. Update `NodeOperatorsRegistry` implementation +24. Call finalizeUpgrade_v4 on Curated Staking Module +--- sDVT +25. Update `SimpleDVT` implementation +26. Call finalizeUpgrade_v4 on sDVT +27. Revoke APP_MANAGER_ROLE role from the AGENT on Kernel +--- Oracle configs --- +28. Grant CONFIG_MANAGER_ROLE role to the AGENT +29. Remove NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP variable from OracleDaemonConfig +30. Remove VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS variable from OracleDaemonConfig +31. Remove VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS variable from OracleDaemonConfig +32. Add EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS variable to OracleDaemonConfig +33. Revoke CONFIG_MANAGER_ROLE role from the AGENT +--- CSM --- +34. Upgrade CSM implementation on proxy +35. Call `finalizeUpgradeV2()` on CSM contract +36. Upgrade CSAccounting implementation on proxy +37. Call `finalizeUpgradeV2(bondCurves)` on CSAccounting contract +38. Upgrade CSFeeOracle implementation on proxy +39. Call `finalizeUpgradeV2(consensusVersion)` on CSFeeOracle contract +40. Upgrade CSFeeDistributor implementation on proxy +41. Call `finalizeUpgradeV2(admin)` on CSFeeDistributor contract +42. Revoke CSAccounting role SET_BOND_CURVE_ROLE from the CSM contract +43. Revoke CSAccounting role RESET_BOND_CURVE_ROLE from the CSM contract +44. Revoke CSAccounting role RESET_BOND_CURVE_ROLE from the CSM committee +45. Grant CSM role CREATE_NODE_OPERATOR_ROLE for the permissionless gate +46. Grant CSM role CREATE_NODE_OPERATOR_ROLE for the vetted gate +47. Grant CSAccounting role SET_BOND_CURVE_ROLE for the vetted gate +48. Revoke role VERIFIER_ROLE from the previous instance of the Verifier contract +49. Grant role VERIFIER_ROLE to the new instance of the Verifier contract +50. Revoke CSM role PAUSE_ROLE from the previous GateSeal instance +51. Revoke CSAccounting role PAUSE_ROLE from the previous GateSeal instance +52. Revoke CSFeeOracle role PAUSE_ROLE from the previous GateSeal instance +53. Grant CSM role PAUSE_ROLE for the new GateSeal instance +54. Grant CSAccounting role PAUSE_ROLE for the new GateSeal instance +55. Grant CSFeeOracle role PAUSE_ROLE for the new GateSeal instance +56. Grant MANAGE_BOND_CURVES_ROLE to the AGENT +57. Add Identified Community Stakers Gate Bond Curve +58. Revoke MANAGE_BOND_CURVES_ROLE from the AGENT +59. Increase CSM share in Staking Router from 15% to 16% +--- Gate Seals --- +60. Revoke PAUSE_ROLE on WithdrawalQueue from the old GateSeal +61. Revoke PAUSE_ROLE on ValidatorsExitBusOracle from the old GateSeal +62. Grant PAUSE_ROLE on WithdrawalQueue to the new WithdrawalQueue GateSeal +63. Grant PAUSE_ROLE on ValidatorsExitBusOracle to the new Triggerable Withdrawals GateSeal +64. Grant PAUSE_ROLE on TriggerableWithdrawalsGateway to the new Triggerable Withdrawals GateSeal +--- ResealManager --- +65. Grant PAUSE_ROLE on TriggerableWithdrawalsGateway to ResealManager +66. Grant RESUME_ROLE on TriggerableWithdrawalsGateway to ResealManager""", dg_call_script[0]), + ( + "67. Add CSSetVettedGateTree factory to EasyTrack with permissions", + add_evmscript_factory( factory=EASYTRACK_CS_SET_VETTED_GATE_TREE_FACTORY, permissions=(create_permissions(interface.CSVettedGate(CS_VETTED_GATE_ADDRESS), "setTreeParams")), ), - "68. Add `SubmitValidatorsExitRequestHashes` (SDVT) EVM script factory to Easy Track": add_evmscript_factory( + ), + ( + "68. Add `SubmitValidatorsExitRequestHashes` (SDVT) EVM script factory to Easy Track", + add_evmscript_factory( factory=EASYTRACK_SDVT_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY, permissions=(create_permissions(contracts.validators_exit_bus_oracle, "submitExitRequestsHash")), ), - "69. Add `SubmitValidatorsExitRequestHashes` (Curated Module) EVM script factory to Easy Track": add_evmscript_factory( + ), + ( + "69. Add `SubmitValidatorsExitRequestHashes` (Curated Module) EVM script factory to Easy Track", + add_evmscript_factory( factory=EASYTRACK_CURATED_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY, permissions=(create_permissions(contracts.validators_exit_bus_oracle, "submitExitRequestsHash")), - ) - } + ), + ), + ) + + return vote_desc_items, call_script_items - if silent: - desc_ipfs = calculate_vote_ipfs_description(DESCRIPTION) - else: - desc_ipfs = upload_vote_ipfs_description(DESCRIPTION) - dg_desc = "\n".join(vote_desc_items) +def start_vote(tx_params: Dict[str, str], silent: bool = False): + vote_desc_items, call_script_items = get_vote_items() + vote_items = bake_vote_items(list(vote_desc_items), list(call_script_items)) - dg_vote = prepare_proposal(call_script_items, dg_desc) - vote_items = {dg_desc: dg_vote, **dg_bypass_item} + desc_ipfs = ( + calculate_vote_ipfs_description(IPFS_DESCRIPTION) if silent else upload_vote_ipfs_description(IPFS_DESCRIPTION) + ) assert confirm_vote_script(vote_items, silent, desc_ipfs) return create_vote(vote_items, tx_params, desc_ipfs=desc_ipfs) + def prepare_proposal( call_script: Sequence[Tuple], description: Optional[str] = "", @@ -888,13 +981,23 @@ def prepare_proposal( dual_governance.submitProposal.encode_input([(_call[0], 0, _call[1]) for _call in forwarded], description), ) + def main(): - tx_params: dict = {"from": get_deployer_account()} + tx_params: Dict[str, str] = {"from": get_deployer_account().address} if get_is_live(): tx_params["priority_fee"] = get_priority_fee() vote_id, _ = start_vote(tx_params=tx_params, silent=False) - vote_id >= 0 and print(f"Vote created: {vote_id}.") time.sleep(5) # hack for waiting thread #2. + + +def start_and_execute_vote_on_fork_manual(): + if get_is_live(): + raise Exception("This script is for local testing only.") + + tx_params = {"from": get_deployer_account()} + vote_id, _ = start_vote(tx_params=tx_params, silent=True) + print(f"Vote created: {vote_id}.") + pass_and_exec_dao_vote(int(vote_id), step_by_step=True) From c275e5e2cdbc1af9c21ad56be692e3df8a0531da Mon Sep 17 00:00:00 2001 From: hweawer Date: Mon, 15 Sep 2025 10:41:44 +0200 Subject: [PATCH 17/28] Remove redundant function from the vote --- scripts/vote_tw_csm2_mainnet.py | 33 ++++++++------------------------- 1 file changed, 8 insertions(+), 25 deletions(-) diff --git a/scripts/vote_tw_csm2_mainnet.py b/scripts/vote_tw_csm2_mainnet.py index e16927158..d6d05df4d 100644 --- a/scripts/vote_tw_csm2_mainnet.py +++ b/scripts/vote_tw_csm2_mainnet.py @@ -122,15 +122,15 @@ # ============================== Addresses =================================== # New core contracts implementations -LIDO_LOCATOR_IMPL = "0x003f20CD17e7683A7F88A7AfF004f0C44F0cfB31" -ACCOUNTING_ORACLE_IMPL = "0x2341c9BE0E639f262f8170f9ef1efeCC92cCF617" -VALIDATORS_EXIT_BUS_ORACLE_IMPL = "0x7E6d9C9C44417bf2EaF69685981646e9752D623A" -WITHDRAWAL_VAULT_IMPL = "0xfe7A58960Af333eAdeAeC39149F9d6A71dc3E668" -STAKING_ROUTER_IMPL = "0xd5F04A81ac472B2cB32073CE9dDABa6FaF022827" -NODE_OPERATORS_REGISTRY_IMPL = "0x95F00b016bB31b7182D96D25074684518246E42a" +LIDO_LOCATOR_IMPL = "0x2C298963FB763f74765829722a1ebe0784f4F5Cf" +ACCOUNTING_ORACLE_IMPL = "0xE9906E543274cebcd335d2C560094089e9547e8d" +VALIDATORS_EXIT_BUS_ORACLE_IMPL = "0x905A211eD6830Cfc95643f0bE2ff64E7f3bf9b94" +WITHDRAWAL_VAULT_IMPL = "0x7D2BAa6094E1C4B60Da4cbAF4A77C3f4694fD53D" +STAKING_ROUTER_IMPL = "0x226f9265CBC37231882b7409658C18bB7738173A" +NODE_OPERATORS_REGISTRY_IMPL = "0x6828b023e737f96B168aCd0b5c6351971a4F81aE" -TRIGGERABLE_WITHDRAWALS_GATEWAY = "0x6679090D92b08a2a686eF8614feECD8cDFE209db" -VALIDATOR_EXIT_VERIFIER = "0xFd4386A8795956f4B6D01cbb6dB116749731D7bD" +TRIGGERABLE_WITHDRAWALS_GATEWAY = "0xDC00116a0D3E064427dA2600449cfD2566B3037B" +VALIDATOR_EXIT_VERIFIER = "0xbDb567672c867DB533119C2dcD4FB9d8b44EC82f" # Oracle consensus versions AO_CONSENSUS_VERSION = 4 @@ -965,23 +965,6 @@ def start_vote(tx_params: Dict[str, str], silent: bool = False): return create_vote(vote_items, tx_params, desc_ipfs=desc_ipfs) -def prepare_proposal( - call_script: Sequence[Tuple], - description: Optional[str] = "", -) -> Tuple[str, str]: - dual_governance = contracts.dual_governance - forwarded = [] - - for _call in call_script: - forwarded.append((_call[0], _call[1])) - - print(f"Forwarding call script to dual governance: {forwarded}") - return ( - contracts.dual_governance.address, - dual_governance.submitProposal.encode_input([(_call[0], 0, _call[1]) for _call in forwarded], description), - ) - - def main(): tx_params: Dict[str, str] = {"from": get_deployer_account().address} if get_is_live(): From 28e988583d417cca2eaeea9a92430810e234d316 Mon Sep 17 00:00:00 2001 From: hweawer Date: Mon, 15 Sep 2025 11:29:59 +0200 Subject: [PATCH 18/28] Update voting tests structure --- tests/test_vote_tw_csm2_mainnet.py | 1709 +++++++++++++++------------- 1 file changed, 892 insertions(+), 817 deletions(-) diff --git a/tests/test_vote_tw_csm2_mainnet.py b/tests/test_vote_tw_csm2_mainnet.py index 327e3adcd..4abeb1246 100644 --- a/tests/test_vote_tw_csm2_mainnet.py +++ b/tests/test_vote_tw_csm2_mainnet.py @@ -1,17 +1,34 @@ from typing import Optional +from brownie import chain, interface +from brownie.network.transaction import TransactionReceipt + +from utils.test.tx_tracing_helpers import ( + count_vote_items_by_events, + display_dg_events, + display_voting_events, + group_voting_events_from_receipt, + group_dg_events_from_receipt, +) +from utils.evm_script import encode_call_script +from utils.voting import find_metadata_by_vote_id +from utils.ipfs import get_lido_vote_cid_from_str +from utils.dual_governance import PROPOSAL_STATUS +from utils.test.event_validators.dual_governance import validate_dual_governance_submit_event from brownie.exceptions import VirtualMachineError -from scripts.vote_tw_csm2_mainnet import start_vote from brownie import interface, reverts, chain, convert, web3, ZERO_ADDRESS # type: ignore from brownie.network.event import EventDict from utils.easy_track import create_permissions +from utils.evm_script import encode_call_script +from utils.voting import find_metadata_by_vote_id +from utils.ipfs import get_lido_vote_cid_from_str +from utils.dual_governance import PROPOSAL_STATUS +from utils.test.event_validators.dual_governance import validate_dual_governance_submit_event from utils.test.tx_tracing_helpers import group_voting_events_from_receipt, group_dg_events_from_receipt from utils.test.event_validators.easy_track import validate_evmscript_factory_added_event, EVMScriptFactoryAdded from utils.test.event_validators.dual_governance import validate_dual_governance_submit_event from utils.dual_governance import wait_for_noon_utc_to_satisfy_time_constrains from utils.config import ( - DUAL_GOVERNANCE, - TIMELOCK, DUAL_GOVERNANCE_EXECUTORS, LDO_HOLDER_ADDRESS_FOR_TESTS, CS_MODULE_ID, @@ -23,7 +40,6 @@ CSM_COMMITTEE_MS, ARAGON_KERNEL, AGENT, - VOTING, contracts, ) @@ -154,6 +170,20 @@ def check_proxy_implementation(proxy_address, expected_impl): actual_impl = get_ossifiable_proxy_impl(proxy_address) assert actual_impl == expected_impl, f"Expected impl {expected_impl}, got {actual_impl}" +# ============================================================================ +# ============================== Import vote ================================= +# ============================================================================ +from scripts.vote_tw_csm2_mainnet import start_vote, get_vote_items + + +# ============================================================================ +# ============================== Constants =================================== +# ============================================================================ +VOTING = "0x2e59A20f205bB85a89C53f1936454680651E618e" +EMERGENCY_PROTECTED_TIMELOCK = "0xCE0425301C85c5Ea2A0873A2dEe44d78E02D2316" +DUAL_GOVERNANCE = "0xcdF49b058D606AD34c5789FD8c3BF8B3E54bA2db" +DUAL_GOVERNANCE_ADMIN_EXECUTOR = "" +AGENT = "" # New core contracts implementations LIDO_LOCATOR_IMPL = "0x003f20CD17e7683A7F88A7AfF004f0C44F0cfB31" @@ -215,8 +245,14 @@ def check_proxy_implementation(proxy_address, expected_impl): EASYTRACK_CS_SET_VETTED_GATE_TREE_FACTORY = "0xa890fc73e1b771Ee6073e2402E631c312FF92Cd9" +EXPECTED_VOTE_ID = None +EXPECTED_DG_PROPOSAL_ID = 1 +EXPECTED_VOTE_EVENTS_COUNT = 66 +EXPECTED_DG_EVENTS_COUNT = 1 +IPFS_DESCRIPTION_HASH = "" -def test_tw_vote(helpers, accounts, vote_ids_from_env, stranger): + +def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_governance_proposal_calls): # Save original implementations for comparison locator_impl_before = get_ossifiable_proxy_impl(contracts.lido_locator) accounting_oracle_impl_before = get_ossifiable_proxy_impl(contracts.accounting_oracle) @@ -229,7 +265,8 @@ def test_tw_vote(helpers, accounts, vote_ids_from_env, stranger): cs_fee_oracle_impl_before = get_ossifiable_proxy_impl(contracts.cs_fee_oracle.address) cs_fee_distributor_impl_before = get_ossifiable_proxy_impl(contracts.cs_fee_distributor.address) - timelock = interface.EmergencyProtectedTimelock(TIMELOCK) + voting = interface.Voting(VOTING) + timelock = interface.EmergencyProtectedTimelock(EMERGENCY_PROTECTED_TIMELOCK) dual_governance = interface.DualGovernance(DUAL_GOVERNANCE) # Not yet used by the protocol, but needed for the test @@ -239,835 +276,873 @@ def test_tw_vote(helpers, accounts, vote_ids_from_env, stranger): cs_vetted_gate = interface.CSVettedGate(CS_VETTED_GATE_ADDRESS) cs_verifier_v2 = interface.CSVerifierV2(CS_VERIFIER_V2_ADDRESS) - # --- Initial state checks --- - - # Step 1: Check Lido Locator implementation initial state - assert locator_impl_before != LIDO_LOCATOR_IMPL, "Locator implementation should be different before upgrade" - - # Step 2: Check VEBO implementation initial state - assert vebo_impl_before != VALIDATORS_EXIT_BUS_ORACLE_IMPL, "VEBO implementation should be different before upgrade" - - # Step 3: Check VEBO finalizeUpgrade_v2 state - try: # FIXME: with reverts - assert contracts.validators_exit_bus_oracle.getMaxValidatorsPerReport() != 600, "VEBO max validators per report should not be 600 before upgrade" # FIXME: magic number - except Exception: - pass # Function might not exist yet - - # Steps 4-6: Check VEBO consensus version management - initial_vebo_consensus_version = contracts.validators_exit_bus_oracle.getConsensusVersion() - assert initial_vebo_consensus_version < VEBO_CONSENSUS_VERSION, f"VEBO consensus version should be less than {VEBO_CONSENSUS_VERSION}" - # FIXME: Why no check for the role SUBMIT_REPORT_HASH_ROLE? - - # Step 7: Check TWG role for CS Ejector initial state - add_full_withdrawal_request_role = triggerable_withdrawals_gateway.ADD_FULL_WITHDRAWAL_REQUEST_ROLE() - assert not triggerable_withdrawals_gateway.hasRole(add_full_withdrawal_request_role, cs_ejector), "CS Ejector should not have ADD_FULL_WITHDRAWAL_REQUEST_ROLE before upgrade" - - # Step 8: Check TWG role for VEB initial state - assert not triggerable_withdrawals_gateway.hasRole(add_full_withdrawal_request_role, contracts.validators_exit_bus_oracle), "VEBO should not have ADD_FULL_WITHDRAWAL_REQUEST_ROLE before upgrade" - - # Step 9: Check EasyTrack VEB SUBMIT_REPORT_HASH_ROLE initial state - submit_report_hash_role = web3.keccak(text="SUBMIT_REPORT_HASH_ROLE") - assert not contracts.validators_exit_bus_oracle.hasRole(submit_report_hash_role, EASYTRACK_EVMSCRIPT_EXECUTOR), "EasyTrack executor should not have SUBMIT_REPORT_HASH_ROLE on VEBO before upgrade" - - # Step 10: Check DualGovernance tiebreaker initial state - tiebreaker_details = contracts.dual_governance.getTiebreakerDetails() - initial_tiebreakers = tiebreaker_details[3] # sealableWithdrawalBlockers - assert TRIGGERABLE_WITHDRAWALS_GATEWAY not in initial_tiebreakers, "TWG should not be in tiebreaker list before upgrade" - - # Step 9: Check Withdrawal Vault implementation initial state - assert withdrawal_vault_impl_before != WITHDRAWAL_VAULT_IMPL, "Withdrawal Vault implementation should be different before upgrade" - - # Step 10: Withdrawal Vault finalizeUpgrade_v2 check is done post-execution - assert contracts.withdrawal_vault.getContractVersion() == 1, "Withdrawal Vault version should be 1 before upgrade" - - # Step 11: Check Accounting Oracle implementation initial state - assert accounting_oracle_impl_before != ACCOUNTING_ORACLE_IMPL, "Accounting Oracle implementation should be different before upgrade" - - # Steps 12-14: Check AO consensus version management - initial_ao_consensus_version = contracts.accounting_oracle.getConsensusVersion() - assert initial_ao_consensus_version < AO_CONSENSUS_VERSION, f"AO consensus version should be less than {AO_CONSENSUS_VERSION}" - assert not contracts.accounting_oracle.hasRole(contracts.accounting_oracle.MANAGE_CONSENSUS_VERSION_ROLE(), contracts.agent), "Agent should not have MANAGE_CONSENSUS_VERSION_ROLE on AO before upgrade" - - # Step 17: Check AO version before finalizeUpgrade_v3 - assert contracts.accounting_oracle.getContractVersion() == 2, "AO contract version should be 2 before finalizeUpgrade_v3" - - # Step 15: Check Staking Router implementation initial state - assert staking_router_impl_before != STAKING_ROUTER_IMPL, "Staking Router implementation should be different before upgrade" - - # Steps 16-17: Check SR roles initial state - try: - report_validator_exiting_status_role = contracts.staking_router.REPORT_VALIDATOR_EXITING_STATUS_ROLE() - report_validator_exit_triggered_role = contracts.staking_router.REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE() - except Exception as e: - assert "Unknown typed error: 0x" in str(e), f"Unexpected error: {e}" - report_validator_exiting_status_role = ZERO_ADDRESS - report_validator_exit_triggered_role = ZERO_ADDRESS - - assert report_validator_exiting_status_role == ZERO_ADDRESS, "REPORT_VALIDATOR_EXITING_STATUS_ROLE should not exist before upgrade" - assert report_validator_exit_triggered_role == ZERO_ADDRESS, "REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE should not exist before upgrade" - - # Step 18: Check APP_MANAGER_ROLE initial state - app_manager_role = web3.keccak(text="APP_MANAGER_ROLE") - assert contracts.acl.getPermissionManager(ARAGON_KERNEL, app_manager_role) == AGENT, "AGENT should be the permission manager for APP_MANAGER_ROLE" - assert contracts.node_operators_registry.kernel() == ARAGON_KERNEL, "Node Operators Registry must use the correct kernel" - assert not contracts.acl.hasPermission(VOTING, ARAGON_KERNEL, app_manager_role), "VOTING should not have APP_MANAGER_ROLE before the upgrade" - assert not contracts.acl.hasPermission(AGENT, ARAGON_KERNEL, app_manager_role), "AGENT should not have APP_MANAGER_ROLE before the upgrade" - - # Steps 19-23: Check NOR and sDVT initial state - assert not contracts.acl.hasPermission(contracts.agent, contracts.kernel, app_manager_role), "Agent should not have APP_MANAGER_ROLE before upgrade" - assert contracts.node_operators_registry.getContractVersion() == 3, "Node Operators Registry version should be 3 before upgrade" - assert contracts.simple_dvt.getContractVersion() == 3, "Simple DVT version should be 3 before upgrade" - - # Step 24: Check CONFIG_MANAGER_ROLE initial state - config_manager_role = contracts.oracle_daemon_config.CONFIG_MANAGER_ROLE() - assert not contracts.oracle_daemon_config.hasRole(config_manager_role, contracts.agent), "Agent should not have CONFIG_MANAGER_ROLE on Oracle Daemon Config before upgrade" - - # Steps 25-27: Check Oracle Daemon Config variables to be removed - try: - contracts.oracle_daemon_config.get('NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP') - contracts.oracle_daemon_config.get('VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS') - contracts.oracle_daemon_config.get('VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS') - except Exception as e: - assert False, f"Expected variables to exist before removal: {e}" - - # Step 28: Check that EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS doesn't exist yet - try: - contracts.oracle_daemon_config.get('EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS') - assert False, "EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS should not exist before vote" - except Exception: - pass # Expected to fail - - # Step 29: Check CSM implementation initial state - assert csm_impl_before != CSM_IMPL_V2_ADDRESS, "CSM implementation should be different before vote" - - # Step 30: Check CSM finalizeUpgradeV2 initial state - with reverts(): - # The function should not exist yet - contracts.csm.getInitializedVersion() - - # CSM Step 32: Check CSAccounting implementation (pre-vote state) - assert cs_accounting_impl_before != CS_ACCOUNTING_IMPL_V2_ADDRESS, "CSAccounting implementation should be different before vote" - - # CSM Step 33: Check CSAccounting finalizeUpgradeV2 was not called (pre-vote state) - with reverts(): - # The function should not exist yet - contracts.cs_accounting.getInitializedVersion() - - # CSM Step 34: Check CSFeeOracle implementation (pre-vote state) - assert cs_fee_oracle_impl_before != CS_FEE_ORACLE_IMPL_V2_ADDRESS, "CSFeeOracle implementation should be different before vote" - - # CSM Step 35: Check CSFeeOracle finalizeUpgradeV2 was not called (pre-vote state) - assert contracts.cs_fee_oracle.getContractVersion() < CS_FEE_ORACLE_V2_VERSION, f"CSFeeOracle version should be less than {CS_FEE_ORACLE_V2_VERSION} before vote" - assert contracts.cs_fee_oracle.getConsensusVersion() < 3, "CSFeeOracle consensus version should be less than 3 before vote" - - # CSM Step 36: Check CSFeeDistributor implementation (pre-vote state) - assert cs_fee_distributor_impl_before != CS_FEE_DISTRIBUTOR_IMPL_V2_ADDRESS, "CSFeeDistributor implementation should be different before vote" - - # CSM Step 37: Check CSFeeDistributor finalizeUpgradeV2 was not called (pre-vote state) - with reverts(): - # The function should not exist yet - contracts.cs_fee_distributor.getInitializedVersion() - - # CSM Steps 38-40: CSAccounting roles (pre-vote state) - assert contracts.cs_accounting.hasRole(contracts.cs_accounting.SET_BOND_CURVE_ROLE(), contracts.csm.address), "CSM should have SET_BOND_CURVE_ROLE on CSAccounting before vote" - assert contracts.cs_accounting.hasRole(web3.keccak(text="RESET_BOND_CURVE_ROLE"), contracts.csm.address), "CSM should have RESET_BOND_CURVE_ROLE on CSAccounting before vote" - assert contracts.cs_accounting.hasRole(web3.keccak(text="RESET_BOND_CURVE_ROLE"), CSM_COMMITTEE_MS), "CSM committee should have RESET_BOND_CURVE_ROLE on CSAccounting before vote" - - # CSM Steps 41-42: CSM roles (pre-vote state) - assert not contracts.csm.hasRole(web3.keccak(text="CREATE_NODE_OPERATOR_ROLE"), cs_permissionless_gate.address), "Permissionless gate should not have CREATE_NODE_OPERATOR_ROLE on CSM before vote" - assert not contracts.csm.hasRole(web3.keccak(text="CREATE_NODE_OPERATOR_ROLE"), cs_vetted_gate.address), "Vetted gate should not have CREATE_NODE_OPERATOR_ROLE on CSM before vote" - - # CSM Step 43: CSAccounting bond curve role for vetted gate (pre-vote state) - assert not contracts.cs_accounting.hasRole(contracts.cs_accounting.SET_BOND_CURVE_ROLE(), cs_vetted_gate.address), "Vetted gate should not have SET_BOND_CURVE_ROLE on CSAccounting before vote" - - # CSM Steps 44-45: Verifier roles (pre-vote state) - assert contracts.csm.hasRole(contracts.csm.VERIFIER_ROLE(), contracts.cs_verifier.address), "Old verifier should have VERIFIER_ROLE on CSM before vote" - assert not contracts.csm.hasRole(contracts.csm.VERIFIER_ROLE(), cs_verifier_v2.address), "New verifier should not have VERIFIER_ROLE on CSM before vote" - - # CSM Steps 46-51: GateSeal roles (pre-vote state) - assert contracts.csm.hasRole(contracts.csm.PAUSE_ROLE(), CS_GATE_SEAL_ADDRESS), "Old GateSeal should have PAUSE_ROLE on CSM before vote" - assert contracts.cs_accounting.hasRole(contracts.cs_accounting.PAUSE_ROLE(), CS_GATE_SEAL_ADDRESS), "Old GateSeal should have PAUSE_ROLE on CSAccounting before vote" - assert contracts.cs_fee_oracle.hasRole(contracts.cs_fee_oracle.PAUSE_ROLE(), CS_GATE_SEAL_ADDRESS), "Old GateSeal should have PAUSE_ROLE on CSFeeOracle before vote" - - assert not contracts.csm.hasRole(contracts.csm.PAUSE_ROLE(), CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should not have PAUSE_ROLE on CSM before vote" - assert not contracts.cs_accounting.hasRole(contracts.cs_accounting.PAUSE_ROLE(), CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should not have PAUSE_ROLE on CSAccounting before vote" - assert not contracts.cs_fee_oracle.hasRole(contracts.cs_fee_oracle.PAUSE_ROLE(), CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should not have PAUSE_ROLE on CSFeeOracle before vote" - - # CSM Step 52: Staking Router CSM module state before vote (pre-vote state) - csm_module_before = contracts.staking_router.getStakingModule(CS_MODULE_ID) - csm_share_before = csm_module_before['stakeShareLimit'] - csm_priority_exit_threshold_before = csm_module_before['priorityExitShareThreshold'] - assert csm_share_before != CS_MODULE_NEW_TARGET_SHARE_BP, f"CSM share should not be {CS_MODULE_NEW_TARGET_SHARE_BP} before vote, current: {csm_share_before}" - assert csm_priority_exit_threshold_before != CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP, f"CSM priority exit threshold should not be {CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP} before vote, current: {csm_priority_exit_threshold_before}" - - # CSM Step 65: EasyTrack factories before vote (pre-vote state) - initial_factories = contracts.easy_track.getEVMScriptFactories() - assert EASYTRACK_CS_SET_VETTED_GATE_TREE_FACTORY not in initial_factories, "EasyTrack should not have CSMSetVettedGateTree factory before vote" - assert EASYTRACK_SDVT_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY not in initial_factories, "EasyTrack should not have SDVT validator exit request hashes factory before vote" - assert EASYTRACK_CURATED_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY not in initial_factories, "EasyTrack should not have Curated validator exit request hashes factory before vote" - - # Gate Seals: Check initial states before vote - assert contracts.withdrawal_queue.hasRole(contracts.withdrawal_queue.PAUSE_ROLE(), OLD_GATE_SEAL_ADDRESS), "Old GateSeal should have PAUSE_ROLE on WithdrawalQueue before vote" - assert contracts.validators_exit_bus_oracle.hasRole(contracts.validators_exit_bus_oracle.PAUSE_ROLE(), OLD_GATE_SEAL_ADDRESS), "Old GateSeal should have PAUSE_ROLE on VEBO before vote" - assert not contracts.withdrawal_queue.hasRole(contracts.withdrawal_queue.PAUSE_ROLE(), NEW_WQ_GATE_SEAL), "New WQ GateSeal should not have PAUSE_ROLE on WithdrawalQueue before vote" - assert not contracts.validators_exit_bus_oracle.hasRole(contracts.validators_exit_bus_oracle.PAUSE_ROLE(), NEW_TW_GATE_SEAL), "New TW GateSeal should not have PAUSE_ROLE on VEBO before vote" - assert not triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.PAUSE_ROLE(), NEW_TW_GATE_SEAL), "New TW GateSeal should not have PAUSE_ROLE on TWG before vote" - - # ResealManager: Check initial states before vote - assert not triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.PAUSE_ROLE(), RESEAL_MANAGER), "ResealManager should not have PAUSE_ROLE on TWG before vote" - assert not triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.RESUME_ROLE(), RESEAL_MANAGER), "ResealManager should not have RESUME_ROLE on TWG before vote" - + # START VOTE - if len(vote_ids_from_env) > 0: - (vote_id,) = vote_ids_from_env + if vote_ids_from_env: + vote_id = vote_ids_from_env[0] + if EXPECTED_VOTE_ID is not None: + assert vote_id == EXPECTED_VOTE_ID + elif EXPECTED_VOTE_ID is not None and voting.votesLength() > EXPECTED_VOTE_ID: + vote_id = EXPECTED_VOTE_ID else: - tx_params = {"from": LDO_HOLDER_ADDRESS_FOR_TESTS} - vote_id, _ = start_vote(tx_params, silent=True) - - vote_tx = helpers.execute_vote(accounts, vote_id, contracts.voting) - print(f"voteId = {vote_id}") - - proposal_id = vote_tx.events["ProposalSubmitted"][1]["proposalId"] - print(f"proposalId = {proposal_id}") - - chain.sleep(timelock.getAfterSubmitDelay() + 1) - dual_governance.scheduleProposal(proposal_id, {"from": stranger}) - - chain.sleep(timelock.getAfterScheduleDelay() + 1) - wait_for_noon_utc_to_satisfy_time_constrains() - - dg_tx = timelock.execute(proposal_id, {"from": stranger}) - - # --- VALIDATE EXECUTION RESULTS --- - - # Step 1: Validate Lido Locator implementation was updated - assert get_ossifiable_proxy_impl(contracts.lido_locator) == LIDO_LOCATOR_IMPL, "Locator implementation should be updated to the new value" - - # Step 2-3: Validate VEBO implementation was updated and configured - assert get_ossifiable_proxy_impl(contracts.validators_exit_bus_oracle) == VALIDATORS_EXIT_BUS_ORACLE_IMPL, "VEBO implementation should be updated" - assert contracts.validators_exit_bus_oracle.getMaxValidatorsPerReport() == 600, "VEBO max validators per report should be set to 600" - - # Validate exit request limit parameters from finalizeUpgrade_v2 call - # FIXME: Magic numbers. - exit_request_limits = contracts.validators_exit_bus_oracle.getExitRequestLimitFullInfo() - assert exit_request_limits[0] == 11200, "maxExitRequestsLimit should be 11200" - assert exit_request_limits[1] == 1, "exitsPerFrame should be 1" - assert exit_request_limits[2] == 48, "frameDurationInSec should be 48 hours in seconds" - - # Steps 4-6: Validate VEBO consensus version management - assert not contracts.validators_exit_bus_oracle.hasRole(contracts.validators_exit_bus_oracle.MANAGE_CONSENSUS_VERSION_ROLE(), contracts.agent), "Agent should not have MANAGE_CONSENSUS_VERSION_ROLE on VEBO" - assert contracts.validators_exit_bus_oracle.getConsensusVersion() == VEBO_CONSENSUS_VERSION, f"VEBO consensus version should be set to {VEBO_CONSENSUS_VERSION}" - - # Step 7: Validate EasyTrack VEB SUBMIT_REPORT_HASH_ROLE - assert contracts.validators_exit_bus_oracle.hasRole(submit_report_hash_role, EASYTRACK_EVMSCRIPT_EXECUTOR), "EasyTrack executor should have SUBMIT_REPORT_HASH_ROLE on VEBO" - - # Steps 8-9: Validate TWG roles - assert triggerable_withdrawals_gateway.hasRole(add_full_withdrawal_request_role, cs_ejector), "CS Ejector should have ADD_FULL_WITHDRAWAL_REQUEST_ROLE on TWG" - assert triggerable_withdrawals_gateway.hasRole(add_full_withdrawal_request_role, contracts.validators_exit_bus_oracle), "VEBO should have ADD_FULL_WITHDRAWAL_REQUEST_ROLE on TWG" - - # Step 10: Validate DualGovernance tiebreaker connection - final_tiebreaker_details = contracts.dual_governance.getTiebreakerDetails() - final_tiebreakers = final_tiebreaker_details[3] # sealableWithdrawalBlockers - assert TRIGGERABLE_WITHDRAWALS_GATEWAY in final_tiebreakers, "TWG should be in tiebreaker list after upgrade" - - # Steps 11-12: Validate Withdrawal Vault upgrade - assert get_wv_contract_proxy_impl(contracts.withdrawal_vault) == WITHDRAWAL_VAULT_IMPL, "Withdrawal Vault implementation should be updated" - assert contracts.withdrawal_vault.getContractVersion() == 2, "Withdrawal Vault version should be 2 after finalizeUpgrade_v2" - - # Steps 13-16: Validate Accounting Oracle upgrade - assert get_ossifiable_proxy_impl(contracts.accounting_oracle) == ACCOUNTING_ORACLE_IMPL, "Accounting Oracle implementation should be updated" - assert not contracts.accounting_oracle.hasRole(contracts.accounting_oracle.MANAGE_CONSENSUS_VERSION_ROLE(), contracts.agent), "Agent should not have MANAGE_CONSENSUS_VERSION_ROLE on AO" - assert contracts.accounting_oracle.getConsensusVersion() == AO_CONSENSUS_VERSION, f"AO consensus version should be set to {AO_CONSENSUS_VERSION}" - - # Step 17: Validate AO finalizeUpgrade_v3 - assert contracts.accounting_oracle.getContractVersion() == 3, "AO contract version should be 3 after finalizeUpgrade_v3" - - # Steps 18-21: Validate Staking Router upgrade - assert get_ossifiable_proxy_impl(contracts.staking_router) == STAKING_ROUTER_IMPL, "Staking Router implementation should be updated" - assert contracts.staking_router.getContractVersion() == 3, "Staking Router version should be 3 after finalizeUpgrade_v3" - assert contracts.staking_router.hasRole(contracts.staking_router.REPORT_VALIDATOR_EXITING_STATUS_ROLE(), VALIDATOR_EXIT_VERIFIER), "ValidatorExitVerifier should have REPORT_VALIDATOR_EXITING_STATUS_ROLE on SR" - assert contracts.staking_router.hasRole(contracts.staking_router.REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE(), triggerable_withdrawals_gateway), "TWG should have REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE on SR" - - # Steps 22-27: Validate NOR and sDVT updates - assert not contracts.acl.hasPermission(contracts.agent, contracts.kernel, app_manager_role), "Agent should not have APP_MANAGER_ROLE after vote" - assert contracts.node_operators_registry.getContractVersion() == 4, "Node Operators Registry version should be updated to 4" - assert contracts.simple_dvt.getContractVersion() == 4, "Simple DVT version should be updated to 4" - assert contracts.node_operators_registry.exitDeadlineThreshold(0) == NOR_EXIT_DEADLINE_IN_SEC, "NOR exit deadline threshold should be set correctly after finalizeUpgrade_v4" - assert contracts.simple_dvt.exitDeadlineThreshold(0) == NOR_EXIT_DEADLINE_IN_SEC, "sDVT exit deadline threshold should be set correctly after finalizeUpgrade_v4" - - # Steps 28-33: Validate Oracle Daemon Config changes - assert not contracts.oracle_daemon_config.hasRole(config_manager_role, contracts.agent), "Agent should not have CONFIG_MANAGER_ROLE on Oracle Daemon Config" - for var_name in ['NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP', 'VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS', 'VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS']: + vote_id, _ = start_vote({"from": ldo_holder}, silent=True) + + _, call_script_items = get_vote_items() + onchain_script = voting.getVote(vote_id)["script"] + assert onchain_script == encode_call_script(call_script_items) + + # ============================================================================ + # ============================= Execute Vote ============================== + # ========================================================================= + is_executed = voting.getVote(vote_id)["executed"] + if not is_executed: + # ======================================================================= + # ========================= Before voting checks ======================== + # ======================================================================= + # Step 1: Check Lido Locator implementation initial state + assert locator_impl_before != LIDO_LOCATOR_IMPL, "Locator implementation should be different before upgrade" + + # Step 2: Check VEBO implementation initial state + assert vebo_impl_before != VALIDATORS_EXIT_BUS_ORACLE_IMPL, "VEBO implementation should be different before upgrade" + + # Step 3: Check VEBO finalizeUpgrade_v2 state + try: # FIXME: with reverts + assert contracts.validators_exit_bus_oracle.getMaxValidatorsPerReport() != 600, "VEBO max validators per report should not be 600 before upgrade" # FIXME: magic number + except Exception: + pass # Function might not exist yet + + # Steps 4-6: Check VEBO consensus version management + initial_vebo_consensus_version = contracts.validators_exit_bus_oracle.getConsensusVersion() + assert initial_vebo_consensus_version < VEBO_CONSENSUS_VERSION, f"VEBO consensus version should be less than {VEBO_CONSENSUS_VERSION}" + # FIXME: Why no check for the role SUBMIT_REPORT_HASH_ROLE? + + # Step 7: Check TWG role for CS Ejector initial state + add_full_withdrawal_request_role = triggerable_withdrawals_gateway.ADD_FULL_WITHDRAWAL_REQUEST_ROLE() + assert not triggerable_withdrawals_gateway.hasRole(add_full_withdrawal_request_role, cs_ejector), "CS Ejector should not have ADD_FULL_WITHDRAWAL_REQUEST_ROLE before upgrade" + + # Step 8: Check TWG role for VEB initial state + assert not triggerable_withdrawals_gateway.hasRole(add_full_withdrawal_request_role, contracts.validators_exit_bus_oracle), "VEBO should not have ADD_FULL_WITHDRAWAL_REQUEST_ROLE before upgrade" + + # Step 9: Check EasyTrack VEB SUBMIT_REPORT_HASH_ROLE initial state + submit_report_hash_role = web3.keccak(text="SUBMIT_REPORT_HASH_ROLE") + assert not contracts.validators_exit_bus_oracle.hasRole(submit_report_hash_role, EASYTRACK_EVMSCRIPT_EXECUTOR), "EasyTrack executor should not have SUBMIT_REPORT_HASH_ROLE on VEBO before upgrade" + + # Step 10: Check DualGovernance tiebreaker initial state + tiebreaker_details = contracts.dual_governance.getTiebreakerDetails() + initial_tiebreakers = tiebreaker_details[3] # sealableWithdrawalBlockers + assert TRIGGERABLE_WITHDRAWALS_GATEWAY not in initial_tiebreakers, "TWG should not be in tiebreaker list before upgrade" + + # Step 9: Check Withdrawal Vault implementation initial state + assert withdrawal_vault_impl_before != WITHDRAWAL_VAULT_IMPL, "Withdrawal Vault implementation should be different before upgrade" + + # Step 10: Withdrawal Vault finalizeUpgrade_v2 check is done post-execution + assert contracts.withdrawal_vault.getContractVersion() == 1, "Withdrawal Vault version should be 1 before upgrade" + + # Step 11: Check Accounting Oracle implementation initial state + assert accounting_oracle_impl_before != ACCOUNTING_ORACLE_IMPL, "Accounting Oracle implementation should be different before upgrade" + + # Steps 12-14: Check AO consensus version management + initial_ao_consensus_version = contracts.accounting_oracle.getConsensusVersion() + assert initial_ao_consensus_version < AO_CONSENSUS_VERSION, f"AO consensus version should be less than {AO_CONSENSUS_VERSION}" + assert not contracts.accounting_oracle.hasRole(contracts.accounting_oracle.MANAGE_CONSENSUS_VERSION_ROLE(), contracts.agent), "Agent should not have MANAGE_CONSENSUS_VERSION_ROLE on AO before upgrade" + + # Step 17: Check AO version before finalizeUpgrade_v3 + assert contracts.accounting_oracle.getContractVersion() == 2, "AO contract version should be 2 before finalizeUpgrade_v3" + + # Step 15: Check Staking Router implementation initial state + assert staking_router_impl_before != STAKING_ROUTER_IMPL, "Staking Router implementation should be different before upgrade" + + # Steps 16-17: Check SR roles initial state try: - contracts.oracle_daemon_config.get(var_name) - except VirtualMachineError: - pass # Expected to fail - variable should be removed - else: - raise AssertionError(f"Variable {var_name} should have been removed") - assert convert.to_uint(contracts.oracle_daemon_config.get('EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS')) == EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS, f"EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS should be set to {EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS}" - - # Step 34: Validate CSM implementation upgrade - check_proxy_implementation(contracts.csm.address, CSM_IMPL_V2_ADDRESS) - - # Step 35: Validate CSM finalizeUpgradeV2 was called - assert contracts.csm.getInitializedVersion() == CSM_V2_VERSION, f"CSM version should be {CSM_V2_VERSION} after vote" - - # Step 36: Validate CSAccounting implementation upgrade - check_proxy_implementation(contracts.cs_accounting.address, CS_ACCOUNTING_IMPL_V2_ADDRESS) - - # Step 37: Validate CSAccounting finalizeUpgradeV2 was called with bond curves - assert contracts.cs_accounting.getInitializedVersion() == CS_ACCOUNTING_V2_VERSION, f"CSAccounting version should be {CS_ACCOUNTING_V2_VERSION} after vote" - # FIXME: check bond curves - - # Step 38: Validate CSFeeOracle implementation upgrade - check_proxy_implementation(contracts.cs_fee_oracle.address, CS_FEE_ORACLE_IMPL_V2_ADDRESS) - - # Step 39: Validate CSFeeOracle finalizeUpgradeV2 was called with consensus version 3 - assert contracts.cs_fee_oracle.getContractVersion() == CS_FEE_ORACLE_V2_VERSION, f"CSFeeOracle version should be {CS_FEE_ORACLE_V2_VERSION} after vote" - assert contracts.cs_fee_oracle.getConsensusVersion() == CSM_CONSENSUS_VERSION, "CSFeeOracle consensus version should be 3 after vote" + report_validator_exiting_status_role = contracts.staking_router.REPORT_VALIDATOR_EXITING_STATUS_ROLE() + report_validator_exit_triggered_role = contracts.staking_router.REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE() + except Exception as e: + assert "Unknown typed error: 0x" in str(e), f"Unexpected error: {e}" + report_validator_exiting_status_role = ZERO_ADDRESS + report_validator_exit_triggered_role = ZERO_ADDRESS + + assert report_validator_exiting_status_role == ZERO_ADDRESS, "REPORT_VALIDATOR_EXITING_STATUS_ROLE should not exist before upgrade" + assert report_validator_exit_triggered_role == ZERO_ADDRESS, "REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE should not exist before upgrade" + + # Step 18: Check APP_MANAGER_ROLE initial state + app_manager_role = web3.keccak(text="APP_MANAGER_ROLE") + assert contracts.acl.getPermissionManager(ARAGON_KERNEL, app_manager_role) == AGENT, "AGENT should be the permission manager for APP_MANAGER_ROLE" + assert contracts.node_operators_registry.kernel() == ARAGON_KERNEL, "Node Operators Registry must use the correct kernel" + assert not contracts.acl.hasPermission(VOTING, ARAGON_KERNEL, app_manager_role), "VOTING should not have APP_MANAGER_ROLE before the upgrade" + assert not contracts.acl.hasPermission(AGENT, ARAGON_KERNEL, app_manager_role), "AGENT should not have APP_MANAGER_ROLE before the upgrade" + + # Steps 19-23: Check NOR and sDVT initial state + assert not contracts.acl.hasPermission(contracts.agent, contracts.kernel, app_manager_role), "Agent should not have APP_MANAGER_ROLE before upgrade" + assert contracts.node_operators_registry.getContractVersion() == 3, "Node Operators Registry version should be 3 before upgrade" + assert contracts.simple_dvt.getContractVersion() == 3, "Simple DVT version should be 3 before upgrade" + + # Step 24: Check CONFIG_MANAGER_ROLE initial state + config_manager_role = contracts.oracle_daemon_config.CONFIG_MANAGER_ROLE() + assert not contracts.oracle_daemon_config.hasRole(config_manager_role, contracts.agent), "Agent should not have CONFIG_MANAGER_ROLE on Oracle Daemon Config before upgrade" + + # Steps 25-27: Check Oracle Daemon Config variables to be removed + try: + contracts.oracle_daemon_config.get('NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP') + contracts.oracle_daemon_config.get('VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS') + contracts.oracle_daemon_config.get('VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS') + except Exception as e: + assert False, f"Expected variables to exist before removal: {e}" - # Step 40: Validate CSFeeDistributor implementation upgrade - check_proxy_implementation(contracts.cs_fee_distributor.address, CS_FEE_DISTRIBUTOR_IMPL_V2_ADDRESS) + # Step 28: Check that EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS doesn't exist yet + try: + contracts.oracle_daemon_config.get('EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS') + assert False, "EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS should not exist before vote" + except Exception: + pass # Expected to fail + + # Step 29: Check CSM implementation initial state + assert csm_impl_before != CSM_IMPL_V2_ADDRESS, "CSM implementation should be different before vote" + + # Step 30: Check CSM finalizeUpgradeV2 initial state + with reverts(): + # The function should not exist yet + contracts.csm.getInitializedVersion() + + # CSM Step 32: Check CSAccounting implementation (pre-vote state) + assert cs_accounting_impl_before != CS_ACCOUNTING_IMPL_V2_ADDRESS, "CSAccounting implementation should be different before vote" + + # CSM Step 33: Check CSAccounting finalizeUpgradeV2 was not called (pre-vote state) + with reverts(): + # The function should not exist yet + contracts.cs_accounting.getInitializedVersion() + + # CSM Step 34: Check CSFeeOracle implementation (pre-vote state) + assert cs_fee_oracle_impl_before != CS_FEE_ORACLE_IMPL_V2_ADDRESS, "CSFeeOracle implementation should be different before vote" + + # CSM Step 35: Check CSFeeOracle finalizeUpgradeV2 was not called (pre-vote state) + assert contracts.cs_fee_oracle.getContractVersion() < CS_FEE_ORACLE_V2_VERSION, f"CSFeeOracle version should be less than {CS_FEE_ORACLE_V2_VERSION} before vote" + assert contracts.cs_fee_oracle.getConsensusVersion() < 3, "CSFeeOracle consensus version should be less than 3 before vote" + + # CSM Step 36: Check CSFeeDistributor implementation (pre-vote state) + assert cs_fee_distributor_impl_before != CS_FEE_DISTRIBUTOR_IMPL_V2_ADDRESS, "CSFeeDistributor implementation should be different before vote" + + # CSM Step 37: Check CSFeeDistributor finalizeUpgradeV2 was not called (pre-vote state) + with reverts(): + # The function should not exist yet + contracts.cs_fee_distributor.getInitializedVersion() + + # CSM Steps 38-40: CSAccounting roles (pre-vote state) + assert contracts.cs_accounting.hasRole(contracts.cs_accounting.SET_BOND_CURVE_ROLE(), contracts.csm.address), "CSM should have SET_BOND_CURVE_ROLE on CSAccounting before vote" + assert contracts.cs_accounting.hasRole(web3.keccak(text="RESET_BOND_CURVE_ROLE"), contracts.csm.address), "CSM should have RESET_BOND_CURVE_ROLE on CSAccounting before vote" + assert contracts.cs_accounting.hasRole(web3.keccak(text="RESET_BOND_CURVE_ROLE"), CSM_COMMITTEE_MS), "CSM committee should have RESET_BOND_CURVE_ROLE on CSAccounting before vote" + + # CSM Steps 41-42: CSM roles (pre-vote state) + assert not contracts.csm.hasRole(web3.keccak(text="CREATE_NODE_OPERATOR_ROLE"), cs_permissionless_gate.address), "Permissionless gate should not have CREATE_NODE_OPERATOR_ROLE on CSM before vote" + assert not contracts.csm.hasRole(web3.keccak(text="CREATE_NODE_OPERATOR_ROLE"), cs_vetted_gate.address), "Vetted gate should not have CREATE_NODE_OPERATOR_ROLE on CSM before vote" + + # CSM Step 43: CSAccounting bond curve role for vetted gate (pre-vote state) + assert not contracts.cs_accounting.hasRole(contracts.cs_accounting.SET_BOND_CURVE_ROLE(), cs_vetted_gate.address), "Vetted gate should not have SET_BOND_CURVE_ROLE on CSAccounting before vote" + + # CSM Steps 44-45: Verifier roles (pre-vote state) + assert contracts.csm.hasRole(contracts.csm.VERIFIER_ROLE(), contracts.cs_verifier.address), "Old verifier should have VERIFIER_ROLE on CSM before vote" + assert not contracts.csm.hasRole(contracts.csm.VERIFIER_ROLE(), cs_verifier_v2.address), "New verifier should not have VERIFIER_ROLE on CSM before vote" + + # CSM Steps 46-51: GateSeal roles (pre-vote state) + assert contracts.csm.hasRole(contracts.csm.PAUSE_ROLE(), CS_GATE_SEAL_ADDRESS), "Old GateSeal should have PAUSE_ROLE on CSM before vote" + assert contracts.cs_accounting.hasRole(contracts.cs_accounting.PAUSE_ROLE(), CS_GATE_SEAL_ADDRESS), "Old GateSeal should have PAUSE_ROLE on CSAccounting before vote" + assert contracts.cs_fee_oracle.hasRole(contracts.cs_fee_oracle.PAUSE_ROLE(), CS_GATE_SEAL_ADDRESS), "Old GateSeal should have PAUSE_ROLE on CSFeeOracle before vote" + + assert not contracts.csm.hasRole(contracts.csm.PAUSE_ROLE(), CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should not have PAUSE_ROLE on CSM before vote" + assert not contracts.cs_accounting.hasRole(contracts.cs_accounting.PAUSE_ROLE(), CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should not have PAUSE_ROLE on CSAccounting before vote" + assert not contracts.cs_fee_oracle.hasRole(contracts.cs_fee_oracle.PAUSE_ROLE(), CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should not have PAUSE_ROLE on CSFeeOracle before vote" + + # CSM Step 52: Staking Router CSM module state before vote (pre-vote state) + csm_module_before = contracts.staking_router.getStakingModule(CS_MODULE_ID) + csm_share_before = csm_module_before['stakeShareLimit'] + csm_priority_exit_threshold_before = csm_module_before['priorityExitShareThreshold'] + assert csm_share_before != CS_MODULE_NEW_TARGET_SHARE_BP, f"CSM share should not be {CS_MODULE_NEW_TARGET_SHARE_BP} before vote, current: {csm_share_before}" + assert csm_priority_exit_threshold_before != CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP, f"CSM priority exit threshold should not be {CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP} before vote, current: {csm_priority_exit_threshold_before}" + + # CSM Step 65: EasyTrack factories before vote (pre-vote state) + initial_factories = contracts.easy_track.getEVMScriptFactories() + assert EASYTRACK_CS_SET_VETTED_GATE_TREE_FACTORY not in initial_factories, "EasyTrack should not have CSMSetVettedGateTree factory before vote" + assert EASYTRACK_SDVT_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY not in initial_factories, "EasyTrack should not have SDVT validator exit request hashes factory before vote" + assert EASYTRACK_CURATED_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY not in initial_factories, "EasyTrack should not have Curated validator exit request hashes factory before vote" + + # Gate Seals: Check initial states before vote + assert contracts.withdrawal_queue.hasRole(contracts.withdrawal_queue.PAUSE_ROLE(), OLD_GATE_SEAL_ADDRESS), "Old GateSeal should have PAUSE_ROLE on WithdrawalQueue before vote" + assert contracts.validators_exit_bus_oracle.hasRole(contracts.validators_exit_bus_oracle.PAUSE_ROLE(), OLD_GATE_SEAL_ADDRESS), "Old GateSeal should have PAUSE_ROLE on VEBO before vote" + assert not contracts.withdrawal_queue.hasRole(contracts.withdrawal_queue.PAUSE_ROLE(), NEW_WQ_GATE_SEAL), "New WQ GateSeal should not have PAUSE_ROLE on WithdrawalQueue before vote" + assert not contracts.validators_exit_bus_oracle.hasRole(contracts.validators_exit_bus_oracle.PAUSE_ROLE(), NEW_TW_GATE_SEAL), "New TW GateSeal should not have PAUSE_ROLE on VEBO before vote" + assert not triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.PAUSE_ROLE(), NEW_TW_GATE_SEAL), "New TW GateSeal should not have PAUSE_ROLE on TWG before vote" + + # ResealManager: Check initial states before vote + assert not triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.PAUSE_ROLE(), RESEAL_MANAGER), "ResealManager should not have PAUSE_ROLE on TWG before vote" + assert not triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.RESUME_ROLE(), RESEAL_MANAGER), "ResealManager should not have RESUME_ROLE on TWG before vote" + + assert get_lido_vote_cid_from_str(find_metadata_by_vote_id(vote_id)) == IPFS_DESCRIPTION_HASH + + vote_tx: TransactionReceipt = helpers.execute_vote(vote_id=vote_id, accounts=accounts, dao_voting=voting) + display_voting_events(vote_tx) + vote_events = group_voting_events_from_receipt(vote_tx) + + + # ======================================================================= + # ========================= After voting checks ========================= + # ======================================================================= + + # Step 1: Validate Lido Locator implementation was updated + assert get_ossifiable_proxy_impl(contracts.lido_locator) == LIDO_LOCATOR_IMPL, "Locator implementation should be updated to the new value" + + # Step 2-3: Validate VEBO implementation was updated and configured + assert get_ossifiable_proxy_impl(contracts.validators_exit_bus_oracle) == VALIDATORS_EXIT_BUS_ORACLE_IMPL, "VEBO implementation should be updated" + assert contracts.validators_exit_bus_oracle.getMaxValidatorsPerReport() == 600, "VEBO max validators per report should be set to 600" + + # Validate exit request limit parameters from finalizeUpgrade_v2 call + # FIXME: Magic numbers. + exit_request_limits = contracts.validators_exit_bus_oracle.getExitRequestLimitFullInfo() + assert exit_request_limits[0] == 11200, "maxExitRequestsLimit should be 11200" + assert exit_request_limits[1] == 1, "exitsPerFrame should be 1" + assert exit_request_limits[2] == 48, "frameDurationInSec should be 48 hours in seconds" + + # Steps 4-6: Validate VEBO consensus version management + assert not contracts.validators_exit_bus_oracle.hasRole(contracts.validators_exit_bus_oracle.MANAGE_CONSENSUS_VERSION_ROLE(), contracts.agent), "Agent should not have MANAGE_CONSENSUS_VERSION_ROLE on VEBO" + assert contracts.validators_exit_bus_oracle.getConsensusVersion() == VEBO_CONSENSUS_VERSION, f"VEBO consensus version should be set to {VEBO_CONSENSUS_VERSION}" + + # Step 7: Validate EasyTrack VEB SUBMIT_REPORT_HASH_ROLE + assert contracts.validators_exit_bus_oracle.hasRole(submit_report_hash_role, EASYTRACK_EVMSCRIPT_EXECUTOR), "EasyTrack executor should have SUBMIT_REPORT_HASH_ROLE on VEBO" + + # Steps 8-9: Validate TWG roles + assert triggerable_withdrawals_gateway.hasRole(add_full_withdrawal_request_role, cs_ejector), "CS Ejector should have ADD_FULL_WITHDRAWAL_REQUEST_ROLE on TWG" + assert triggerable_withdrawals_gateway.hasRole(add_full_withdrawal_request_role, contracts.validators_exit_bus_oracle), "VEBO should have ADD_FULL_WITHDRAWAL_REQUEST_ROLE on TWG" - # Step 41: Validate CSFeeDistributor finalizeUpgradeV2 was called - assert contracts.cs_fee_distributor.getInitializedVersion() == CS_FEE_DISTRIBUTOR_V2_VERSION, f"CSFeeDistributor version should be {CS_FEE_DISTRIBUTOR_V2_VERSION} after vote" - assert contracts.cs_fee_distributor.rebateRecipient() == contracts.agent.address, "Rebate recipient should be the agent after vote" + # Step 10: Validate DualGovernance tiebreaker connection + final_tiebreaker_details = contracts.dual_governance.getTiebreakerDetails() + final_tiebreakers = final_tiebreaker_details[3] # sealableWithdrawalBlockers + assert TRIGGERABLE_WITHDRAWALS_GATEWAY in final_tiebreakers, "TWG should be in tiebreaker list after upgrade" - # Step 42: Validate SET_BOND_CURVE_ROLE was revoked from CSM on CSAccounting - assert not contracts.cs_accounting.hasRole(contracts.cs_accounting.SET_BOND_CURVE_ROLE(), contracts.csm.address), "CSM should not have SET_BOND_CURVE_ROLE on CSAccounting after vote" + # Steps 11-12: Validate Withdrawal Vault upgrade + assert get_wv_contract_proxy_impl(contracts.withdrawal_vault) == WITHDRAWAL_VAULT_IMPL, "Withdrawal Vault implementation should be updated" + assert contracts.withdrawal_vault.getContractVersion() == 2, "Withdrawal Vault version should be 2 after finalizeUpgrade_v2" - # Step 43: Validate RESET_BOND_CURVE_ROLE was revoked from CSM on CSAccounting - assert not contracts.cs_accounting.hasRole(web3.keccak(text="RESET_BOND_CURVE_ROLE"), contracts.csm.address), "CSM should not have RESET_BOND_CURVE_ROLE on CSAccounting after vote" + # Steps 13-16: Validate Accounting Oracle upgrade + assert get_ossifiable_proxy_impl(contracts.accounting_oracle) == ACCOUNTING_ORACLE_IMPL, "Accounting Oracle implementation should be updated" + assert not contracts.accounting_oracle.hasRole(contracts.accounting_oracle.MANAGE_CONSENSUS_VERSION_ROLE(), contracts.agent), "Agent should not have MANAGE_CONSENSUS_VERSION_ROLE on AO" + assert contracts.accounting_oracle.getConsensusVersion() == AO_CONSENSUS_VERSION, f"AO consensus version should be set to {AO_CONSENSUS_VERSION}" - # Step 44: Validate RESET_BOND_CURVE_ROLE was revoked from CSM committee on CSAccounting - assert not contracts.cs_accounting.hasRole(web3.keccak(text="RESET_BOND_CURVE_ROLE"), CSM_COMMITTEE_MS), "CSM committee should not have RESET_BOND_CURVE_ROLE on CSAccounting after vote" + # Step 17: Validate AO finalizeUpgrade_v3 + assert contracts.accounting_oracle.getContractVersion() == 3, "AO contract version should be 3 after finalizeUpgrade_v3" - # Step 45: Validate CREATE_NODE_OPERATOR_ROLE was granted to permissionless gate on CSM - assert contracts.csm.hasRole(contracts.csm.CREATE_NODE_OPERATOR_ROLE(), cs_permissionless_gate.address), "Permissionless gate should have CREATE_NODE_OPERATOR_ROLE on CSM after vote" + # Steps 18-21: Validate Staking Router upgrade + assert get_ossifiable_proxy_impl(contracts.staking_router) == STAKING_ROUTER_IMPL, "Staking Router implementation should be updated" + assert contracts.staking_router.getContractVersion() == 3, "Staking Router version should be 3 after finalizeUpgrade_v3" + assert contracts.staking_router.hasRole(contracts.staking_router.REPORT_VALIDATOR_EXITING_STATUS_ROLE(), VALIDATOR_EXIT_VERIFIER), "ValidatorExitVerifier should have REPORT_VALIDATOR_EXITING_STATUS_ROLE on SR" + assert contracts.staking_router.hasRole(contracts.staking_router.REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE(), triggerable_withdrawals_gateway), "TWG should have REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE on SR" - # Step 46: Validate CREATE_NODE_OPERATOR_ROLE was granted to vetted gate on CSM - assert contracts.csm.hasRole(contracts.csm.CREATE_NODE_OPERATOR_ROLE(), cs_vetted_gate.address), "Vetted gate should have CREATE_NODE_OPERATOR_ROLE on CSM after vote" + # Steps 22-27: Validate NOR and sDVT updates + assert not contracts.acl.hasPermission(contracts.agent, contracts.kernel, app_manager_role), "Agent should not have APP_MANAGER_ROLE after vote" + assert contracts.node_operators_registry.getContractVersion() == 4, "Node Operators Registry version should be updated to 4" + assert contracts.simple_dvt.getContractVersion() == 4, "Simple DVT version should be updated to 4" + assert contracts.node_operators_registry.exitDeadlineThreshold(0) == NOR_EXIT_DEADLINE_IN_SEC, "NOR exit deadline threshold should be set correctly after finalizeUpgrade_v4" + assert contracts.simple_dvt.exitDeadlineThreshold(0) == NOR_EXIT_DEADLINE_IN_SEC, "sDVT exit deadline threshold should be set correctly after finalizeUpgrade_v4" - # Step 47: Validate SET_BOND_CURVE_ROLE was granted to vetted gate on CSAccounting - assert contracts.cs_accounting.hasRole(contracts.cs_accounting.SET_BOND_CURVE_ROLE(), cs_vetted_gate.address), "Vetted gate should have SET_BOND_CURVE_ROLE on CSAccounting after vote" + # Steps 28-33: Validate Oracle Daemon Config changes + assert not contracts.oracle_daemon_config.hasRole(config_manager_role, contracts.agent), "Agent should not have CONFIG_MANAGER_ROLE on Oracle Daemon Config" + for var_name in ['NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP', 'VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS', 'VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS']: + try: + contracts.oracle_daemon_config.get(var_name) + except VirtualMachineError: + pass # Expected to fail - variable should be removed + else: + raise AssertionError(f"Variable {var_name} should have been removed") + assert convert.to_uint(contracts.oracle_daemon_config.get('EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS')) == EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS, f"EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS should be set to {EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS}" - # Step 48: Validate VERIFIER_ROLE was revoked from old verifier on CSM - assert not contracts.csm.hasRole(contracts.csm.VERIFIER_ROLE(), contracts.cs_verifier.address), "Old verifier should not have VERIFIER_ROLE on CSM after vote" + # Step 34: Validate CSM implementation upgrade + check_proxy_implementation(contracts.csm.address, CSM_IMPL_V2_ADDRESS) - # Step 49: Validate VERIFIER_ROLE was granted to new verifier on CSM - assert contracts.csm.hasRole(contracts.csm.VERIFIER_ROLE(), cs_verifier_v2.address), "New verifier should have VERIFIER_ROLE on CSM after vote" + # Step 35: Validate CSM finalizeUpgradeV2 was called + assert contracts.csm.getInitializedVersion() == CSM_V2_VERSION, f"CSM version should be {CSM_V2_VERSION} after vote" - # Step 50: Validate PAUSE_ROLE was revoked from old GateSeal on CSM - assert not contracts.csm.hasRole(contracts.csm.PAUSE_ROLE(), CS_GATE_SEAL_ADDRESS), "Old GateSeal should not have PAUSE_ROLE on CSM after vote" + # Step 36: Validate CSAccounting implementation upgrade + check_proxy_implementation(contracts.cs_accounting.address, CS_ACCOUNTING_IMPL_V2_ADDRESS) - # Step 51: Validate PAUSE_ROLE was revoked from old GateSeal on CSAccounting - assert not contracts.cs_accounting.hasRole(contracts.cs_accounting.PAUSE_ROLE(), CS_GATE_SEAL_ADDRESS), "Old GateSeal should not have PAUSE_ROLE on CSAccounting after vote" + # Step 37: Validate CSAccounting finalizeUpgradeV2 was called with bond curves + assert contracts.cs_accounting.getInitializedVersion() == CS_ACCOUNTING_V2_VERSION, f"CSAccounting version should be {CS_ACCOUNTING_V2_VERSION} after vote" + # FIXME: check bond curves - # Step 52: Validate PAUSE_ROLE was revoked from old GateSeal on CSFeeOracle - assert not contracts.cs_fee_oracle.hasRole(contracts.cs_fee_oracle.PAUSE_ROLE(), CS_GATE_SEAL_ADDRESS), "Old GateSeal should not have PAUSE_ROLE on CSFeeOracle after vote" + # Step 38: Validate CSFeeOracle implementation upgrade + check_proxy_implementation(contracts.cs_fee_oracle.address, CS_FEE_ORACLE_IMPL_V2_ADDRESS) - # Step 53: Validate PAUSE_ROLE was granted to new GateSeal on CSM - assert contracts.csm.hasRole(contracts.csm.PAUSE_ROLE(), CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should have PAUSE_ROLE on CSM after vote" + # Step 39: Validate CSFeeOracle finalizeUpgradeV2 was called with consensus version 3 + assert contracts.cs_fee_oracle.getContractVersion() == CS_FEE_ORACLE_V2_VERSION, f"CSFeeOracle version should be {CS_FEE_ORACLE_V2_VERSION} after vote" + assert contracts.cs_fee_oracle.getConsensusVersion() == CSM_CONSENSUS_VERSION, "CSFeeOracle consensus version should be 3 after vote" - # Step 54: Validate PAUSE_ROLE was granted to new GateSeal on CSAccounting - assert contracts.cs_accounting.hasRole(contracts.cs_accounting.PAUSE_ROLE(), CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should have PAUSE_ROLE on CSAccounting after vote" + # Step 40: Validate CSFeeDistributor implementation upgrade + check_proxy_implementation(contracts.cs_fee_distributor.address, CS_FEE_DISTRIBUTOR_IMPL_V2_ADDRESS) - # Step 55: Validate PAUSE_ROLE was granted to new GateSeal on CSFeeOracle - assert contracts.cs_fee_oracle.hasRole(contracts.cs_fee_oracle.PAUSE_ROLE(), CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should have PAUSE_ROLE on CSFeeOracle after vote" + # Step 41: Validate CSFeeDistributor finalizeUpgradeV2 was called + assert contracts.cs_fee_distributor.getInitializedVersion() == CS_FEE_DISTRIBUTOR_V2_VERSION, f"CSFeeDistributor version should be {CS_FEE_DISTRIBUTOR_V2_VERSION} after vote" + assert contracts.cs_fee_distributor.rebateRecipient() == contracts.agent.address, "Rebate recipient should be the agent after vote" - # Step 50-52: Check add ICS Bond Curve to CSAccounting - assert not contracts.cs_accounting.hasRole(contracts.cs_accounting.MANAGE_BOND_CURVES_ROLE(), contracts.agent), "Agent should not have MANAGE_BOND_CURVES_ROLE on CSAccounting after vote" - assert contracts.cs_accounting.getCurvesCount() == len(CS_CURVES) + 1, "CSAccounting should have legacy bond curves and ICS Bond Curve after vote" - # FIXME: Check curves? + # Step 42: Validate SET_BOND_CURVE_ROLE was revoked from CSM on CSAccounting + assert not contracts.cs_accounting.hasRole(contracts.cs_accounting.SET_BOND_CURVE_ROLE(), contracts.csm.address), "CSM should not have SET_BOND_CURVE_ROLE on CSAccounting after vote" - # Step 53: Increase CSM share in Staking Router - csm_module_after = contracts.staking_router.getStakingModule(CS_MODULE_ID) - csm_share_after = csm_module_after['stakeShareLimit'] - assert csm_share_after == CS_MODULE_NEW_TARGET_SHARE_BP, f"CSM share should be {CS_MODULE_NEW_TARGET_SHARE_BP} after vote, but got {csm_share_after}" - - csm_priority_exit_threshold_after = csm_module_after['priorityExitShareThreshold'] - assert csm_priority_exit_threshold_after == CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP, f"CSM priority exit threshold should be {CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP} after vote, but got {csm_priority_exit_threshold_after}" - - - # Steps 58-62: Validate Gate Seals updates - assert not contracts.withdrawal_queue.hasRole(contracts.withdrawal_queue.PAUSE_ROLE(), OLD_GATE_SEAL_ADDRESS), "Old GateSeal should not have PAUSE_ROLE on WithdrawalQueue after vote" - assert not contracts.validators_exit_bus_oracle.hasRole(contracts.validators_exit_bus_oracle.PAUSE_ROLE(), OLD_GATE_SEAL_ADDRESS), "Old GateSeal should not have PAUSE_ROLE on VEBO after vote" - assert contracts.withdrawal_queue.hasRole(contracts.withdrawal_queue.PAUSE_ROLE(), NEW_WQ_GATE_SEAL), "New WQ GateSeal should have PAUSE_ROLE on WithdrawalQueue after vote" - assert contracts.validators_exit_bus_oracle.hasRole(contracts.validators_exit_bus_oracle.PAUSE_ROLE(), NEW_TW_GATE_SEAL), "New TW GateSeal should have PAUSE_ROLE on VEBO after vote" - assert triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.PAUSE_ROLE(), NEW_TW_GATE_SEAL), "New TW GateSeal should have PAUSE_ROLE on TWG after vote" - - # Steps 63-64: Validate ResealManager roles - assert triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.PAUSE_ROLE(), RESEAL_MANAGER), "ResealManager should have PAUSE_ROLE on TWG after vote" - assert triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.RESUME_ROLE(), RESEAL_MANAGER), "ResealManager should have RESUME_ROLE on TWG after vote" - - # Step 65: Add EasyTrack factory for CSSetVettedGateTree - new_factories = contracts.easy_track.getEVMScriptFactories() - assert EASYTRACK_CS_SET_VETTED_GATE_TREE_FACTORY in new_factories, "EasyTrack should have CSSetVettedGateTree factory after vote" - - # Steps 66-67: Validate EasyTrack factories for validator exit request hashes - assert EASYTRACK_SDVT_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY in new_factories, "EasyTrack should have SDVT validator exit request hashes factory after vote" - assert EASYTRACK_CURATED_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY in new_factories, "EasyTrack should have Curated validator exit request hashes factory after vote" - - # --- VALIDATE EVENTS --- - - voting_events = group_voting_events_from_receipt(vote_tx) - dg_execution_events = group_dg_events_from_receipt(dg_tx, timelock=TIMELOCK, admin_executor=DUAL_GOVERNANCE_EXECUTORS[0]) - - # Validate voting events structure - assert len(voting_events) == 4, "Unexpected number of voting events" - dg_voting_event, dg_bypass_voting_event1, dg_bypass_voting_event2, dg_bypass_voting_event3 = voting_events - - # Validate DG execution events structure - assert len(dg_execution_events) == 66, "Unexpected number of dual governance events" - - - # Main DG voting event validation - validate_dual_governance_submit_event( - dg_voting_event, - proposal_id, - proposer=VOTING, - executor=DUAL_GOVERNANCE_EXECUTORS[0], - ) - - # Validate EasyTrack bypass events for new factories - validate_evmscript_factory_added_event( - event=dg_bypass_voting_event1, - p=EVMScriptFactoryAdded( - factory_addr=EASYTRACK_CS_SET_VETTED_GATE_TREE_FACTORY, - permissions=create_permissions(interface.CSVettedGate(CS_VETTED_GATE_ADDRESS), "setTreeParams") - ), - emitted_by=contracts.easy_track, - ) - - validate_evmscript_factory_added_event( - event=dg_bypass_voting_event2, - p=EVMScriptFactoryAdded( - factory_addr=EASYTRACK_SDVT_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY, - permissions=create_permissions(contracts.validators_exit_bus_oracle, "submitExitRequestsHash") - ), - emitted_by=contracts.easy_track, - ) - - validate_evmscript_factory_added_event( - event=dg_bypass_voting_event3, - p=EVMScriptFactoryAdded( - factory_addr=EASYTRACK_CURATED_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY, - permissions=create_permissions(contracts.validators_exit_bus_oracle, "submitExitRequestsHash") - ), - emitted_by=contracts.easy_track, - ) - - # === DG EXECUTION EVENTS VALIDATION === - - # 0. Lido Locator upgrade events - validate_proxy_upgrade_event(dg_execution_events[0], LIDO_LOCATOR_IMPL, emitted_by=contracts.lido_locator) - - # 1. VEBO upgrade events - validate_proxy_upgrade_event(dg_execution_events[1], VALIDATORS_EXIT_BUS_ORACLE_IMPL, emitted_by=contracts.validators_exit_bus_oracle) - - # 2. VEBO finalize upgrade events - validate_contract_version_set_event(dg_execution_events[2], version=2, emitted_by=contracts.validators_exit_bus_oracle) - assert 'ExitRequestsLimitSet' in dg_execution_events[2], "ExitRequestsLimitSet event not found" - assert dg_execution_events[2]['ExitRequestsLimitSet'][0]['maxExitRequestsLimit'] == 11200, "Wrong maxExitRequestsLimit" - assert dg_execution_events[2]['ExitRequestsLimitSet'][0]['exitsPerFrame'] == 1, "Wrong exitsPerFrame" - assert dg_execution_events[2]['ExitRequestsLimitSet'][0]['frameDurationInSec'] == 48, "Wrong frameDurationInSec" - - # 3. Grant VEBO MANAGE_CONSENSUS_VERSION_ROLE to Agent - validate_role_grant_event( - dg_execution_events[3], - role_hash=web3.keccak(text="MANAGE_CONSENSUS_VERSION_ROLE").hex(), - account=contracts.agent.address, - emitted_by=contracts.validators_exit_bus_oracle - ) - - # 4. Set VEBO consensus version to 4 - validate_consensus_version_set_event( - dg_execution_events[4], - new_version=4, - prev_version=3, - emitted_by=contracts.validators_exit_bus_oracle - ) - - # 5. Revoke VEBO MANAGE_CONSENSUS_VERSION_ROLE from Agent - validate_role_revoke_event( - dg_execution_events[5], - role_hash=web3.keccak(text="MANAGE_CONSENSUS_VERSION_ROLE").hex(), - account=contracts.agent.address, - emitted_by=contracts.validators_exit_bus_oracle - ) - - # 6. Grant VEBO SUBMIT_REPORT_HASH_ROLE to EasyTrack executor - validate_role_grant_event( - dg_execution_events[6], - role_hash=web3.keccak(text="SUBMIT_REPORT_HASH_ROLE").hex(), - account=EASYTRACK_EVMSCRIPT_EXECUTOR, - emitted_by=contracts.validators_exit_bus_oracle - ) - - # 7. Grant TWG ADD_FULL_WITHDRAWAL_REQUEST_ROLE to CS Ejector - validate_role_grant_event( - dg_execution_events[7], - role_hash=web3.keccak(text="ADD_FULL_WITHDRAWAL_REQUEST_ROLE").hex(), - account=CS_EJECTOR_ADDRESS, - emitted_by=triggerable_withdrawals_gateway - ) - - # 8. Grant TWG ADD_FULL_WITHDRAWAL_REQUEST_ROLE to VEBO - validate_role_grant_event( - dg_execution_events[8], - role_hash=web3.keccak(text="ADD_FULL_WITHDRAWAL_REQUEST_ROLE").hex(), - account=contracts.validators_exit_bus_oracle.address, - emitted_by=triggerable_withdrawals_gateway - ) - - # 9. Connect TWG to Dual Governance tiebreaker - assert 'SealableWithdrawalBlockerAdded' in dg_execution_events[9], "SealableWithdrawalBlockerAdded event not found" - assert dg_execution_events[9]['SealableWithdrawalBlockerAdded'][0]['sealable'] == TRIGGERABLE_WITHDRAWALS_GATEWAY, "Wrong sealableWithdrawalBlocker" - - # 10. Update WithdrawalVault implementation - validate_proxy_upgrade_event(dg_execution_events[10], WITHDRAWAL_VAULT_IMPL, emitted_by=contracts.withdrawal_vault) - - # 11. Call finalizeUpgrade_v2 on WithdrawalVault - validate_contract_version_set_event(dg_execution_events[11], version=2, emitted_by=contracts.withdrawal_vault) - - # 12. Update AO implementation - validate_proxy_upgrade_event(dg_execution_events[12], ACCOUNTING_ORACLE_IMPL, emitted_by=contracts.accounting_oracle) - - # 13. Grant AO MANAGE_CONSENSUS_VERSION_ROLE to the AGENT - validate_role_grant_event( - dg_execution_events[13], - role_hash=web3.keccak(text="MANAGE_CONSENSUS_VERSION_ROLE").hex(), - account=contracts.agent.address, - emitted_by=contracts.accounting_oracle - ) - - # 14. Bump AO consensus version to 4 - validate_consensus_version_set_event( - dg_execution_events[14], - new_version=4, - prev_version=3, - emitted_by=contracts.accounting_oracle - ) - - # 15. Revoke AO MANAGE_CONSENSUS_VERSION_ROLE from the AGENT - validate_role_revoke_event( - dg_execution_events[15], - role_hash=web3.keccak(text="MANAGE_CONSENSUS_VERSION_ROLE").hex(), - account=contracts.agent.address, - emitted_by=contracts.accounting_oracle - ) - - # 16. Call finalizeUpgrade_v3() on AO - validate_contract_version_set_event(dg_execution_events[16], version=3, emitted_by=contracts.accounting_oracle) - - # 17. Update SR implementation - validate_proxy_upgrade_event(dg_execution_events[17], STAKING_ROUTER_IMPL, emitted_by=contracts.staking_router) - - # 18. Call finalizeUpgrade_v3() on SR - validate_contract_version_set_event(dg_execution_events[18], version=3, emitted_by=contracts.staking_router) - - # 19. Grant SR REPORT_VALIDATOR_EXITING_STATUS_ROLE to ValidatorExitVerifier - validate_role_grant_event( - dg_execution_events[19], - role_hash=web3.keccak(text="REPORT_VALIDATOR_EXITING_STATUS_ROLE").hex(), - account=VALIDATOR_EXIT_VERIFIER, - emitted_by=contracts.staking_router - ) - - # 20. Grant SR REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE to TWG - validate_role_grant_event( - dg_execution_events[20], - role_hash=web3.keccak(text="REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE").hex(), - account=triggerable_withdrawals_gateway.address, - emitted_by=contracts.staking_router - ) - - # 21. Grant APP_MANAGER_ROLE on Kernel to Voting - assert 'SetPermission' in dg_execution_events[21] - assert dg_execution_events[21]['SetPermission'][0]['allowed'] is True - - # 22. Set new implementation for NOR - assert 'SetApp' in dg_execution_events[22] - - # 23. Finalize upgrade for NOR - validate_contract_version_set_event(dg_execution_events[23], version=4, emitted_by=contracts.node_operators_registry) - assert 'ExitDeadlineThresholdChanged' in dg_execution_events[23] - assert dg_execution_events[23]['ExitDeadlineThresholdChanged'][0]['threshold'] == NOR_EXIT_DEADLINE_IN_SEC - - # 24. Set new implementation for sDVT - assert 'SetApp' in dg_execution_events[24] - - # 25. Finalize upgrade for sDVT - validate_contract_version_set_event(dg_execution_events[25], version=4, emitted_by=contracts.simple_dvt) - assert 'ExitDeadlineThresholdChanged' in dg_execution_events[25] - assert dg_execution_events[25]['ExitDeadlineThresholdChanged'][0]['threshold'] == NOR_EXIT_DEADLINE_IN_SEC - - # 26. Revoke APP_MANAGER_ROLE on Kernel from Voting - assert 'SetPermission' in dg_execution_events[26] - assert dg_execution_events[26]['SetPermission'][0]['allowed'] is False - - # 27. Grant CONFIG_MANAGER_ROLE on OracleDaemonConfig to Agent - validate_role_grant_event( - dg_execution_events[27], - role_hash=contracts.oracle_daemon_config.CONFIG_MANAGER_ROLE().hex(), - account=contracts.agent.address, - emitted_by=contracts.oracle_daemon_config - ) - - # 28. Unset NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP - assert 'ConfigValueUnset' in dg_execution_events[28] - assert 'NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP' in dg_execution_events[28]['ConfigValueUnset'][0]['key'] - - # 29. Unset VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS - assert 'ConfigValueUnset' in dg_execution_events[29] - assert 'VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS' in dg_execution_events[29]['ConfigValueUnset'][0]['key'] - - # 30. Unset VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS - assert 'ConfigValueUnset' in dg_execution_events[30] - assert 'VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS' in dg_execution_events[30]['ConfigValueUnset'][0]['key'] - - # 31. Set EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS - assert 'ConfigValueSet' in dg_execution_events[31] - assert 'EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS' in dg_execution_events[31]['ConfigValueSet'][0]['key'] - assert convert.to_int(dg_execution_events[31]['ConfigValueSet'][0]['value']) == EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS - - # 32. Revoke CONFIG_MANAGER_ROLE from the AGENT - validate_role_revoke_event( - dg_execution_events[32], - role_hash=contracts.oracle_daemon_config.CONFIG_MANAGER_ROLE().hex(), - account=contracts.agent.address, - emitted_by=contracts.oracle_daemon_config - ) - - # 33. CSM implementation upgrade - validate_proxy_upgrade_event(dg_execution_events[33], CSM_IMPL_V2_ADDRESS, emitted_by=contracts.csm) - - # 34. CSM finalize upgrade validation - assert 'Initialized' in dg_execution_events[34] - assert dg_execution_events[34]['Initialized'][0]['version'] == CSM_V2_VERSION - - # 35. CSAccounting implementation upgrade - validate_proxy_upgrade_event(dg_execution_events[35], CS_ACCOUNTING_IMPL_V2_ADDRESS, emitted_by=contracts.cs_accounting) - - # 36. CSAccounting finalize upgrade with bond curves - assert 'BondCurveAdded' in dg_execution_events[36] - assert len(dg_execution_events[36]['BondCurveAdded']) == len(CS_CURVES) - assert 'Initialized' in dg_execution_events[36] - assert dg_execution_events[36]['Initialized'][0]['version'] == CS_ACCOUNTING_V2_VERSION - - # 37. CSFeeOracle implementation upgrade - validate_proxy_upgrade_event(dg_execution_events[37], CS_FEE_ORACLE_IMPL_V2_ADDRESS, emitted_by=contracts.cs_fee_oracle) - - # 38. CSFeeOracle finalize upgrade with consensus version - validate_consensus_version_set_event(dg_execution_events[38], new_version=3, prev_version=2, emitted_by=contracts.cs_fee_oracle) - validate_contract_version_set_event(dg_execution_events[38], version=CS_FEE_ORACLE_V2_VERSION, emitted_by=contracts.cs_fee_oracle) - - # 39. CSFeeDistributor implementation upgrade - validate_proxy_upgrade_event(dg_execution_events[39], CS_FEE_DISTRIBUTOR_IMPL_V2_ADDRESS, emitted_by=contracts.cs_fee_distributor) - - # 40. CSFeeDistributor finalize upgrade - assert 'RebateRecipientSet' in dg_execution_events[40] - assert 'Initialized' in dg_execution_events[40] - assert dg_execution_events[40]['Initialized'][0]['version'] == CS_FEE_DISTRIBUTOR_V2_VERSION - - # 41. Revoke SET_BOND_CURVE_ROLE from CSM on CSAccounting - validate_role_revoke_event( - dg_execution_events[41], - role_hash=contracts.cs_accounting.SET_BOND_CURVE_ROLE().hex(), - account=contracts.csm.address, - emitted_by=contracts.cs_accounting - ) - - # 42. Revoke RESET_BOND_CURVE_ROLE from CSM on CSAccounting - validate_role_revoke_event( - dg_execution_events[42], - role_hash=web3.keccak(text="RESET_BOND_CURVE_ROLE").hex(), - account=contracts.csm.address, - emitted_by=contracts.cs_accounting - ) - - # 43. Revoke RESET_BOND_CURVE_ROLE from CSM committee on CSAccounting - validate_role_revoke_event( - dg_execution_events[43], - role_hash=web3.keccak(text="RESET_BOND_CURVE_ROLE").hex(), - account=CSM_COMMITTEE_MS, - emitted_by=contracts.cs_accounting - ) - - # 44. Grant CREATE_NODE_OPERATOR_ROLE to permissionless gate on CSM - validate_role_grant_event( - dg_execution_events[44], - role_hash=contracts.csm.CREATE_NODE_OPERATOR_ROLE().hex(), - account=CS_PERMISSIONLESS_GATE_ADDRESS, - emitted_by=contracts.csm - ) - - # 45. Grant CREATE_NODE_OPERATOR_ROLE to vetted gate on CSM - validate_role_grant_event( - dg_execution_events[45], - role_hash=contracts.csm.CREATE_NODE_OPERATOR_ROLE().hex(), - account=CS_VETTED_GATE_ADDRESS, - emitted_by=contracts.csm - ) - - # 46. Grant SET_BOND_CURVE_ROLE to vetted gate on CSAccounting - validate_role_grant_event( - dg_execution_events[46], - role_hash=contracts.cs_accounting.SET_BOND_CURVE_ROLE().hex(), - account=CS_VETTED_GATE_ADDRESS, - emitted_by=contracts.cs_accounting - ) - - # 47. Revoke VERIFIER_ROLE from old verifier on CSM - validate_role_revoke_event( - dg_execution_events[47], - role_hash=contracts.csm.VERIFIER_ROLE().hex(), - account=contracts.cs_verifier.address, - emitted_by=contracts.csm - ) - - # 48. Grant VERIFIER_ROLE to new verifier on CSM - validate_role_grant_event( - dg_execution_events[48], - role_hash=contracts.csm.VERIFIER_ROLE().hex(), - account=CS_VERIFIER_V2_ADDRESS, - emitted_by=contracts.csm - ) - - # 49. Revoke PAUSE_ROLE from old GateSeal on CSM - validate_role_revoke_event( - dg_execution_events[49], - role_hash=contracts.csm.PAUSE_ROLE().hex(), - account=CS_GATE_SEAL_ADDRESS, - emitted_by=contracts.csm - ) - - # 50. Revoke PAUSE_ROLE from old GateSeal on CSAccounting - validate_role_revoke_event( - dg_execution_events[50], - role_hash=contracts.cs_accounting.PAUSE_ROLE().hex(), - account=CS_GATE_SEAL_ADDRESS, - emitted_by=contracts.cs_accounting - ) - - # 51. Revoke PAUSE_ROLE from old GateSeal on CSFeeOracle - validate_role_revoke_event( - dg_execution_events[51], - role_hash=contracts.cs_fee_oracle.PAUSE_ROLE().hex(), - account=CS_GATE_SEAL_ADDRESS, - emitted_by=contracts.cs_fee_oracle - ) - - # 52. Grant PAUSE_ROLE to new GateSeal on CSM - validate_role_grant_event( - dg_execution_events[52], - role_hash=contracts.csm.PAUSE_ROLE().hex(), - account=CS_GATE_SEAL_V2_ADDRESS, - emitted_by=contracts.csm - ) - - # 53. Grant PAUSE_ROLE to new GateSeal on CSAccounting - validate_role_grant_event( - dg_execution_events[53], - role_hash=contracts.cs_accounting.PAUSE_ROLE().hex(), - account=CS_GATE_SEAL_V2_ADDRESS, - emitted_by=contracts.cs_accounting - ) - - # 54. Grant PAUSE_ROLE to new GateSeal on CSFeeOracle - validate_role_grant_event( - dg_execution_events[54], - role_hash=contracts.cs_fee_oracle.PAUSE_ROLE().hex(), - account=CS_GATE_SEAL_V2_ADDRESS, - emitted_by=contracts.cs_fee_oracle - ) - - # 55. Grant MANAGE_BOND_CURVES_ROLE to agent on CSAccounting - validate_role_grant_event( - dg_execution_events[55], - role_hash=contracts.cs_accounting.MANAGE_BOND_CURVES_ROLE().hex(), - account=contracts.agent.address, - emitted_by=contracts.cs_accounting - ) - - # 56. Add ICS bond curve - ics_curve_id = len(CS_CURVES) - validate_bond_curve_added_event(dg_execution_events[56], curve_id=ics_curve_id, emitted_by=contracts.cs_accounting) - - # 57. Revoke MANAGE_BOND_CURVES_ROLE from agent on CSAccounting - validate_role_revoke_event( - dg_execution_events[57], - role_hash=contracts.cs_accounting.MANAGE_BOND_CURVES_ROLE().hex(), - account=contracts.agent.address, - emitted_by=contracts.cs_accounting - ) - - # 58. Increase CSM share in Staking Router - validate_staking_module_update_event( - dg_execution_events[58], - module_id=CS_MODULE_ID, - share_limit=CS_MODULE_NEW_TARGET_SHARE_BP, - priority_share_threshold=CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP, - module_fee_points_bp=CS_MODULE_MODULE_FEE_BP, - treasury_fee_points_bp=CS_MODULE_TREASURY_FEE_BP, - max_deposits_per_block=CS_MODULE_MAX_DEPOSITS_PER_BLOCK, - min_deposit_block_distance=CS_MODULE_MIN_DEPOSIT_BLOCK_DISTANCE, - emitted_by=contracts.staking_router - ) - - # 59-65. Gate Seals and ResealManager role updates - # 59. Revoke PAUSE_ROLE on WithdrawalQueue from the old GateSeal - validate_role_revoke_event( - dg_execution_events[59], - role_hash=contracts.withdrawal_queue.PAUSE_ROLE().hex(), - account=OLD_GATE_SEAL_ADDRESS, - emitted_by=contracts.withdrawal_queue - ) - - # 60. Revoke PAUSE_ROLE on ValidatorsExitBusOracle from the old GateSeal - validate_role_revoke_event( - dg_execution_events[60], - role_hash=contracts.validators_exit_bus_oracle.PAUSE_ROLE().hex(), - account=OLD_GATE_SEAL_ADDRESS, - emitted_by=contracts.validators_exit_bus_oracle - ) - - # 61. Grant PAUSE_ROLE on WithdrawalQueue to the new WithdrawalQueue GateSeal - validate_role_grant_event( - dg_execution_events[61], - role_hash=contracts.withdrawal_queue.PAUSE_ROLE().hex(), - account=NEW_WQ_GATE_SEAL, - emitted_by=contracts.withdrawal_queue - ) - - # 62. Grant PAUSE_ROLE on ValidatorsExitBusOracle to the new Triggerable Withdrawals GateSeal - validate_role_grant_event( - dg_execution_events[62], - role_hash=contracts.validators_exit_bus_oracle.PAUSE_ROLE().hex(), - account=NEW_TW_GATE_SEAL, - emitted_by=contracts.validators_exit_bus_oracle - ) - - # 63. Grant PAUSE_ROLE on TriggerableWithdrawalsGateway to the new Triggerable Withdrawals GateSeal - validate_role_grant_event( - dg_execution_events[63], - role_hash=triggerable_withdrawals_gateway.PAUSE_ROLE().hex(), - account=NEW_TW_GATE_SEAL, - emitted_by=triggerable_withdrawals_gateway - ) - - # 64. Grant PAUSE_ROLE on TriggerableWithdrawalsGateway to ResealManager - validate_role_grant_event( - dg_execution_events[64], - role_hash=triggerable_withdrawals_gateway.PAUSE_ROLE().hex(), - account=RESEAL_MANAGER, - emitted_by=triggerable_withdrawals_gateway - ) - - # 65. Grant RESUME_ROLE on TriggerableWithdrawalsGateway to ResealManager - validate_role_grant_event( - dg_execution_events[65], - role_hash=triggerable_withdrawals_gateway.RESUME_ROLE().hex(), - account=RESEAL_MANAGER, - emitted_by=triggerable_withdrawals_gateway - ) + # Step 43: Validate RESET_BOND_CURVE_ROLE was revoked from CSM on CSAccounting + assert not contracts.cs_accounting.hasRole(web3.keccak(text="RESET_BOND_CURVE_ROLE"), contracts.csm.address), "CSM should not have RESET_BOND_CURVE_ROLE on CSAccounting after vote" + + # Step 44: Validate RESET_BOND_CURVE_ROLE was revoked from CSM committee on CSAccounting + assert not contracts.cs_accounting.hasRole(web3.keccak(text="RESET_BOND_CURVE_ROLE"), CSM_COMMITTEE_MS), "CSM committee should not have RESET_BOND_CURVE_ROLE on CSAccounting after vote" + + # Step 45: Validate CREATE_NODE_OPERATOR_ROLE was granted to permissionless gate on CSM + assert contracts.csm.hasRole(contracts.csm.CREATE_NODE_OPERATOR_ROLE(), cs_permissionless_gate.address), "Permissionless gate should have CREATE_NODE_OPERATOR_ROLE on CSM after vote" + + # Step 46: Validate CREATE_NODE_OPERATOR_ROLE was granted to vetted gate on CSM + assert contracts.csm.hasRole(contracts.csm.CREATE_NODE_OPERATOR_ROLE(), cs_vetted_gate.address), "Vetted gate should have CREATE_NODE_OPERATOR_ROLE on CSM after vote" + + # Step 47: Validate SET_BOND_CURVE_ROLE was granted to vetted gate on CSAccounting + assert contracts.cs_accounting.hasRole(contracts.cs_accounting.SET_BOND_CURVE_ROLE(), cs_vetted_gate.address), "Vetted gate should have SET_BOND_CURVE_ROLE on CSAccounting after vote" + + # Step 48: Validate VERIFIER_ROLE was revoked from old verifier on CSM + assert not contracts.csm.hasRole(contracts.csm.VERIFIER_ROLE(), contracts.cs_verifier.address), "Old verifier should not have VERIFIER_ROLE on CSM after vote" + + # Step 49: Validate VERIFIER_ROLE was granted to new verifier on CSM + assert contracts.csm.hasRole(contracts.csm.VERIFIER_ROLE(), cs_verifier_v2.address), "New verifier should have VERIFIER_ROLE on CSM after vote" + + # Step 50: Validate PAUSE_ROLE was revoked from old GateSeal on CSM + assert not contracts.csm.hasRole(contracts.csm.PAUSE_ROLE(), CS_GATE_SEAL_ADDRESS), "Old GateSeal should not have PAUSE_ROLE on CSM after vote" + + # Step 51: Validate PAUSE_ROLE was revoked from old GateSeal on CSAccounting + assert not contracts.cs_accounting.hasRole(contracts.cs_accounting.PAUSE_ROLE(), CS_GATE_SEAL_ADDRESS), "Old GateSeal should not have PAUSE_ROLE on CSAccounting after vote" + + # Step 52: Validate PAUSE_ROLE was revoked from old GateSeal on CSFeeOracle + assert not contracts.cs_fee_oracle.hasRole(contracts.cs_fee_oracle.PAUSE_ROLE(), CS_GATE_SEAL_ADDRESS), "Old GateSeal should not have PAUSE_ROLE on CSFeeOracle after vote" + + # Step 53: Validate PAUSE_ROLE was granted to new GateSeal on CSM + assert contracts.csm.hasRole(contracts.csm.PAUSE_ROLE(), CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should have PAUSE_ROLE on CSM after vote" + + # Step 54: Validate PAUSE_ROLE was granted to new GateSeal on CSAccounting + assert contracts.cs_accounting.hasRole(contracts.cs_accounting.PAUSE_ROLE(), CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should have PAUSE_ROLE on CSAccounting after vote" + + # Step 55: Validate PAUSE_ROLE was granted to new GateSeal on CSFeeOracle + assert contracts.cs_fee_oracle.hasRole(contracts.cs_fee_oracle.PAUSE_ROLE(), CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should have PAUSE_ROLE on CSFeeOracle after vote" + + # Step 50-52: Check add ICS Bond Curve to CSAccounting + assert not contracts.cs_accounting.hasRole(contracts.cs_accounting.MANAGE_BOND_CURVES_ROLE(), contracts.agent), "Agent should not have MANAGE_BOND_CURVES_ROLE on CSAccounting after vote" + assert contracts.cs_accounting.getCurvesCount() == len(CS_CURVES) + 1, "CSAccounting should have legacy bond curves and ICS Bond Curve after vote" + # FIXME: Check curves? + + # Step 53: Increase CSM share in Staking Router + csm_module_after = contracts.staking_router.getStakingModule(CS_MODULE_ID) + csm_share_after = csm_module_after['stakeShareLimit'] + assert csm_share_after == CS_MODULE_NEW_TARGET_SHARE_BP, f"CSM share should be {CS_MODULE_NEW_TARGET_SHARE_BP} after vote, but got {csm_share_after}" + + csm_priority_exit_threshold_after = csm_module_after['priorityExitShareThreshold'] + assert csm_priority_exit_threshold_after == CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP, f"CSM priority exit threshold should be {CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP} after vote, but got {csm_priority_exit_threshold_after}" + + + # Steps 58-62: Validate Gate Seals updates + assert not contracts.withdrawal_queue.hasRole(contracts.withdrawal_queue.PAUSE_ROLE(), OLD_GATE_SEAL_ADDRESS), "Old GateSeal should not have PAUSE_ROLE on WithdrawalQueue after vote" + assert not contracts.validators_exit_bus_oracle.hasRole(contracts.validators_exit_bus_oracle.PAUSE_ROLE(), OLD_GATE_SEAL_ADDRESS), "Old GateSeal should not have PAUSE_ROLE on VEBO after vote" + assert contracts.withdrawal_queue.hasRole(contracts.withdrawal_queue.PAUSE_ROLE(), NEW_WQ_GATE_SEAL), "New WQ GateSeal should have PAUSE_ROLE on WithdrawalQueue after vote" + assert contracts.validators_exit_bus_oracle.hasRole(contracts.validators_exit_bus_oracle.PAUSE_ROLE(), NEW_TW_GATE_SEAL), "New TW GateSeal should have PAUSE_ROLE on VEBO after vote" + assert triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.PAUSE_ROLE(), NEW_TW_GATE_SEAL), "New TW GateSeal should have PAUSE_ROLE on TWG after vote" + + # Steps 63-64: Validate ResealManager roles + assert triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.PAUSE_ROLE(), RESEAL_MANAGER), "ResealManager should have PAUSE_ROLE on TWG after vote" + assert triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.RESUME_ROLE(), RESEAL_MANAGER), "ResealManager should have RESUME_ROLE on TWG after vote" + + # Step 65: Add EasyTrack factory for CSSetVettedGateTree + new_factories = contracts.easy_track.getEVMScriptFactories() + assert EASYTRACK_CS_SET_VETTED_GATE_TREE_FACTORY in new_factories, "EasyTrack should have CSSetVettedGateTree factory after vote" + + # Steps 66-67: Validate EasyTrack factories for validator exit request hashes + assert EASYTRACK_SDVT_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY in new_factories, "EasyTrack should have SDVT validator exit request hashes factory after vote" + assert EASYTRACK_CURATED_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY in new_factories, "EasyTrack should have Curated validator exit request hashes factory after vote" + + # --- VALIDATE EVENTS --- + + voting_events = group_voting_events_from_receipt(vote_tx) + dg_execution_events = group_dg_events_from_receipt(dg_tx, timelock=TIMELOCK, admin_executor=DUAL_GOVERNANCE_EXECUTORS[0]) + + # Validate voting events structure + assert len(voting_events) == 4, "Unexpected number of voting events" + dg_voting_event, dg_bypass_voting_event1, dg_bypass_voting_event2, dg_bypass_voting_event3 = voting_events + + assert len(vote_events) == EXPECTED_VOTE_EVENTS_COUNT, "Unexpected number of dual governance events" + assert count_vote_items_by_events(vote_tx, voting) == EXPECTED_VOTE_EVENTS_COUNT + if EXPECTED_DG_PROPOSAL_ID is not None: + assert EXPECTED_DG_PROPOSAL_ID == timelock.getProposalsCount() + + # Validate DG Proposal Submit event + validate_dual_governance_submit_event( + vote_events[0], + proposal_id=EXPECTED_DG_PROPOSAL_ID, + proposer=VOTING, + executor=DUAL_GOVERNANCE_ADMIN_EXECUTOR, + metadata="TODO DG proposal description", + proposal_calls=dual_governance_proposal_calls, + emitted_by=[EMERGENCY_PROTECTED_TIMELOCK, DUAL_GOVERNANCE], + ) + + # Validate EasyTrack bypass events for new factories + validate_evmscript_factory_added_event( + event=dg_bypass_voting_event1, + p=EVMScriptFactoryAdded( + factory_addr=EASYTRACK_CS_SET_VETTED_GATE_TREE_FACTORY, + permissions=create_permissions(interface.CSVettedGate(CS_VETTED_GATE_ADDRESS), "setTreeParams") + ), + emitted_by=contracts.easy_track, + ) + + validate_evmscript_factory_added_event( + event=dg_bypass_voting_event2, + p=EVMScriptFactoryAdded( + factory_addr=EASYTRACK_SDVT_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY, + permissions=create_permissions(contracts.validators_exit_bus_oracle, "submitExitRequestsHash") + ), + emitted_by=contracts.easy_track, + ) + + validate_evmscript_factory_added_event( + event=dg_bypass_voting_event3, + p=EVMScriptFactoryAdded( + factory_addr=EASYTRACK_CURATED_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY, + permissions=create_permissions(contracts.validators_exit_bus_oracle, "submitExitRequestsHash") + ), + emitted_by=contracts.easy_track, + ) + + + if EXPECTED_DG_PROPOSAL_ID is not None: + details = timelock.getProposalDetails(EXPECTED_DG_PROPOSAL_ID) + if details["status"] != PROPOSAL_STATUS["executed"]: + # ========================================================================= + # ================== DG before proposal executed checks =================== + # ========================================================================= + # TODO add DG before proposal executed checks + + + if details["status"] == PROPOSAL_STATUS["submitted"]: + chain.sleep(timelock.getAfterSubmitDelay() + 1) + dual_governance.scheduleProposal(EXPECTED_DG_PROPOSAL_ID, {"from": stranger}) + + if timelock.getProposalDetails(EXPECTED_DG_PROPOSAL_ID)["status"] == PROPOSAL_STATUS["scheduled"]: + chain.sleep(timelock.getAfterScheduleDelay() + 1) + dg_tx: TransactionReceipt = timelock.execute(EXPECTED_DG_PROPOSAL_ID, {"from": stranger}) + display_dg_events(dg_tx) + dg_events = group_dg_events_from_receipt( + dg_tx, + timelock=EMERGENCY_PROTECTED_TIMELOCK, + admin_executor=DUAL_GOVERNANCE_ADMIN_EXECUTOR, + ) + assert count_vote_items_by_events(dg_tx, AGENT) == EXPECTED_DG_EVENTS_COUNT + assert len(dg_events) == EXPECTED_DG_EVENTS_COUNT + + # === DG EXECUTION EVENTS VALIDATION === + # 0. Lido Locator upgrade events + validate_proxy_upgrade_event(dg_execution_events[0], LIDO_LOCATOR_IMPL, emitted_by=contracts.lido_locator) + + # 1. VEBO upgrade events + validate_proxy_upgrade_event(dg_execution_events[1], VALIDATORS_EXIT_BUS_ORACLE_IMPL, emitted_by=contracts.validators_exit_bus_oracle) + + # 2. VEBO finalize upgrade events + validate_contract_version_set_event(dg_execution_events[2], version=2, emitted_by=contracts.validators_exit_bus_oracle) + assert 'ExitRequestsLimitSet' in dg_execution_events[2], "ExitRequestsLimitSet event not found" + assert dg_execution_events[2]['ExitRequestsLimitSet'][0]['maxExitRequestsLimit'] == 11200, "Wrong maxExitRequestsLimit" + assert dg_execution_events[2]['ExitRequestsLimitSet'][0]['exitsPerFrame'] == 1, "Wrong exitsPerFrame" + assert dg_execution_events[2]['ExitRequestsLimitSet'][0]['frameDurationInSec'] == 48, "Wrong frameDurationInSec" + + # 3. Grant VEBO MANAGE_CONSENSUS_VERSION_ROLE to Agent + validate_role_grant_event( + dg_execution_events[3], + role_hash=web3.keccak(text="MANAGE_CONSENSUS_VERSION_ROLE").hex(), + account=contracts.agent.address, + emitted_by=contracts.validators_exit_bus_oracle + ) + + # 4. Set VEBO consensus version to 4 + validate_consensus_version_set_event( + dg_execution_events[4], + new_version=4, + prev_version=3, + emitted_by=contracts.validators_exit_bus_oracle + ) + + # 5. Revoke VEBO MANAGE_CONSENSUS_VERSION_ROLE from Agent + validate_role_revoke_event( + dg_execution_events[5], + role_hash=web3.keccak(text="MANAGE_CONSENSUS_VERSION_ROLE").hex(), + account=contracts.agent.address, + emitted_by=contracts.validators_exit_bus_oracle + ) + + # 6. Grant VEBO SUBMIT_REPORT_HASH_ROLE to EasyTrack executor + validate_role_grant_event( + dg_execution_events[6], + role_hash=web3.keccak(text="SUBMIT_REPORT_HASH_ROLE").hex(), + account=EASYTRACK_EVMSCRIPT_EXECUTOR, + emitted_by=contracts.validators_exit_bus_oracle + ) + + # 7. Grant TWG ADD_FULL_WITHDRAWAL_REQUEST_ROLE to CS Ejector + validate_role_grant_event( + dg_execution_events[7], + role_hash=web3.keccak(text="ADD_FULL_WITHDRAWAL_REQUEST_ROLE").hex(), + account=CS_EJECTOR_ADDRESS, + emitted_by=triggerable_withdrawals_gateway + ) + + # 8. Grant TWG ADD_FULL_WITHDRAWAL_REQUEST_ROLE to VEBO + validate_role_grant_event( + dg_execution_events[8], + role_hash=web3.keccak(text="ADD_FULL_WITHDRAWAL_REQUEST_ROLE").hex(), + account=contracts.validators_exit_bus_oracle.address, + emitted_by=triggerable_withdrawals_gateway + ) + + # 9. Connect TWG to Dual Governance tiebreaker + assert 'SealableWithdrawalBlockerAdded' in dg_execution_events[9], "SealableWithdrawalBlockerAdded event not found" + assert dg_execution_events[9]['SealableWithdrawalBlockerAdded'][0]['sealable'] == TRIGGERABLE_WITHDRAWALS_GATEWAY, "Wrong sealableWithdrawalBlocker" + + # 10. Update WithdrawalVault implementation + validate_proxy_upgrade_event(dg_execution_events[10], WITHDRAWAL_VAULT_IMPL, emitted_by=contracts.withdrawal_vault) + + # 11. Call finalizeUpgrade_v2 on WithdrawalVault + validate_contract_version_set_event(dg_execution_events[11], version=2, emitted_by=contracts.withdrawal_vault) + + # 12. Update AO implementation + validate_proxy_upgrade_event(dg_execution_events[12], ACCOUNTING_ORACLE_IMPL, emitted_by=contracts.accounting_oracle) + + # 13. Grant AO MANAGE_CONSENSUS_VERSION_ROLE to the AGENT + validate_role_grant_event( + dg_execution_events[13], + role_hash=web3.keccak(text="MANAGE_CONSENSUS_VERSION_ROLE").hex(), + account=contracts.agent.address, + emitted_by=contracts.accounting_oracle + ) + + # 14. Bump AO consensus version to 4 + validate_consensus_version_set_event( + dg_execution_events[14], + new_version=4, + prev_version=3, + emitted_by=contracts.accounting_oracle + ) + + # 15. Revoke AO MANAGE_CONSENSUS_VERSION_ROLE from the AGENT + validate_role_revoke_event( + dg_execution_events[15], + role_hash=web3.keccak(text="MANAGE_CONSENSUS_VERSION_ROLE").hex(), + account=contracts.agent.address, + emitted_by=contracts.accounting_oracle + ) + + # 16. Call finalizeUpgrade_v3() on AO + validate_contract_version_set_event(dg_execution_events[16], version=3, emitted_by=contracts.accounting_oracle) + + # 17. Update SR implementation + validate_proxy_upgrade_event(dg_execution_events[17], STAKING_ROUTER_IMPL, emitted_by=contracts.staking_router) + + # 18. Call finalizeUpgrade_v3() on SR + validate_contract_version_set_event(dg_execution_events[18], version=3, emitted_by=contracts.staking_router) + + # 19. Grant SR REPORT_VALIDATOR_EXITING_STATUS_ROLE to ValidatorExitVerifier + validate_role_grant_event( + dg_execution_events[19], + role_hash=web3.keccak(text="REPORT_VALIDATOR_EXITING_STATUS_ROLE").hex(), + account=VALIDATOR_EXIT_VERIFIER, + emitted_by=contracts.staking_router + ) + + # 20. Grant SR REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE to TWG + validate_role_grant_event( + dg_execution_events[20], + role_hash=web3.keccak(text="REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE").hex(), + account=triggerable_withdrawals_gateway.address, + emitted_by=contracts.staking_router + ) + + # 21. Grant APP_MANAGER_ROLE on Kernel to Voting + assert 'SetPermission' in dg_execution_events[21] + assert dg_execution_events[21]['SetPermission'][0]['allowed'] is True + + # 22. Set new implementation for NOR + assert 'SetApp' in dg_execution_events[22] + + # 23. Finalize upgrade for NOR + validate_contract_version_set_event(dg_execution_events[23], version=4, emitted_by=contracts.node_operators_registry) + assert 'ExitDeadlineThresholdChanged' in dg_execution_events[23] + assert dg_execution_events[23]['ExitDeadlineThresholdChanged'][0]['threshold'] == NOR_EXIT_DEADLINE_IN_SEC + + # 24. Set new implementation for sDVT + assert 'SetApp' in dg_execution_events[24] + + # 25. Finalize upgrade for sDVT + validate_contract_version_set_event(dg_execution_events[25], version=4, emitted_by=contracts.simple_dvt) + assert 'ExitDeadlineThresholdChanged' in dg_execution_events[25] + assert dg_execution_events[25]['ExitDeadlineThresholdChanged'][0]['threshold'] == NOR_EXIT_DEADLINE_IN_SEC + + # 26. Revoke APP_MANAGER_ROLE on Kernel from Voting + assert 'SetPermission' in dg_execution_events[26] + assert dg_execution_events[26]['SetPermission'][0]['allowed'] is False + + # 27. Grant CONFIG_MANAGER_ROLE on OracleDaemonConfig to Agent + validate_role_grant_event( + dg_execution_events[27], + role_hash=contracts.oracle_daemon_config.CONFIG_MANAGER_ROLE().hex(), + account=contracts.agent.address, + emitted_by=contracts.oracle_daemon_config + ) + + # 28. Unset NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP + assert 'ConfigValueUnset' in dg_execution_events[28] + assert 'NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP' in dg_execution_events[28]['ConfigValueUnset'][0]['key'] + + # 29. Unset VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS + assert 'ConfigValueUnset' in dg_execution_events[29] + assert 'VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS' in dg_execution_events[29]['ConfigValueUnset'][0]['key'] + + # 30. Unset VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS + assert 'ConfigValueUnset' in dg_execution_events[30] + assert 'VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS' in dg_execution_events[30]['ConfigValueUnset'][0]['key'] + + # 31. Set EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS + assert 'ConfigValueSet' in dg_execution_events[31] + assert 'EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS' in dg_execution_events[31]['ConfigValueSet'][0]['key'] + assert convert.to_int(dg_execution_events[31]['ConfigValueSet'][0]['value']) == EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS + + # 32. Revoke CONFIG_MANAGER_ROLE from the AGENT + validate_role_revoke_event( + dg_execution_events[32], + role_hash=contracts.oracle_daemon_config.CONFIG_MANAGER_ROLE().hex(), + account=contracts.agent.address, + emitted_by=contracts.oracle_daemon_config + ) + + # 33. CSM implementation upgrade + validate_proxy_upgrade_event(dg_execution_events[33], CSM_IMPL_V2_ADDRESS, emitted_by=contracts.csm) + + # 34. CSM finalize upgrade validation + assert 'Initialized' in dg_execution_events[34] + assert dg_execution_events[34]['Initialized'][0]['version'] == CSM_V2_VERSION + + # 35. CSAccounting implementation upgrade + validate_proxy_upgrade_event(dg_execution_events[35], CS_ACCOUNTING_IMPL_V2_ADDRESS, emitted_by=contracts.cs_accounting) + + # 36. CSAccounting finalize upgrade with bond curves + assert 'BondCurveAdded' in dg_execution_events[36] + assert len(dg_execution_events[36]['BondCurveAdded']) == len(CS_CURVES) + assert 'Initialized' in dg_execution_events[36] + assert dg_execution_events[36]['Initialized'][0]['version'] == CS_ACCOUNTING_V2_VERSION + + # 37. CSFeeOracle implementation upgrade + validate_proxy_upgrade_event(dg_execution_events[37], CS_FEE_ORACLE_IMPL_V2_ADDRESS, emitted_by=contracts.cs_fee_oracle) + + # 38. CSFeeOracle finalize upgrade with consensus version + validate_consensus_version_set_event(dg_execution_events[38], new_version=3, prev_version=2, emitted_by=contracts.cs_fee_oracle) + validate_contract_version_set_event(dg_execution_events[38], version=CS_FEE_ORACLE_V2_VERSION, emitted_by=contracts.cs_fee_oracle) + + # 39. CSFeeDistributor implementation upgrade + validate_proxy_upgrade_event(dg_execution_events[39], CS_FEE_DISTRIBUTOR_IMPL_V2_ADDRESS, emitted_by=contracts.cs_fee_distributor) + + # 40. CSFeeDistributor finalize upgrade + assert 'RebateRecipientSet' in dg_execution_events[40] + assert 'Initialized' in dg_execution_events[40] + assert dg_execution_events[40]['Initialized'][0]['version'] == CS_FEE_DISTRIBUTOR_V2_VERSION + + # 41. Revoke SET_BOND_CURVE_ROLE from CSM on CSAccounting + validate_role_revoke_event( + dg_execution_events[41], + role_hash=contracts.cs_accounting.SET_BOND_CURVE_ROLE().hex(), + account=contracts.csm.address, + emitted_by=contracts.cs_accounting + ) + + # 42. Revoke RESET_BOND_CURVE_ROLE from CSM on CSAccounting + validate_role_revoke_event( + dg_execution_events[42], + role_hash=web3.keccak(text="RESET_BOND_CURVE_ROLE").hex(), + account=contracts.csm.address, + emitted_by=contracts.cs_accounting + ) + + # 43. Revoke RESET_BOND_CURVE_ROLE from CSM committee on CSAccounting + validate_role_revoke_event( + dg_execution_events[43], + role_hash=web3.keccak(text="RESET_BOND_CURVE_ROLE").hex(), + account=CSM_COMMITTEE_MS, + emitted_by=contracts.cs_accounting + ) + + # 44. Grant CREATE_NODE_OPERATOR_ROLE to permissionless gate on CSM + validate_role_grant_event( + dg_execution_events[44], + role_hash=contracts.csm.CREATE_NODE_OPERATOR_ROLE().hex(), + account=CS_PERMISSIONLESS_GATE_ADDRESS, + emitted_by=contracts.csm + ) + + # 45. Grant CREATE_NODE_OPERATOR_ROLE to vetted gate on CSM + validate_role_grant_event( + dg_execution_events[45], + role_hash=contracts.csm.CREATE_NODE_OPERATOR_ROLE().hex(), + account=CS_VETTED_GATE_ADDRESS, + emitted_by=contracts.csm + ) + + # 46. Grant SET_BOND_CURVE_ROLE to vetted gate on CSAccounting + validate_role_grant_event( + dg_execution_events[46], + role_hash=contracts.cs_accounting.SET_BOND_CURVE_ROLE().hex(), + account=CS_VETTED_GATE_ADDRESS, + emitted_by=contracts.cs_accounting + ) + + # 47. Revoke VERIFIER_ROLE from old verifier on CSM + validate_role_revoke_event( + dg_execution_events[47], + role_hash=contracts.csm.VERIFIER_ROLE().hex(), + account=contracts.cs_verifier.address, + emitted_by=contracts.csm + ) + + # 48. Grant VERIFIER_ROLE to new verifier on CSM + validate_role_grant_event( + dg_execution_events[48], + role_hash=contracts.csm.VERIFIER_ROLE().hex(), + account=CS_VERIFIER_V2_ADDRESS, + emitted_by=contracts.csm + ) + + # 49. Revoke PAUSE_ROLE from old GateSeal on CSM + validate_role_revoke_event( + dg_execution_events[49], + role_hash=contracts.csm.PAUSE_ROLE().hex(), + account=CS_GATE_SEAL_ADDRESS, + emitted_by=contracts.csm + ) + + # 50. Revoke PAUSE_ROLE from old GateSeal on CSAccounting + validate_role_revoke_event( + dg_execution_events[50], + role_hash=contracts.cs_accounting.PAUSE_ROLE().hex(), + account=CS_GATE_SEAL_ADDRESS, + emitted_by=contracts.cs_accounting + ) + + # 51. Revoke PAUSE_ROLE from old GateSeal on CSFeeOracle + validate_role_revoke_event( + dg_execution_events[51], + role_hash=contracts.cs_fee_oracle.PAUSE_ROLE().hex(), + account=CS_GATE_SEAL_ADDRESS, + emitted_by=contracts.cs_fee_oracle + ) + + # 52. Grant PAUSE_ROLE to new GateSeal on CSM + validate_role_grant_event( + dg_execution_events[52], + role_hash=contracts.csm.PAUSE_ROLE().hex(), + account=CS_GATE_SEAL_V2_ADDRESS, + emitted_by=contracts.csm + ) + + # 53. Grant PAUSE_ROLE to new GateSeal on CSAccounting + validate_role_grant_event( + dg_execution_events[53], + role_hash=contracts.cs_accounting.PAUSE_ROLE().hex(), + account=CS_GATE_SEAL_V2_ADDRESS, + emitted_by=contracts.cs_accounting + ) + + # 54. Grant PAUSE_ROLE to new GateSeal on CSFeeOracle + validate_role_grant_event( + dg_execution_events[54], + role_hash=contracts.cs_fee_oracle.PAUSE_ROLE().hex(), + account=CS_GATE_SEAL_V2_ADDRESS, + emitted_by=contracts.cs_fee_oracle + ) + + # 55. Grant MANAGE_BOND_CURVES_ROLE to agent on CSAccounting + validate_role_grant_event( + dg_execution_events[55], + role_hash=contracts.cs_accounting.MANAGE_BOND_CURVES_ROLE().hex(), + account=contracts.agent.address, + emitted_by=contracts.cs_accounting + ) + + # 56. Add ICS bond curve + ics_curve_id = len(CS_CURVES) + validate_bond_curve_added_event(dg_execution_events[56], curve_id=ics_curve_id, emitted_by=contracts.cs_accounting) + + # 57. Revoke MANAGE_BOND_CURVES_ROLE from agent on CSAccounting + validate_role_revoke_event( + dg_execution_events[57], + role_hash=contracts.cs_accounting.MANAGE_BOND_CURVES_ROLE().hex(), + account=contracts.agent.address, + emitted_by=contracts.cs_accounting + ) + + # 58. Increase CSM share in Staking Router + validate_staking_module_update_event( + dg_execution_events[58], + module_id=CS_MODULE_ID, + share_limit=CS_MODULE_NEW_TARGET_SHARE_BP, + priority_share_threshold=CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP, + module_fee_points_bp=CS_MODULE_MODULE_FEE_BP, + treasury_fee_points_bp=CS_MODULE_TREASURY_FEE_BP, + max_deposits_per_block=CS_MODULE_MAX_DEPOSITS_PER_BLOCK, + min_deposit_block_distance=CS_MODULE_MIN_DEPOSIT_BLOCK_DISTANCE, + emitted_by=contracts.staking_router + ) + + # 59-65. Gate Seals and ResealManager role updates + # 59. Revoke PAUSE_ROLE on WithdrawalQueue from the old GateSeal + validate_role_revoke_event( + dg_execution_events[59], + role_hash=contracts.withdrawal_queue.PAUSE_ROLE().hex(), + account=OLD_GATE_SEAL_ADDRESS, + emitted_by=contracts.withdrawal_queue + ) + + # 60. Revoke PAUSE_ROLE on ValidatorsExitBusOracle from the old GateSeal + validate_role_revoke_event( + dg_execution_events[60], + role_hash=contracts.validators_exit_bus_oracle.PAUSE_ROLE().hex(), + account=OLD_GATE_SEAL_ADDRESS, + emitted_by=contracts.validators_exit_bus_oracle + ) + + # 61. Grant PAUSE_ROLE on WithdrawalQueue to the new WithdrawalQueue GateSeal + validate_role_grant_event( + dg_execution_events[61], + role_hash=contracts.withdrawal_queue.PAUSE_ROLE().hex(), + account=NEW_WQ_GATE_SEAL, + emitted_by=contracts.withdrawal_queue + ) + + # 62. Grant PAUSE_ROLE on ValidatorsExitBusOracle to the new Triggerable Withdrawals GateSeal + validate_role_grant_event( + dg_execution_events[62], + role_hash=contracts.validators_exit_bus_oracle.PAUSE_ROLE().hex(), + account=NEW_TW_GATE_SEAL, + emitted_by=contracts.validators_exit_bus_oracle + ) + + # 63. Grant PAUSE_ROLE on TriggerableWithdrawalsGateway to the new Triggerable Withdrawals GateSeal + validate_role_grant_event( + dg_execution_events[63], + role_hash=triggerable_withdrawals_gateway.PAUSE_ROLE().hex(), + account=NEW_TW_GATE_SEAL, + emitted_by=triggerable_withdrawals_gateway + ) + + # 64. Grant PAUSE_ROLE on TriggerableWithdrawalsGateway to ResealManager + validate_role_grant_event( + dg_execution_events[64], + role_hash=triggerable_withdrawals_gateway.PAUSE_ROLE().hex(), + account=RESEAL_MANAGER, + emitted_by=triggerable_withdrawals_gateway + ) + + # 65. Grant RESUME_ROLE on TriggerableWithdrawalsGateway to ResealManager + validate_role_grant_event( + dg_execution_events[65], + role_hash=triggerable_withdrawals_gateway.RESUME_ROLE().hex(), + account=RESEAL_MANAGER, + emitted_by=triggerable_withdrawals_gateway + ) \ No newline at end of file From d9ce3d3e0db00e5280bfb3552281292fbc2c34ef Mon Sep 17 00:00:00 2001 From: vgorkavenko Date: Mon, 14 Jul 2025 18:18:26 +0200 Subject: [PATCH 19/28] feat: addresses for voting. regression, acceptance tests for CSM --- .../test_vote_dg_easy_track_tw_holesky.py | 3 +- archive/tests/test_vote_tw_csm2_hoodi.py | 2 +- configs/config_holesky.py | 15 +- configs/config_hoodi.py | 34 ++- configs/config_mainnet.py | 54 +++-- interfaces/CSExitPenalties.json | 2 +- interfaces/CSModule.json | 2 +- interfaces/CSParametersRegistry.json | 1 + interfaces/CSVerifierV2.json | 2 +- scripts/ci/prepare_environment.py | 2 +- scripts/vote_tw_csm2_mainnet.py | 24 +- tests/acceptance/test_csm.py | 137 ++++++++--- tests/regression/test_csm.py | 203 ++++++++-------- utils/config.py | 17 +- utils/test/csm_helpers.py | 216 +++++++----------- utils/test/extra_data.py | 10 +- utils/test/oracle_report_helpers.py | 3 + utils/test/staking_router_helpers.py | 8 +- 18 files changed, 422 insertions(+), 313 deletions(-) create mode 100644 interfaces/CSParametersRegistry.json diff --git a/archive/tests/test_vote_dg_easy_track_tw_holesky.py b/archive/tests/test_vote_dg_easy_track_tw_holesky.py index 1e04cdfa7..f70d7235d 100644 --- a/archive/tests/test_vote_dg_easy_track_tw_holesky.py +++ b/archive/tests/test_vote_dg_easy_track_tw_holesky.py @@ -1,5 +1,4 @@ -from typing import Optional -from scripts.vote_dg_easy_track_tw_holesky import start_vote +from archive.scripts.vote_dg_easy_track_tw_holesky import start_vote from brownie import interface, chain, web3 # type: ignore from utils.dual_governance import wait_for_noon_utc_to_satisfy_time_constrains from utils.config import ( diff --git a/archive/tests/test_vote_tw_csm2_hoodi.py b/archive/tests/test_vote_tw_csm2_hoodi.py index 944009e48..01b224f14 100644 --- a/archive/tests/test_vote_tw_csm2_hoodi.py +++ b/archive/tests/test_vote_tw_csm2_hoodi.py @@ -1,5 +1,5 @@ from typing import Optional -from scripts.vote_tw_csm2_hoodi import start_vote +from archive.scripts.vote_tw_csm2_hoodi import start_vote from brownie import interface, reverts, chain, convert, web3, ZERO_ADDRESS # type: ignore from brownie.network.event import EventDict from utils.easy_track import create_permissions diff --git a/configs/config_holesky.py b/configs/config_holesky.py index 77c3bbfdc..daca2417c 100644 --- a/configs/config_holesky.py +++ b/configs/config_holesky.py @@ -101,6 +101,8 @@ DEPOSIT_SECURITY_MODULE_V2 = "0x045dd46212A178428c088573A7d102B9d89a022A" # dsm address before SR V2 enact ACCOUNTING_ORACLE = "0x4E97A3972ce8511D87F334dA17a2C332542a5246" ACCOUNTING_ORACLE_IMPL = "0x748CE008ac6b15634ceD5a6083796f75695052a2" +HASH_CONSENSUS_FOR_AO = "0xa067FC95c22D51c3bC35fd4BE37414Ee8cc890d2" +AO_CONSENSUS_VERSION = 4 VALIDATORS_EXIT_BUS_ORACLE = "0xffDDF7025410412deaa05E3E1cE68FE53208afcb" EIP712_STETH = "0xE154732c5Eab277fd88a9fF6Bdff7805eD97BCB1" STAKING_ROUTER = "0xd6EbF043D30A7fe46D1Db32BA90a0A51207FE229" @@ -143,6 +145,9 @@ CS_MODULE_MAX_DEPOSITS_PER_BLOCK = 30 CS_MODULE_MIN_DEPOSIT_BLOCK_DISTANCE = 25 +ORACLE_QUORUM = 2 +ORACLE_COMMITTEE = () + CSM_COMMITTEE_MS = "0xc4DAB3a3ef68C6DFd8614a870D64D475bA44F164" # EOA CSM_ADDRESS = "0x4562c3e63c2e586cD1651B958C22F88135aCAd4f" CS_ACCOUNTING_ADDRESS = "0xc093e53e8F4b55A223c18A2Da6fA00e60DD5EFE1" @@ -151,7 +156,7 @@ CS_FEE_DISTRIBUTOR_ADDRESS = "0xD7ba648C8F72669C6aE649648B516ec03D07c8ED" CS_FEE_ORACLE_ADDRESS = "0xaF57326C7d513085051b50912D51809ECC5d98Ee" CS_GATE_SEAL_ADDRESS = "0xf1C03536dbC77B1bD493a2D1C0b1831Ea78B540a" -CS_VERIFIER_ADDRESS = "0xc099dfd61f6e5420e0ca7e84d820daad17fc1d44" +CS_VERIFIER_ADDRESS = "0xBC88b4b56A58b33716C3C2e879b4B1F964152AD4" CS_ORACLE_EPOCHS_PER_FRAME = 225 * 7 # 7 days CS_VERIFIER_ADDRESS_OLD = "0x6FDAA094227CF8E1593f9fB9C1b867C1f846F916" @@ -166,3 +171,11 @@ TIME_CONSTRAINTS = "0x4D36598EA14bd70a1040CF59ABF6f9439afBf5d9" ROLES_VALIDATOR = "0xf532fC0a18D3339A52b3f1152FcA9925De5855AA" ALLOWED_TOKENS_REGISTRY = "0x091C0eC8B4D54a9fcB36269B5D5E5AF43309e666" + +# CSM v2 Contracts +CS_PERMISSIONLESS_GATE_ADDRESS = "0x676626c3940ae32eF1e4F609938F785fF064ee22" +CS_VETTED_GATE_ADDRESS = "0x92A5aB5e4f98e67Fb7295fe439A652d0E51033bf" +CS_PARAMS_REGISTRY_ADDRESS = "0x25Cb2bA01849Ff577DD5223C4C8E46292cB15550" +CS_STRIKES_ADDRESS = "0xa3806442E717308dc7FED0cb4d7b0de1F643546C" +CS_EJECTOR_ADDRESS = "0x477589D5A8cB67Bd6682AF3612f99ADB72d09582" +CS_EXIT_PENALTIES_ADDRESS = "0xCF153E01322Ffd038737A25A2A139ECccF1A5bAD" diff --git a/configs/config_hoodi.py b/configs/config_hoodi.py index 24c84baaf..b73b72629 100644 --- a/configs/config_hoodi.py +++ b/configs/config_hoodi.py @@ -1,6 +1,28 @@ # Ethereum Chain parameters CHAIN_NETWORK_NAME = "hoodi" +CHAIN_SECONDS_PER_SLOT = 12 +CHAIN_SLOTS_PER_EPOCH = 32 +CHAIN_GENESIS_TIME = 1742213400 +ORACLE_QUORUM = 7 +ORACLE_COMMITTEE = [ + '0x1932f53B1457a5987791a40Ba91f71c5Efd5788F', + '0x219743f1911d84B32599BdC2Df21fC8Dba6F81a2', + '0x43C45C2455C49eed320F463fF4f1Ece3D2BF5aE2', + '0x4c75FA734a39f3a21C57e583c1c29942F021C6B7', + '0x948A62cc0414979dc7aa9364BA5b96ECb29f8736', + '0x99B2B75F490fFC9A29E4E1f5987BE8e30E690aDF', + '0xB1cC91878c1831893D39C2Bb0988404ca5Fa7918', + '0xD3b1e36A372Ca250eefF61f90E833Ca070559970', + '0xcA80ee7313A315879f326105134F938676Cfd7a9', + '0xf03B8DC8762B97F13Ac82e6F94bE3Ed002FF7459', + '0xf7aE520e99ed3C41180B5E12681d31Aa7302E4e5', + '0xfe43A8B0b481Ae9fB1862d31826532047d2d538c' +] + +WSTETH_TOKEN = "0x7E99eE3C66636DE415D2d7C880938F2f40f94De4" +BURNER = "0x4e9A9ea2F154bA34BE919CD16a4A953DCd888165" + # DAO ARAGON_KERNEL = "0xA48DF029Fd2e5FCECB3886c5c2F60e3625A1E87d" LDO_TOKEN = "0xEf2573966D009CcEA0Fc74451dee2193564198dc" @@ -121,6 +143,14 @@ WITHDRAWAL_QUEUE_GATE_SEAL_ADDRESS = "0x73d76Bd3D589B2b2185c402da82cdAfbc18b958D" TRIGGERABLE_WITHDRAWALS_GATE_SEAL_ADDRESS = "0x368f2fcb593170823cc844F1B29e75E3d26879A1" +CS_PARAMS_REGISTRY_ADDRESS = "0xA4aD5236963f9Fe4229864712269D8d79B65C5Ad" +CS_EXIT_PENALTIES_ADDRESS = "0xD259b31083Be841E5C85b2D481Cfc17C14276800" +CS_STRIKES_ADDRESS = "0x8fBA385C3c334D251eE413e79d4D3890db98693c" +CS_VETTED_GATE_ADDRESS = "0x10a254E724fe2b7f305F76f3F116a3969c53845f" +CS_PERMISSIONLESS_GATE_ADDRESS = "0x5553077102322689876A6AdFd48D75014c28acfb" +CS_EJECTOR_ADDRESS = "0x21e271cBa32672B106737AbeB3a45E53Fe9a0df4" +CS_VERIFIER_V2_ADDRESS = "0xf805b3711cBB48F15Ae2bb27095ddC38c5339968" + # DualGovernance DUAL_GOVERNANCE = "0x9CAaCCc62c66d817CC59c44780D1b722359795bF" @@ -143,8 +173,8 @@ DUAL_GOVERNANCE_CONFIG_PROVIDER_VALUES = { - "FIRST_SEAL_RAGE_QUIT_SUPPORT": 3 * 10**16, # 3% in PercentD16 - "SECOND_SEAL_RAGE_QUIT_SUPPORT": 15 * 10**16, # 15% in PercentD16 + "FIRST_SEAL_RAGE_QUIT_SUPPORT": 3 * 10 ** 16, # 3% in PercentD16 + "SECOND_SEAL_RAGE_QUIT_SUPPORT": 15 * 10 ** 16, # 15% in PercentD16 "MIN_ASSETS_LOCK_DURATION": 300, # 5 mins "RAGE_QUIT_ETH_WITHDRAWALS_DELAY_GROWTH": 1200, # 20 mins "RAGE_QUIT_ETH_WITHDRAWALS_MIN_DELAY": 600, # 10 min diff --git a/configs/config_mainnet.py b/configs/config_mainnet.py index bca9f6216..854e3dc2f 100644 --- a/configs/config_mainnet.py +++ b/configs/config_mainnet.py @@ -380,9 +380,16 @@ CS_GATE_SEAL_ADDRESS = "0x16Dbd4B85a448bE564f1742d5c8cCdD2bB3185D0" CS_VERIFIER_ADDRESS = "0xeC6Cc185f671F627fb9b6f06C8772755F587b05d" # Rotated from 0x0c345dFa318f9F4977cdd4f33d80F9D0ffA38e8B to 0xeC6Cc185f671F627fb9b6f06C8772755F587b05d in vote 2025/07/16 CS_VERIFIER_ADDRESS_OLD = "0x3Dfc50f22aCA652a0a6F28a0F892ab62074b5583" +CS_PARAMS_REGISTRY_ADDRESS = "0x9D28ad303C90DF524BA960d7a2DAC56DcC31e428" +CS_EXIT_PENALTIES_ADDRESS = "0x06cd61045f958A209a0f8D746e103eCc625f4193" +CS_STRIKES_ADDRESS = "0xaa328816027F2D32B9F56d190BC9Fa4A5C07637f" +CS_EJECTOR_ADDRESS = "0xc72b58aa02E0e98cF8A4a0E9Dce75e763800802C" +CS_VETTED_GATE_ADDRESS = "0xB314D4A76C457c93150d308787939063F4Cc67E0" +CS_PERMISSIONLESS_GATE_ADDRESS = "0xcF33a38111d0B1246A3F38a838fb41D626B454f0" +CS_VERIFIER_V2_ADDRESS = "0xdC5FE1782B6943f318E05230d688713a560063DC" # DualGovernance -DUAL_GOVERNANCE = "0xcdF49b058D606AD34c5789FD8c3BF8B3E54bA2db" +DUAL_GOVERNANCE = "0xC1db28B3301331277e307FDCfF8DE28242A4486E" TIMELOCK = "0xCE0425301C85c5Ea2A0873A2dEe44d78E02D2316" DUAL_GOVERNANCE_EXECUTORS = ["0x23E0B465633FF5178808F4A75186E2F2F9537021"] # Executor #1 is admin executor RESEAL_MANAGER = "0x7914b5a1539b97Bd0bbd155757F25FD79A522d24" @@ -396,25 +403,10 @@ RESEAL_COMMITTEE = "0xFFe21561251c49AdccFad065C94Fb4931dF49081" -ESCROW_MASTER_COPY = "0xb84317C0E142D8911A0d69Dc32c48d87753B8d1C" -ESCROW_VETO_SIGNALLING = "0xA8F14D033f377779274Ae016584a05bF14Dccaf8" +ESCROW_MASTER_COPY = "0xd6A67636c05BeB5B4a5c90D408b03A63c4e39426" +ESCROW_VETO_SIGNALLING = "0x165813A31446a98c84E20Dda8C101BB3C8228e1c" MAX_MIN_ASSETS_LOCK_DURATION = 4147200 -DUAL_GOVERNANCE_VALUES = { - "MAX_TIEBREAKER_ACTIVATION_TIMEOUT": 63072000, # 2 years - "MIN_TIEBREAKER_ACTIVATION_TIMEOUT": 15768000, # 6 months - "MAX_SEALABLE_WITHDRAWAL_BLOCKERS_COUNT": 255, - "PROPOSERS_COUNT": 1, - "TIEBREAKER_DETAILS": { - "TIEBREAKER_COMMITTEE": "0x175742c3DDD88B0192df3EcF98f180A79cb259D0", - "TIEBREAKER_ACTIVATION_TIMEOUT": 31536000, # 1 year - "WITHDRAWAL_BLOCKERS": ( - "0x889edC2eDab5f40e902b864aD4d7AdE8E412F9B1", - "0x0De4Ea0184c2ad0BacA7183356Aea5B8d5Bf5c6e" - ) - } -} - DUAL_GOVERNANCE_CONFIG_PROVIDER_VALUES = { "FIRST_SEAL_RAGE_QUIT_SUPPORT": 1 * 10 ** 16, # 1% in PercentD16 "SECOND_SEAL_RAGE_QUIT_SUPPORT": 10 * 10 ** 16, # 10% in PercentD16 @@ -447,19 +439,19 @@ TIEBREAKER_VALUES = { "CORE_COMMITTEE": { - "ADDRESS": "0x175742c3DDD88B0192df3EcF98f180A79cb259D0", + "ADDRESS": "0xf65614d73952Be91ce0aE7Dd9cFf25Ba15bEE2f5", "OWNER": DUAL_GOVERNANCE_EXECUTORS[0], "TIMELOCK_DURATION": 2592000, "QUORUM": 2, "MEMBERS": ( - "0x74836470337Ba5d2a92fe16E44AD862E28fcf9B3", - "0xb9d82E1A49f6a66E8a07260BA05Cf9Ac8a938B1C", - "0x7dAdae4e1a0DB43F6bcfA75295666fc044605679" + "0x3D3ba54D54bbFF40F2Dfa2A8e27bD4dE3dab2951", + "0xDBfa0B8A15a503f25224fcA5F84a3853230A715C", + "0xBF048f2111497B6Df5E062811f5fC422804D4baE" ) }, "SUB_COMMITTEES": [ { - "ADDRESS": "0x74836470337Ba5d2a92fe16E44AD862E28fcf9B3", + "ADDRESS": "0x3D3ba54D54bbFF40F2Dfa2A8e27bD4dE3dab2951", "OWNER": DUAL_GOVERNANCE_EXECUTORS[0], "QUORUM": 3, "MEMBERS": ( @@ -471,7 +463,7 @@ ) }, { - "ADDRESS": "0xb9d82E1A49f6a66E8a07260BA05Cf9Ac8a938B1C", + "ADDRESS": "0xDBfa0B8A15a503f25224fcA5F84a3853230A715C", "OWNER": DUAL_GOVERNANCE_EXECUTORS[0], "QUORUM": 5, "MEMBERS": ( @@ -485,7 +477,7 @@ ) }, { - "ADDRESS": "0x7dAdae4e1a0DB43F6bcfA75295666fc044605679", + "ADDRESS": "0xBF048f2111497B6Df5E062811f5fC422804D4baE", "OWNER": DUAL_GOVERNANCE_EXECUTORS[0], "QUORUM": 3, "MEMBERS": ( @@ -498,3 +490,15 @@ } ], } + +DUAL_GOVERNANCE_VALUES = { + "MAX_TIEBREAKER_ACTIVATION_TIMEOUT": 63072000, # 2 years + "MIN_TIEBREAKER_ACTIVATION_TIMEOUT": 15768000, # 6 months + "MAX_SEALABLE_WITHDRAWAL_BLOCKERS_COUNT": 255, + "PROPOSERS_COUNT": 1, + "TIEBREAKER_DETAILS": { + "TIEBREAKER_COMMITTEE": TIEBREAKER_VALUES["CORE_COMMITTEE"]["ADDRESS"], + "TIEBREAKER_ACTIVATION_TIMEOUT": 31536000, # 1 year + "WITHDRAWAL_BLOCKERS": (WITHDRAWAL_QUEUE, VALIDATORS_EXIT_BUS_ORACLE), + } +} diff --git a/interfaces/CSExitPenalties.json b/interfaces/CSExitPenalties.json index e45976af2..12a6b410e 100644 --- a/interfaces/CSExitPenalties.json +++ b/interfaces/CSExitPenalties.json @@ -1 +1 @@ -[{"type":"constructor","inputs":[{"name":"module","type":"address","internalType":"address"},{"name":"parametersRegistry","type":"address","internalType":"address"},{"name":"strikes","type":"address","internalType":"address"}],"stateMutability":"nonpayable"},{"type":"function","name":"ACCOUNTING","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ICSAccounting"}],"stateMutability":"view"},{"type":"function","name":"MODULE","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ICSModule"}],"stateMutability":"view"},{"type":"function","name":"PARAMETERS_REGISTRY","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ICSParametersRegistry"}],"stateMutability":"view"},{"type":"function","name":"STRIKES","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"STRIKES_EXIT_TYPE_ID","inputs":[],"outputs":[{"name":"","type":"uint8","internalType":"uint8"}],"stateMutability":"view"},{"type":"function","name":"VOLUNTARY_EXIT_TYPE_ID","inputs":[],"outputs":[{"name":"","type":"uint8","internalType":"uint8"}],"stateMutability":"view"},{"type":"function","name":"getExitPenaltyInfo","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"publicKey","type":"bytes","internalType":"bytes"}],"outputs":[{"name":"","type":"tuple","internalType":"struct ExitPenaltyInfo","components":[{"name":"delayPenalty","type":"tuple","internalType":"struct MarkedUint248","components":[{"name":"value","type":"uint248","internalType":"uint248"},{"name":"isValue","type":"bool","internalType":"bool"}]},{"name":"strikesPenalty","type":"tuple","internalType":"struct MarkedUint248","components":[{"name":"value","type":"uint248","internalType":"uint248"},{"name":"isValue","type":"bool","internalType":"bool"}]},{"name":"withdrawalRequestFee","type":"tuple","internalType":"struct MarkedUint248","components":[{"name":"value","type":"uint248","internalType":"uint248"},{"name":"isValue","type":"bool","internalType":"bool"}]}]}],"stateMutability":"view"},{"type":"function","name":"isValidatorExitDelayPenaltyApplicable","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"publicKey","type":"bytes","internalType":"bytes"},{"name":"eligibleToExitInSec","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"processExitDelayReport","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"publicKey","type":"bytes","internalType":"bytes"},{"name":"eligibleToExitInSec","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"processStrikesReport","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"publicKey","type":"bytes","internalType":"bytes"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"processTriggeredExit","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"publicKey","type":"bytes","internalType":"bytes"},{"name":"withdrawalRequestPaidFee","type":"uint256","internalType":"uint256"},{"name":"exitType","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"event","name":"StrikesPenaltyProcessed","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"pubkey","type":"bytes","indexed":false,"internalType":"bytes"},{"name":"strikesPenalty","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"TriggeredExitFeeRecorded","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"exitType","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"pubkey","type":"bytes","indexed":false,"internalType":"bytes"},{"name":"withdrawalRequestFee","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ValidatorExitDelayProcessed","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"pubkey","type":"bytes","indexed":false,"internalType":"bytes"},{"name":"delayPenalty","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"error","name":"SafeCastOverflowedUintDowncast","inputs":[{"name":"bits","type":"uint8","internalType":"uint8"},{"name":"value","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"SenderIsNotModule","inputs":[]},{"type":"error","name":"SenderIsNotStrikes","inputs":[]},{"type":"error","name":"ValidatorExitDelayAlreadyReported","inputs":[]},{"type":"error","name":"ValidatorExitDelayNotApplicable","inputs":[]},{"type":"error","name":"ZeroAccountingAddress","inputs":[]},{"type":"error","name":"ZeroModuleAddress","inputs":[]},{"type":"error","name":"ZeroParametersRegistryAddress","inputs":[]},{"type":"error","name":"ZeroStrikesAddress","inputs":[]}] +[{"type":"constructor","inputs":[{"name":"module","type":"address","internalType":"address"},{"name":"parametersRegistry","type":"address","internalType":"address"},{"name":"strikes","type":"address","internalType":"address"}],"stateMutability":"nonpayable"},{"type":"function","name":"ACCOUNTING","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ICSAccounting"}],"stateMutability":"view"},{"type":"function","name":"MODULE","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ICSModule"}],"stateMutability":"view"},{"type":"function","name":"PARAMETERS_REGISTRY","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ICSParametersRegistry"}],"stateMutability":"view"},{"type":"function","name":"STRIKES","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"STRIKES_EXIT_TYPE_ID","inputs":[],"outputs":[{"name":"","type":"uint8","internalType":"uint8"}],"stateMutability":"view"},{"type":"function","name":"VOLUNTARY_EXIT_TYPE_ID","inputs":[],"outputs":[{"name":"","type":"uint8","internalType":"uint8"}],"stateMutability":"view"},{"type":"function","name":"getExitPenaltyInfo","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"publicKey","type":"bytes","internalType":"bytes"}],"outputs":[{"name":"","type":"tuple","internalType":"struct ExitPenaltyInfo","components":[{"name":"delayPenalty","type":"tuple","internalType":"struct MarkedUint248","components":[{"name":"value","type":"uint248","internalType":"uint248"},{"name":"isValue","type":"bool","internalType":"bool"}]},{"name":"strikesPenalty","type":"tuple","internalType":"struct MarkedUint248","components":[{"name":"value","type":"uint248","internalType":"uint248"},{"name":"isValue","type":"bool","internalType":"bool"}]},{"name":"withdrawalRequestFee","type":"tuple","internalType":"struct MarkedUint248","components":[{"name":"value","type":"uint248","internalType":"uint248"},{"name":"isValue","type":"bool","internalType":"bool"}]}]}],"stateMutability":"view"},{"type":"function","name":"isValidatorExitDelayPenaltyApplicable","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"publicKey","type":"bytes","internalType":"bytes"},{"name":"eligibleToExitInSec","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"processExitDelayReport","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"publicKey","type":"bytes","internalType":"bytes"},{"name":"eligibleToExitInSec","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"processStrikesReport","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"publicKey","type":"bytes","internalType":"bytes"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"processTriggeredExit","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"publicKey","type":"bytes","internalType":"bytes"},{"name":"withdrawalRequestPaidFee","type":"uint256","internalType":"uint256"},{"name":"exitType","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"event","name":"StrikesPenaltyProcessed","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"pubkey","type":"bytes","indexed":false,"internalType":"bytes"},{"name":"strikesPenalty","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"TriggeredExitFeeRecorded","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"exitType","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"pubkey","type":"bytes","indexed":false,"internalType":"bytes"},{"name":"withdrawalRequestPaidFee","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"withdrawalRequestRecordedFee","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ValidatorExitDelayProcessed","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"pubkey","type":"bytes","indexed":false,"internalType":"bytes"},{"name":"delayPenalty","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"error","name":"SafeCastOverflowedUintDowncast","inputs":[{"name":"bits","type":"uint8","internalType":"uint8"},{"name":"value","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"SenderIsNotModule","inputs":[]},{"type":"error","name":"SenderIsNotStrikes","inputs":[]},{"type":"error","name":"ValidatorExitDelayNotApplicable","inputs":[]},{"type":"error","name":"ZeroModuleAddress","inputs":[]},{"type":"error","name":"ZeroParametersRegistryAddress","inputs":[]},{"type":"error","name":"ZeroStrikesAddress","inputs":[]}] diff --git a/interfaces/CSModule.json b/interfaces/CSModule.json index 67ac8332a..0652581d9 100644 --- a/interfaces/CSModule.json +++ b/interfaces/CSModule.json @@ -1 +1 @@ -[{"type":"constructor","inputs":[{"name":"moduleType","type":"bytes32","internalType":"bytes32"},{"name":"lidoLocator","type":"address","internalType":"address"},{"name":"parametersRegistry","type":"address","internalType":"address"},{"name":"_accounting","type":"address","internalType":"address"},{"name":"exitPenalties","type":"address","internalType":"address"}],"stateMutability":"nonpayable"},{"type":"function","name":"ACCOUNTING","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ICSAccounting"}],"stateMutability":"view"},{"type":"function","name":"CREATE_NODE_OPERATOR_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"DEFAULT_ADMIN_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"DEPOSIT_SIZE","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"EXIT_PENALTIES","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ICSExitPenalties"}],"stateMutability":"view"},{"type":"function","name":"LIDO_LOCATOR","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ILidoLocator"}],"stateMutability":"view"},{"type":"function","name":"PARAMETERS_REGISTRY","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ICSParametersRegistry"}],"stateMutability":"view"},{"type":"function","name":"PAUSE_INFINITELY","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"PAUSE_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"QUEUE_LEGACY_PRIORITY","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"QUEUE_LOWEST_PRIORITY","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"RECOVERER_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"REPORT_EL_REWARDS_STEALING_PENALTY_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"RESUME_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"SETTLE_EL_REWARDS_STEALING_PENALTY_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"STAKING_ROUTER_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"STETH","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IStETH"}],"stateMutability":"view"},{"type":"function","name":"VERIFIER_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"accounting","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ICSAccounting"}],"stateMutability":"view"},{"type":"function","name":"addValidatorKeysETH","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"keysCount","type":"uint256","internalType":"uint256"},{"name":"publicKeys","type":"bytes","internalType":"bytes"},{"name":"signatures","type":"bytes","internalType":"bytes"}],"outputs":[],"stateMutability":"payable"},{"type":"function","name":"addValidatorKeysStETH","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"keysCount","type":"uint256","internalType":"uint256"},{"name":"publicKeys","type":"bytes","internalType":"bytes"},{"name":"signatures","type":"bytes","internalType":"bytes"},{"name":"permit","type":"tuple","internalType":"struct ICSAccounting.PermitInput","components":[{"name":"value","type":"uint256","internalType":"uint256"},{"name":"deadline","type":"uint256","internalType":"uint256"},{"name":"v","type":"uint8","internalType":"uint8"},{"name":"r","type":"bytes32","internalType":"bytes32"},{"name":"s","type":"bytes32","internalType":"bytes32"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"addValidatorKeysWstETH","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"keysCount","type":"uint256","internalType":"uint256"},{"name":"publicKeys","type":"bytes","internalType":"bytes"},{"name":"signatures","type":"bytes","internalType":"bytes"},{"name":"permit","type":"tuple","internalType":"struct ICSAccounting.PermitInput","components":[{"name":"value","type":"uint256","internalType":"uint256"},{"name":"deadline","type":"uint256","internalType":"uint256"},{"name":"v","type":"uint8","internalType":"uint8"},{"name":"r","type":"bytes32","internalType":"bytes32"},{"name":"s","type":"bytes32","internalType":"bytes32"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"cancelELRewardsStealingPenalty","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"amount","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"changeNodeOperatorRewardAddress","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"newAddress","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"cleanDepositQueue","inputs":[{"name":"maxItems","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"removed","type":"uint256","internalType":"uint256"},{"name":"lastRemovedAtDepth","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"compensateELRewardsStealingPenalty","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"payable"},{"type":"function","name":"confirmNodeOperatorManagerAddressChange","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"confirmNodeOperatorRewardAddressChange","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"createNodeOperator","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"managementProperties","type":"tuple","internalType":"struct NodeOperatorManagementProperties","components":[{"name":"managerAddress","type":"address","internalType":"address"},{"name":"rewardAddress","type":"address","internalType":"address"},{"name":"extendedManagerPermissions","type":"bool","internalType":"bool"}]},{"name":"referrer","type":"address","internalType":"address"}],"outputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"decreaseVettedSigningKeysCount","inputs":[{"name":"nodeOperatorIds","type":"bytes","internalType":"bytes"},{"name":"vettedSigningKeysCounts","type":"bytes","internalType":"bytes"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"depositQueueItem","inputs":[{"name":"queuePriority","type":"uint256","internalType":"uint256"},{"name":"index","type":"uint128","internalType":"uint128"}],"outputs":[{"name":"","type":"uint256","internalType":"Batch"}],"stateMutability":"view"},{"type":"function","name":"depositQueuePointers","inputs":[{"name":"queuePriority","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"head","type":"uint128","internalType":"uint128"},{"name":"tail","type":"uint128","internalType":"uint128"}],"stateMutability":"view"},{"type":"function","name":"exitDeadlineThreshold","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"finalizeUpgradeV2","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"getActiveNodeOperatorsCount","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getInitializedVersion","inputs":[],"outputs":[{"name":"","type":"uint64","internalType":"uint64"}],"stateMutability":"view"},{"type":"function","name":"getNodeOperator","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"tuple","internalType":"struct NodeOperator","components":[{"name":"totalAddedKeys","type":"uint32","internalType":"uint32"},{"name":"totalWithdrawnKeys","type":"uint32","internalType":"uint32"},{"name":"totalDepositedKeys","type":"uint32","internalType":"uint32"},{"name":"totalVettedKeys","type":"uint32","internalType":"uint32"},{"name":"stuckValidatorsCount","type":"uint32","internalType":"uint32"},{"name":"depositableValidatorsCount","type":"uint32","internalType":"uint32"},{"name":"targetLimit","type":"uint32","internalType":"uint32"},{"name":"targetLimitMode","type":"uint8","internalType":"uint8"},{"name":"totalExitedKeys","type":"uint32","internalType":"uint32"},{"name":"enqueuedCount","type":"uint32","internalType":"uint32"},{"name":"managerAddress","type":"address","internalType":"address"},{"name":"proposedManagerAddress","type":"address","internalType":"address"},{"name":"rewardAddress","type":"address","internalType":"address"},{"name":"proposedRewardAddress","type":"address","internalType":"address"},{"name":"extendedManagerPermissions","type":"bool","internalType":"bool"},{"name":"usedPriorityQueue","type":"bool","internalType":"bool"}]}],"stateMutability":"view"},{"type":"function","name":"getNodeOperatorIds","inputs":[{"name":"offset","type":"uint256","internalType":"uint256"},{"name":"limit","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"nodeOperatorIds","type":"uint256[]","internalType":"uint256[]"}],"stateMutability":"view"},{"type":"function","name":"getNodeOperatorIsActive","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"getNodeOperatorManagementProperties","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"tuple","internalType":"struct NodeOperatorManagementProperties","components":[{"name":"managerAddress","type":"address","internalType":"address"},{"name":"rewardAddress","type":"address","internalType":"address"},{"name":"extendedManagerPermissions","type":"bool","internalType":"bool"}]}],"stateMutability":"view"},{"type":"function","name":"getNodeOperatorNonWithdrawnKeys","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getNodeOperatorSummary","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"targetLimitMode","type":"uint256","internalType":"uint256"},{"name":"targetValidatorsCount","type":"uint256","internalType":"uint256"},{"name":"stuckValidatorsCount","type":"uint256","internalType":"uint256"},{"name":"refundedValidatorsCount","type":"uint256","internalType":"uint256"},{"name":"stuckPenaltyEndTimestamp","type":"uint256","internalType":"uint256"},{"name":"totalExitedValidators","type":"uint256","internalType":"uint256"},{"name":"totalDepositedValidators","type":"uint256","internalType":"uint256"},{"name":"depositableValidatorsCount","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getNodeOperatorTotalDepositedKeys","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"totalDepositedKeys","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getNodeOperatorsCount","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getNonce","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getResumeSinceTimestamp","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getRoleAdmin","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"getRoleMember","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"index","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"getRoleMemberCount","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getSigningKeys","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"startIndex","type":"uint256","internalType":"uint256"},{"name":"keysCount","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bytes","internalType":"bytes"}],"stateMutability":"view"},{"type":"function","name":"getSigningKeysWithSignatures","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"startIndex","type":"uint256","internalType":"uint256"},{"name":"keysCount","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"keys","type":"bytes","internalType":"bytes"},{"name":"signatures","type":"bytes","internalType":"bytes"}],"stateMutability":"view"},{"type":"function","name":"getStakingModuleSummary","inputs":[],"outputs":[{"name":"totalExitedValidators","type":"uint256","internalType":"uint256"},{"name":"totalDepositedValidators","type":"uint256","internalType":"uint256"},{"name":"depositableValidatorsCount","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getType","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"grantRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"hasRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"initialize","inputs":[{"name":"admin","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"isPaused","inputs":[],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"isValidatorExitDelayPenaltyApplicable","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"","type":"uint256","internalType":"uint256"},{"name":"publicKey","type":"bytes","internalType":"bytes"},{"name":"eligibleToExitInSec","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"isValidatorWithdrawn","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"keyIndex","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"legacyQueue","inputs":[],"outputs":[{"name":"head","type":"uint128","internalType":"uint128"},{"name":"tail","type":"uint128","internalType":"uint128"}],"stateMutability":"view"},{"type":"function","name":"migrateToPriorityQueue","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"obtainDepositData","inputs":[{"name":"depositsCount","type":"uint256","internalType":"uint256"},{"name":"","type":"bytes","internalType":"bytes"}],"outputs":[{"name":"publicKeys","type":"bytes","internalType":"bytes"},{"name":"signatures","type":"bytes","internalType":"bytes"}],"stateMutability":"nonpayable"},{"type":"function","name":"onExitedAndStuckValidatorsCountsUpdated","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"onRewardsMinted","inputs":[{"name":"totalShares","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"onValidatorExitTriggered","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"publicKey","type":"bytes","internalType":"bytes"},{"name":"withdrawalRequestPaidFee","type":"uint256","internalType":"uint256"},{"name":"exitType","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"onWithdrawalCredentialsChanged","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"pauseFor","inputs":[{"name":"duration","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"proposeNodeOperatorManagerAddressChange","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"proposedAddress","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"proposeNodeOperatorRewardAddressChange","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"proposedAddress","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"recoverERC1155","inputs":[{"name":"token","type":"address","internalType":"address"},{"name":"tokenId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"recoverERC20","inputs":[{"name":"token","type":"address","internalType":"address"},{"name":"amount","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"recoverERC721","inputs":[{"name":"token","type":"address","internalType":"address"},{"name":"tokenId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"recoverEther","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"removeKeys","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"startIndex","type":"uint256","internalType":"uint256"},{"name":"keysCount","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"renounceRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"callerConfirmation","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"reportELRewardsStealingPenalty","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"blockHash","type":"bytes32","internalType":"bytes32"},{"name":"amount","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"reportValidatorExitDelay","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"","type":"uint256","internalType":"uint256"},{"name":"publicKey","type":"bytes","internalType":"bytes"},{"name":"eligibleToExitInSec","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"resetNodeOperatorManagerAddress","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"resume","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"revokeRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"settleELRewardsStealingPenalty","inputs":[{"name":"nodeOperatorIds","type":"uint256[]","internalType":"uint256[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"submitWithdrawals","inputs":[{"name":"withdrawalsInfo","type":"tuple[]","internalType":"struct ValidatorWithdrawalInfo[]","components":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"keyIndex","type":"uint256","internalType":"uint256"},{"name":"amount","type":"uint256","internalType":"uint256"},{"name":"isSlashed","type":"bool","internalType":"bool"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"supportsInterface","inputs":[{"name":"interfaceId","type":"bytes4","internalType":"bytes4"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"unsafeUpdateValidatorsCount","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"exitedValidatorsKeysCount","type":"uint256","internalType":"uint256"},{"name":"stuckValidatorsKeysCount","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateDepositableValidatorsCount","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateExitedValidatorsCount","inputs":[{"name":"nodeOperatorIds","type":"bytes","internalType":"bytes"},{"name":"exitedValidatorsCounts","type":"bytes","internalType":"bytes"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateTargetValidatorsLimits","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"targetLimitMode","type":"uint256","internalType":"uint256"},{"name":"targetLimit","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"event","name":"BatchEnqueued","inputs":[{"name":"queuePriority","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"count","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"DelayedValidatorExitPenalized","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"penaltyValue","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"DepositableSigningKeysCountChanged","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"depositableKeysCount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"DepositedSigningKeysCountChanged","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"depositedKeysCount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ELRewardsStealingPenaltyCancelled","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ELRewardsStealingPenaltyCompensated","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ELRewardsStealingPenaltyReported","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"proposedBlockHash","type":"bytes32","indexed":false,"internalType":"bytes32"},{"name":"stolenAmount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ELRewardsStealingPenaltySettled","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ERC1155Recovered","inputs":[{"name":"token","type":"address","indexed":true,"internalType":"address"},{"name":"tokenId","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"recipient","type":"address","indexed":true,"internalType":"address"},{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ERC20Recovered","inputs":[{"name":"token","type":"address","indexed":true,"internalType":"address"},{"name":"recipient","type":"address","indexed":true,"internalType":"address"},{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ERC721Recovered","inputs":[{"name":"token","type":"address","indexed":true,"internalType":"address"},{"name":"tokenId","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"recipient","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"EtherRecovered","inputs":[{"name":"recipient","type":"address","indexed":true,"internalType":"address"},{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ExitedSigningKeysCountChanged","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"exitedKeysCount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"Initialized","inputs":[{"name":"version","type":"uint64","indexed":false,"internalType":"uint64"}],"anonymous":false},{"type":"event","name":"KeyRemovalChargeApplied","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"NodeOperatorAdded","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"managerAddress","type":"address","indexed":true,"internalType":"address"},{"name":"rewardAddress","type":"address","indexed":true,"internalType":"address"},{"name":"extendedManagerPermissions","type":"bool","indexed":false,"internalType":"bool"}],"anonymous":false},{"type":"event","name":"NodeOperatorManagerAddressChangeProposed","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"oldProposedAddress","type":"address","indexed":true,"internalType":"address"},{"name":"newProposedAddress","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"NodeOperatorManagerAddressChanged","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"oldAddress","type":"address","indexed":true,"internalType":"address"},{"name":"newAddress","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"NodeOperatorRewardAddressChangeProposed","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"oldProposedAddress","type":"address","indexed":true,"internalType":"address"},{"name":"newProposedAddress","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"NodeOperatorRewardAddressChanged","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"oldAddress","type":"address","indexed":true,"internalType":"address"},{"name":"newAddress","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"NonceChanged","inputs":[{"name":"nonce","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"Paused","inputs":[{"name":"duration","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ReferrerSet","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"referrer","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"Resumed","inputs":[],"anonymous":false},{"type":"event","name":"RoleAdminChanged","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"previousAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"newAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"}],"anonymous":false},{"type":"event","name":"RoleGranted","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"RoleRevoked","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"SigningKeyAdded","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"pubkey","type":"bytes","indexed":false,"internalType":"bytes"}],"anonymous":false},{"type":"event","name":"SigningKeyRemoved","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"pubkey","type":"bytes","indexed":false,"internalType":"bytes"}],"anonymous":false},{"type":"event","name":"StETHSharesRecovered","inputs":[{"name":"recipient","type":"address","indexed":true,"internalType":"address"},{"name":"shares","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"TargetValidatorsCountChanged","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"targetLimitMode","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"targetValidatorsCount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"TotalSigningKeysCountChanged","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"totalKeysCount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"VettedSigningKeysCountChanged","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"vettedKeysCount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"VettedSigningKeysCountDecreased","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"WithdrawalSubmitted","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"keyIndex","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"pubkey","type":"bytes","indexed":false,"internalType":"bytes"}],"anonymous":false},{"type":"error","name":"AccessControlBadConfirmation","inputs":[]},{"type":"error","name":"AccessControlUnauthorizedAccount","inputs":[{"name":"account","type":"address","internalType":"address"},{"name":"neededRole","type":"bytes32","internalType":"bytes32"}]},{"type":"error","name":"AlreadyProposed","inputs":[]},{"type":"error","name":"AlreadyWithdrawn","inputs":[]},{"type":"error","name":"CannotAddKeys","inputs":[]},{"type":"error","name":"EmptyKey","inputs":[]},{"type":"error","name":"ExitedKeysDecrease","inputs":[]},{"type":"error","name":"ExitedKeysHigherThanTotalDeposited","inputs":[]},{"type":"error","name":"FailedToSendEther","inputs":[]},{"type":"error","name":"InvalidAmount","inputs":[]},{"type":"error","name":"InvalidInitialization","inputs":[]},{"type":"error","name":"InvalidInput","inputs":[]},{"type":"error","name":"InvalidKeysCount","inputs":[]},{"type":"error","name":"InvalidLength","inputs":[]},{"type":"error","name":"InvalidReportData","inputs":[]},{"type":"error","name":"InvalidVetKeysPointer","inputs":[]},{"type":"error","name":"KeysLimitExceeded","inputs":[]},{"type":"error","name":"MethodCallIsNotAllowed","inputs":[]},{"type":"error","name":"NodeOperatorDoesNotExist","inputs":[]},{"type":"error","name":"NotAllowedToRecover","inputs":[]},{"type":"error","name":"NotEnoughKeys","inputs":[]},{"type":"error","name":"NotInitializing","inputs":[]},{"type":"error","name":"PauseUntilMustBeInFuture","inputs":[]},{"type":"error","name":"PausedExpected","inputs":[]},{"type":"error","name":"PriorityQueueAlreadyUsed","inputs":[]},{"type":"error","name":"QueueIsEmpty","inputs":[]},{"type":"error","name":"QueueLookupNoLimit","inputs":[]},{"type":"error","name":"ResumedExpected","inputs":[]},{"type":"error","name":"SameAddress","inputs":[]},{"type":"error","name":"SenderIsNotEligible","inputs":[]},{"type":"error","name":"SenderIsNotManagerAddress","inputs":[]},{"type":"error","name":"SenderIsNotProposedAddress","inputs":[]},{"type":"error","name":"SenderIsNotRewardAddress","inputs":[]},{"type":"error","name":"SigningKeysInvalidOffset","inputs":[]},{"type":"error","name":"ZeroAccountingAddress","inputs":[]},{"type":"error","name":"ZeroAdminAddress","inputs":[]},{"type":"error","name":"ZeroExitPenaltiesAddress","inputs":[]},{"type":"error","name":"ZeroLocatorAddress","inputs":[]},{"type":"error","name":"ZeroParametersRegistryAddress","inputs":[]},{"type":"error","name":"ZeroPauseDuration","inputs":[]},{"type":"error","name":"ZeroRewardAddress","inputs":[]},{"type":"error","name":"ZeroSenderAddress","inputs":[]}] +[{"inputs":[{"internalType":"bytes32","name":"moduleType","type":"bytes32"},{"internalType":"address","name":"lidoLocator","type":"address"},{"internalType":"address","name":"parametersRegistry","type":"address"},{"internalType":"address","name":"_accounting","type":"address"},{"internalType":"address","name":"exitPenalties","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"inputs":[],"name":"AlreadyProposed","type":"error"},{"inputs":[],"name":"CannotAddKeys","type":"error"},{"inputs":[],"name":"EmptyKey","type":"error"},{"inputs":[],"name":"ExitedKeysDecrease","type":"error"},{"inputs":[],"name":"ExitedKeysHigherThanTotalDeposited","type":"error"},{"inputs":[],"name":"FailedToSendEther","type":"error"},{"inputs":[],"name":"InvalidAmount","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"InvalidInput","type":"error"},{"inputs":[],"name":"InvalidKeysCount","type":"error"},{"inputs":[],"name":"InvalidLength","type":"error"},{"inputs":[],"name":"InvalidReportData","type":"error"},{"inputs":[],"name":"InvalidVetKeysPointer","type":"error"},{"inputs":[],"name":"KeysLimitExceeded","type":"error"},{"inputs":[],"name":"MethodCallIsNotAllowed","type":"error"},{"inputs":[],"name":"NoQueuedKeysToMigrate","type":"error"},{"inputs":[],"name":"NodeOperatorDoesNotExist","type":"error"},{"inputs":[],"name":"NotAllowedToRecover","type":"error"},{"inputs":[],"name":"NotEligibleForPriorityQueue","type":"error"},{"inputs":[],"name":"NotEnoughKeys","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[],"name":"PauseUntilMustBeInFuture","type":"error"},{"inputs":[],"name":"PausedExpected","type":"error"},{"inputs":[],"name":"PriorityQueueAlreadyUsed","type":"error"},{"inputs":[],"name":"PriorityQueueMaxDepositsUsed","type":"error"},{"inputs":[],"name":"QueueIsEmpty","type":"error"},{"inputs":[],"name":"QueueLookupNoLimit","type":"error"},{"inputs":[],"name":"ResumedExpected","type":"error"},{"inputs":[],"name":"SameAddress","type":"error"},{"inputs":[],"name":"SenderIsNotEligible","type":"error"},{"inputs":[],"name":"SenderIsNotManagerAddress","type":"error"},{"inputs":[],"name":"SenderIsNotProposedAddress","type":"error"},{"inputs":[],"name":"SenderIsNotRewardAddress","type":"error"},{"inputs":[],"name":"SigningKeysInvalidOffset","type":"error"},{"inputs":[],"name":"ZeroAccountingAddress","type":"error"},{"inputs":[],"name":"ZeroAdminAddress","type":"error"},{"inputs":[],"name":"ZeroExitPenaltiesAddress","type":"error"},{"inputs":[],"name":"ZeroLocatorAddress","type":"error"},{"inputs":[],"name":"ZeroParametersRegistryAddress","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRewardAddress","type":"error"},{"inputs":[],"name":"ZeroSenderAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"queuePriority","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"nodeOperatorId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"count","type":"uint256"}],"name":"BatchEnqueued","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"nodeOperatorId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"depositableKeysCount","type":"uint256"}],"name":"DepositableSigningKeysCountChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"nodeOperatorId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"depositedKeysCount","type":"uint256"}],"name":"DepositedSigningKeysCountChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"nodeOperatorId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ELRewardsStealingPenaltyCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"nodeOperatorId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ELRewardsStealingPenaltyCompensated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"nodeOperatorId","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"proposedBlockHash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"stolenAmount","type":"uint256"}],"name":"ELRewardsStealingPenaltyReported","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"nodeOperatorId","type":"uint256"}],"name":"ELRewardsStealingPenaltySettled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ERC1155Recovered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ERC20Recovered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"}],"name":"ERC721Recovered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"EtherRecovered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"nodeOperatorId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"exitedKeysCount","type":"uint256"}],"name":"ExitedSigningKeysCountChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"nodeOperatorId","type":"uint256"}],"name":"KeyRemovalChargeApplied","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"nodeOperatorId","type":"uint256"},{"indexed":true,"internalType":"address","name":"managerAddress","type":"address"},{"indexed":true,"internalType":"address","name":"rewardAddress","type":"address"},{"indexed":false,"internalType":"bool","name":"extendedManagerPermissions","type":"bool"}],"name":"NodeOperatorAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"nodeOperatorId","type":"uint256"},{"indexed":true,"internalType":"address","name":"oldProposedAddress","type":"address"},{"indexed":true,"internalType":"address","name":"newProposedAddress","type":"address"}],"name":"NodeOperatorManagerAddressChangeProposed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"nodeOperatorId","type":"uint256"},{"indexed":true,"internalType":"address","name":"oldAddress","type":"address"},{"indexed":true,"internalType":"address","name":"newAddress","type":"address"}],"name":"NodeOperatorManagerAddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"nodeOperatorId","type":"uint256"},{"indexed":true,"internalType":"address","name":"oldProposedAddress","type":"address"},{"indexed":true,"internalType":"address","name":"newProposedAddress","type":"address"}],"name":"NodeOperatorRewardAddressChangeProposed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"nodeOperatorId","type":"uint256"},{"indexed":true,"internalType":"address","name":"oldAddress","type":"address"},{"indexed":true,"internalType":"address","name":"newAddress","type":"address"}],"name":"NodeOperatorRewardAddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"NonceChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"duration","type":"uint256"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"nodeOperatorId","type":"uint256"},{"indexed":true,"internalType":"address","name":"referrer","type":"address"}],"name":"ReferrerSet","type":"event"},{"anonymous":false,"inputs":[],"name":"Resumed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"nodeOperatorId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"pubkey","type":"bytes"}],"name":"SigningKeyAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"nodeOperatorId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"pubkey","type":"bytes"}],"name":"SigningKeyRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"StETHSharesRecovered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"nodeOperatorId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"targetLimitMode","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"targetValidatorsCount","type":"uint256"}],"name":"TargetValidatorsCountChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"nodeOperatorId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalKeysCount","type":"uint256"}],"name":"TotalSigningKeysCountChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"nodeOperatorId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"vettedKeysCount","type":"uint256"}],"name":"VettedSigningKeysCountChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"nodeOperatorId","type":"uint256"}],"name":"VettedSigningKeysCountDecreased","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"nodeOperatorId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"keyIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"pubkey","type":"bytes"}],"name":"WithdrawalSubmitted","type":"event"},{"inputs":[],"name":"ACCOUNTING","outputs":[{"internalType":"contract ICSAccounting","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CREATE_NODE_OPERATOR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEPOSIT_SIZE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EXIT_PENALTIES","outputs":[{"internalType":"contract ICSExitPenalties","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FEE_DISTRIBUTOR","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LIDO_LOCATOR","outputs":[{"internalType":"contract ILidoLocator","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PARAMETERS_REGISTRY","outputs":[{"internalType":"contract ICSParametersRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAUSE_INFINITELY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAUSE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"QUEUE_LEGACY_PRIORITY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"QUEUE_LOWEST_PRIORITY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RECOVERER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REPORT_EL_REWARDS_STEALING_PENALTY_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RESUME_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SETTLE_EL_REWARDS_STEALING_PENALTY_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STAKING_ROUTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STETH","outputs":[{"internalType":"contract IStETH","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VERIFIER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"accounting","outputs":[{"internalType":"contract ICSAccounting","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"nodeOperatorId","type":"uint256"},{"internalType":"uint256","name":"keysCount","type":"uint256"},{"internalType":"bytes","name":"publicKeys","type":"bytes"},{"internalType":"bytes","name":"signatures","type":"bytes"}],"name":"addValidatorKeysETH","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"nodeOperatorId","type":"uint256"},{"internalType":"uint256","name":"keysCount","type":"uint256"},{"internalType":"bytes","name":"publicKeys","type":"bytes"},{"internalType":"bytes","name":"signatures","type":"bytes"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct ICSAccounting.PermitInput","name":"permit","type":"tuple"}],"name":"addValidatorKeysStETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"nodeOperatorId","type":"uint256"},{"internalType":"uint256","name":"keysCount","type":"uint256"},{"internalType":"bytes","name":"publicKeys","type":"bytes"},{"internalType":"bytes","name":"signatures","type":"bytes"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct ICSAccounting.PermitInput","name":"permit","type":"tuple"}],"name":"addValidatorKeysWstETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nodeOperatorId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"cancelELRewardsStealingPenalty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nodeOperatorId","type":"uint256"},{"internalType":"address","name":"newAddress","type":"address"}],"name":"changeNodeOperatorRewardAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"maxItems","type":"uint256"}],"name":"cleanDepositQueue","outputs":[{"internalType":"uint256","name":"removed","type":"uint256"},{"internalType":"uint256","name":"lastRemovedAtDepth","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nodeOperatorId","type":"uint256"}],"name":"compensateELRewardsStealingPenalty","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nodeOperatorId","type":"uint256"}],"name":"confirmNodeOperatorManagerAddressChange","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nodeOperatorId","type":"uint256"}],"name":"confirmNodeOperatorRewardAddressChange","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"components":[{"internalType":"address","name":"managerAddress","type":"address"},{"internalType":"address","name":"rewardAddress","type":"address"},{"internalType":"bool","name":"extendedManagerPermissions","type":"bool"}],"internalType":"struct NodeOperatorManagementProperties","name":"managementProperties","type":"tuple"},{"internalType":"address","name":"referrer","type":"address"}],"name":"createNodeOperator","outputs":[{"internalType":"uint256","name":"nodeOperatorId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"nodeOperatorIds","type":"bytes"},{"internalType":"bytes","name":"vettedSigningKeysCounts","type":"bytes"}],"name":"decreaseVettedSigningKeysCount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"queuePriority","type":"uint256"},{"internalType":"uint128","name":"index","type":"uint128"}],"name":"depositQueueItem","outputs":[{"internalType":"Batch","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"queuePriority","type":"uint256"}],"name":"depositQueuePointers","outputs":[{"internalType":"uint128","name":"head","type":"uint128"},{"internalType":"uint128","name":"tail","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nodeOperatorId","type":"uint256"}],"name":"exitDeadlineThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"finalizeUpgradeV2","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getActiveNodeOperatorsCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getInitializedVersion","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nodeOperatorId","type":"uint256"}],"name":"getNodeOperator","outputs":[{"components":[{"internalType":"uint32","name":"totalAddedKeys","type":"uint32"},{"internalType":"uint32","name":"totalWithdrawnKeys","type":"uint32"},{"internalType":"uint32","name":"totalDepositedKeys","type":"uint32"},{"internalType":"uint32","name":"totalVettedKeys","type":"uint32"},{"internalType":"uint32","name":"stuckValidatorsCount","type":"uint32"},{"internalType":"uint32","name":"depositableValidatorsCount","type":"uint32"},{"internalType":"uint32","name":"targetLimit","type":"uint32"},{"internalType":"uint8","name":"targetLimitMode","type":"uint8"},{"internalType":"uint32","name":"totalExitedKeys","type":"uint32"},{"internalType":"uint32","name":"enqueuedCount","type":"uint32"},{"internalType":"address","name":"managerAddress","type":"address"},{"internalType":"address","name":"proposedManagerAddress","type":"address"},{"internalType":"address","name":"rewardAddress","type":"address"},{"internalType":"address","name":"proposedRewardAddress","type":"address"},{"internalType":"bool","name":"extendedManagerPermissions","type":"bool"},{"internalType":"bool","name":"usedPriorityQueue","type":"bool"}],"internalType":"struct NodeOperator","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"offset","type":"uint256"},{"internalType":"uint256","name":"limit","type":"uint256"}],"name":"getNodeOperatorIds","outputs":[{"internalType":"uint256[]","name":"nodeOperatorIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nodeOperatorId","type":"uint256"}],"name":"getNodeOperatorIsActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nodeOperatorId","type":"uint256"}],"name":"getNodeOperatorManagementProperties","outputs":[{"components":[{"internalType":"address","name":"managerAddress","type":"address"},{"internalType":"address","name":"rewardAddress","type":"address"},{"internalType":"bool","name":"extendedManagerPermissions","type":"bool"}],"internalType":"struct NodeOperatorManagementProperties","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nodeOperatorId","type":"uint256"}],"name":"getNodeOperatorNonWithdrawnKeys","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nodeOperatorId","type":"uint256"}],"name":"getNodeOperatorOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nodeOperatorId","type":"uint256"}],"name":"getNodeOperatorSummary","outputs":[{"internalType":"uint256","name":"targetLimitMode","type":"uint256"},{"internalType":"uint256","name":"targetValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"stuckValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"refundedValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"stuckPenaltyEndTimestamp","type":"uint256"},{"internalType":"uint256","name":"totalExitedValidators","type":"uint256"},{"internalType":"uint256","name":"totalDepositedValidators","type":"uint256"},{"internalType":"uint256","name":"depositableValidatorsCount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nodeOperatorId","type":"uint256"}],"name":"getNodeOperatorTotalDepositedKeys","outputs":[{"internalType":"uint256","name":"totalDepositedKeys","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNodeOperatorsCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getResumeSinceTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nodeOperatorId","type":"uint256"},{"internalType":"uint256","name":"startIndex","type":"uint256"},{"internalType":"uint256","name":"keysCount","type":"uint256"}],"name":"getSigningKeys","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nodeOperatorId","type":"uint256"},{"internalType":"uint256","name":"startIndex","type":"uint256"},{"internalType":"uint256","name":"keysCount","type":"uint256"}],"name":"getSigningKeysWithSignatures","outputs":[{"internalType":"bytes","name":"keys","type":"bytes"},{"internalType":"bytes","name":"signatures","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStakingModuleSummary","outputs":[{"internalType":"uint256","name":"totalExitedValidators","type":"uint256"},{"internalType":"uint256","name":"totalDepositedValidators","type":"uint256"},{"internalType":"uint256","name":"depositableValidatorsCount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getType","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nodeOperatorId","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"publicKey","type":"bytes"},{"internalType":"uint256","name":"eligibleToExitInSec","type":"uint256"}],"name":"isValidatorExitDelayPenaltyApplicable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nodeOperatorId","type":"uint256"},{"internalType":"uint256","name":"keyIndex","type":"uint256"}],"name":"isValidatorWithdrawn","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nodeOperatorId","type":"uint256"}],"name":"migrateToPriorityQueue","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"depositsCount","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"obtainDepositData","outputs":[{"internalType":"bytes","name":"publicKeys","type":"bytes"},{"internalType":"bytes","name":"signatures","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"onExitedAndStuckValidatorsCountsUpdated","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"totalShares","type":"uint256"}],"name":"onRewardsMinted","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nodeOperatorId","type":"uint256"},{"internalType":"bytes","name":"publicKey","type":"bytes"},{"internalType":"uint256","name":"withdrawalRequestPaidFee","type":"uint256"},{"internalType":"uint256","name":"exitType","type":"uint256"}],"name":"onValidatorExitTriggered","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"onWithdrawalCredentialsChanged","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"duration","type":"uint256"}],"name":"pauseFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nodeOperatorId","type":"uint256"},{"internalType":"address","name":"proposedAddress","type":"address"}],"name":"proposeNodeOperatorManagerAddressChange","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nodeOperatorId","type":"uint256"},{"internalType":"address","name":"proposedAddress","type":"address"}],"name":"proposeNodeOperatorRewardAddressChange","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"recoverERC1155","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"recoverERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"recoverERC721","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"recoverEther","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nodeOperatorId","type":"uint256"},{"internalType":"uint256","name":"startIndex","type":"uint256"},{"internalType":"uint256","name":"keysCount","type":"uint256"}],"name":"removeKeys","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nodeOperatorId","type":"uint256"},{"internalType":"bytes32","name":"blockHash","type":"bytes32"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"reportELRewardsStealingPenalty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nodeOperatorId","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"publicKey","type":"bytes"},{"internalType":"uint256","name":"eligibleToExitInSec","type":"uint256"}],"name":"reportValidatorExitDelay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nodeOperatorId","type":"uint256"}],"name":"resetNodeOperatorManagerAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"resume","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"nodeOperatorIds","type":"uint256[]"}],"name":"settleELRewardsStealingPenalty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"nodeOperatorId","type":"uint256"},{"internalType":"uint256","name":"keyIndex","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct ValidatorWithdrawalInfo[]","name":"withdrawalsInfo","type":"tuple[]"}],"name":"submitWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nodeOperatorId","type":"uint256"},{"internalType":"uint256","name":"exitedValidatorsKeysCount","type":"uint256"}],"name":"unsafeUpdateValidatorsCount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nodeOperatorId","type":"uint256"}],"name":"updateDepositableValidatorsCount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"nodeOperatorIds","type":"bytes"},{"internalType":"bytes","name":"exitedValidatorsCounts","type":"bytes"}],"name":"updateExitedValidatorsCount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nodeOperatorId","type":"uint256"},{"internalType":"uint256","name":"targetLimitMode","type":"uint256"},{"internalType":"uint256","name":"targetLimit","type":"uint256"}],"name":"updateTargetValidatorsLimits","outputs":[],"stateMutability":"nonpayable","type":"function"}] diff --git a/interfaces/CSParametersRegistry.json b/interfaces/CSParametersRegistry.json new file mode 100644 index 000000000..8a41979fb --- /dev/null +++ b/interfaces/CSParametersRegistry.json @@ -0,0 +1 @@ +[{"type":"constructor","inputs":[{"name":"queueLowestPriority","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"DEFAULT_ADMIN_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"QUEUE_LEGACY_PRIORITY","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"QUEUE_LOWEST_PRIORITY","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"defaultAllowedExitDelay","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"defaultBadPerformancePenalty","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"defaultElRewardsStealingAdditionalFine","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"defaultExitDelayPenalty","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"defaultKeyRemovalCharge","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"defaultKeysLimit","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"defaultMaxWithdrawalRequestFee","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"defaultPerformanceCoefficients","inputs":[],"outputs":[{"name":"attestationsWeight","type":"uint32","internalType":"uint32"},{"name":"blocksWeight","type":"uint32","internalType":"uint32"},{"name":"syncWeight","type":"uint32","internalType":"uint32"}],"stateMutability":"view"},{"type":"function","name":"defaultPerformanceLeeway","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"defaultQueueConfig","inputs":[],"outputs":[{"name":"priority","type":"uint32","internalType":"uint32"},{"name":"maxDeposits","type":"uint32","internalType":"uint32"}],"stateMutability":"view"},{"type":"function","name":"defaultRewardShare","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"defaultStrikesParams","inputs":[],"outputs":[{"name":"lifetime","type":"uint32","internalType":"uint32"},{"name":"threshold","type":"uint32","internalType":"uint32"}],"stateMutability":"view"},{"type":"function","name":"getAllowedExitDelay","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"delay","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getBadPerformancePenalty","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"penalty","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getElRewardsStealingAdditionalFine","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"fine","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getExitDelayPenalty","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"penalty","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getInitializedVersion","inputs":[],"outputs":[{"name":"","type":"uint64","internalType":"uint64"}],"stateMutability":"view"},{"type":"function","name":"getKeyRemovalCharge","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"keyRemovalCharge","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getKeysLimit","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"limit","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getMaxWithdrawalRequestFee","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"fee","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getPerformanceCoefficients","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"attestationsWeight","type":"uint256","internalType":"uint256"},{"name":"blocksWeight","type":"uint256","internalType":"uint256"},{"name":"syncWeight","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getPerformanceLeewayData","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"data","type":"tuple[]","internalType":"struct ICSParametersRegistry.KeyNumberValueInterval[]","components":[{"name":"minKeyNumber","type":"uint256","internalType":"uint256"},{"name":"value","type":"uint256","internalType":"uint256"}]}],"stateMutability":"view"},{"type":"function","name":"getQueueConfig","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"queuePriority","type":"uint32","internalType":"uint32"},{"name":"maxDeposits","type":"uint32","internalType":"uint32"}],"stateMutability":"view"},{"type":"function","name":"getRewardShareData","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"data","type":"tuple[]","internalType":"struct ICSParametersRegistry.KeyNumberValueInterval[]","components":[{"name":"minKeyNumber","type":"uint256","internalType":"uint256"},{"name":"value","type":"uint256","internalType":"uint256"}]}],"stateMutability":"view"},{"type":"function","name":"getRoleAdmin","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"getRoleMember","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"index","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"getRoleMemberCount","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getStrikesParams","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"lifetime","type":"uint256","internalType":"uint256"},{"name":"threshold","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"grantRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"hasRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"initialize","inputs":[{"name":"admin","type":"address","internalType":"address"},{"name":"data","type":"tuple","internalType":"struct ICSParametersRegistry.InitializationData","components":[{"name":"keyRemovalCharge","type":"uint256","internalType":"uint256"},{"name":"elRewardsStealingAdditionalFine","type":"uint256","internalType":"uint256"},{"name":"keysLimit","type":"uint256","internalType":"uint256"},{"name":"rewardShare","type":"uint256","internalType":"uint256"},{"name":"performanceLeeway","type":"uint256","internalType":"uint256"},{"name":"strikesLifetime","type":"uint256","internalType":"uint256"},{"name":"strikesThreshold","type":"uint256","internalType":"uint256"},{"name":"defaultQueuePriority","type":"uint256","internalType":"uint256"},{"name":"defaultQueueMaxDeposits","type":"uint256","internalType":"uint256"},{"name":"badPerformancePenalty","type":"uint256","internalType":"uint256"},{"name":"attestationsWeight","type":"uint256","internalType":"uint256"},{"name":"blocksWeight","type":"uint256","internalType":"uint256"},{"name":"syncWeight","type":"uint256","internalType":"uint256"},{"name":"defaultAllowedExitDelay","type":"uint256","internalType":"uint256"},{"name":"defaultExitDelayPenalty","type":"uint256","internalType":"uint256"},{"name":"defaultMaxWithdrawalRequestFee","type":"uint256","internalType":"uint256"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"renounceRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"callerConfirmation","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"revokeRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setAllowedExitDelay","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"},{"name":"delay","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setBadPerformancePenalty","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"},{"name":"penalty","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setDefaultAllowedExitDelay","inputs":[{"name":"delay","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setDefaultBadPerformancePenalty","inputs":[{"name":"penalty","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setDefaultElRewardsStealingAdditionalFine","inputs":[{"name":"fine","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setDefaultExitDelayPenalty","inputs":[{"name":"penalty","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setDefaultKeyRemovalCharge","inputs":[{"name":"keyRemovalCharge","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setDefaultKeysLimit","inputs":[{"name":"limit","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setDefaultMaxWithdrawalRequestFee","inputs":[{"name":"fee","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setDefaultPerformanceCoefficients","inputs":[{"name":"attestationsWeight","type":"uint256","internalType":"uint256"},{"name":"blocksWeight","type":"uint256","internalType":"uint256"},{"name":"syncWeight","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setDefaultPerformanceLeeway","inputs":[{"name":"leeway","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setDefaultQueueConfig","inputs":[{"name":"priority","type":"uint256","internalType":"uint256"},{"name":"maxDeposits","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setDefaultRewardShare","inputs":[{"name":"share","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setDefaultStrikesParams","inputs":[{"name":"lifetime","type":"uint256","internalType":"uint256"},{"name":"threshold","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setElRewardsStealingAdditionalFine","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"},{"name":"fine","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setExitDelayPenalty","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"},{"name":"penalty","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setKeyRemovalCharge","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"},{"name":"keyRemovalCharge","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setKeysLimit","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"},{"name":"limit","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setMaxWithdrawalRequestFee","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"},{"name":"fee","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setPerformanceCoefficients","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"},{"name":"attestationsWeight","type":"uint256","internalType":"uint256"},{"name":"blocksWeight","type":"uint256","internalType":"uint256"},{"name":"syncWeight","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setPerformanceLeewayData","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"},{"name":"data","type":"tuple[]","internalType":"struct ICSParametersRegistry.KeyNumberValueInterval[]","components":[{"name":"minKeyNumber","type":"uint256","internalType":"uint256"},{"name":"value","type":"uint256","internalType":"uint256"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setQueueConfig","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"},{"name":"priority","type":"uint256","internalType":"uint256"},{"name":"maxDeposits","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setRewardShareData","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"},{"name":"data","type":"tuple[]","internalType":"struct ICSParametersRegistry.KeyNumberValueInterval[]","components":[{"name":"minKeyNumber","type":"uint256","internalType":"uint256"},{"name":"value","type":"uint256","internalType":"uint256"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setStrikesParams","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"},{"name":"lifetime","type":"uint256","internalType":"uint256"},{"name":"threshold","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"supportsInterface","inputs":[{"name":"interfaceId","type":"bytes4","internalType":"bytes4"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"unsetAllowedExitDelay","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"unsetBadPerformancePenalty","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"unsetElRewardsStealingAdditionalFine","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"unsetExitDelayPenalty","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"unsetKeyRemovalCharge","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"unsetKeysLimit","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"unsetMaxWithdrawalRequestFee","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"unsetPerformanceCoefficients","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"unsetPerformanceLeewayData","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"unsetQueueConfig","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"unsetRewardShareData","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"unsetStrikesParams","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"event","name":"AllowedExitDelaySet","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"delay","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"AllowedExitDelayUnset","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"BadPerformancePenaltySet","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"penalty","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"BadPerformancePenaltyUnset","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"DefaultAllowedExitDelaySet","inputs":[{"name":"delay","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"DefaultBadPerformancePenaltySet","inputs":[{"name":"value","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"DefaultElRewardsStealingAdditionalFineSet","inputs":[{"name":"value","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"DefaultExitDelayPenaltySet","inputs":[{"name":"penalty","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"DefaultKeyRemovalChargeSet","inputs":[{"name":"value","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"DefaultKeysLimitSet","inputs":[{"name":"value","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"DefaultMaxWithdrawalRequestFeeSet","inputs":[{"name":"fee","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"DefaultPerformanceCoefficientsSet","inputs":[{"name":"attestationsWeight","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"blocksWeight","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"syncWeight","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"DefaultPerformanceLeewaySet","inputs":[{"name":"value","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"DefaultQueueConfigSet","inputs":[{"name":"priority","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"maxDeposits","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"DefaultRewardShareSet","inputs":[{"name":"value","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"DefaultStrikesParamsSet","inputs":[{"name":"lifetime","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"threshold","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ElRewardsStealingAdditionalFineSet","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"fine","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ElRewardsStealingAdditionalFineUnset","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ExitDelayPenaltySet","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"penalty","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ExitDelayPenaltyUnset","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"Initialized","inputs":[{"name":"version","type":"uint64","indexed":false,"internalType":"uint64"}],"anonymous":false},{"type":"event","name":"KeyRemovalChargeSet","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"keyRemovalCharge","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"KeyRemovalChargeUnset","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"KeysLimitSet","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"limit","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"KeysLimitUnset","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"MaxWithdrawalRequestFeeSet","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"fee","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"MaxWithdrawalRequestFeeUnset","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"PerformanceCoefficientsSet","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"attestationsWeight","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"blocksWeight","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"syncWeight","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"PerformanceCoefficientsUnset","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"PerformanceLeewayDataSet","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"data","type":"tuple[]","indexed":false,"internalType":"struct ICSParametersRegistry.KeyNumberValueInterval[]","components":[{"name":"minKeyNumber","type":"uint256","internalType":"uint256"},{"name":"value","type":"uint256","internalType":"uint256"}]}],"anonymous":false},{"type":"event","name":"PerformanceLeewayDataUnset","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"QueueConfigSet","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"priority","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"maxDeposits","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"QueueConfigUnset","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"RewardShareDataSet","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"data","type":"tuple[]","indexed":false,"internalType":"struct ICSParametersRegistry.KeyNumberValueInterval[]","components":[{"name":"minKeyNumber","type":"uint256","internalType":"uint256"},{"name":"value","type":"uint256","internalType":"uint256"}]}],"anonymous":false},{"type":"event","name":"RewardShareDataUnset","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"RoleAdminChanged","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"previousAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"newAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"}],"anonymous":false},{"type":"event","name":"RoleGranted","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"RoleRevoked","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"StrikesParamsSet","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"lifetime","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"threshold","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"StrikesParamsUnset","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"type":"error","name":"AccessControlBadConfirmation","inputs":[]},{"type":"error","name":"AccessControlUnauthorizedAccount","inputs":[{"name":"account","type":"address","internalType":"address"},{"name":"neededRole","type":"bytes32","internalType":"bytes32"}]},{"type":"error","name":"InvalidAllowedExitDelay","inputs":[]},{"type":"error","name":"InvalidInitialization","inputs":[]},{"type":"error","name":"InvalidKeyNumberValueIntervals","inputs":[]},{"type":"error","name":"InvalidPerformanceCoefficients","inputs":[]},{"type":"error","name":"InvalidPerformanceLeewayData","inputs":[]},{"type":"error","name":"InvalidRewardShareData","inputs":[]},{"type":"error","name":"InvalidStrikesParams","inputs":[]},{"type":"error","name":"NotInitializing","inputs":[]},{"type":"error","name":"QueueCannotBeUsed","inputs":[]},{"type":"error","name":"SafeCastOverflowedUintDowncast","inputs":[{"name":"bits","type":"uint8","internalType":"uint8"},{"name":"value","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"ZeroAdminAddress","inputs":[]},{"type":"error","name":"ZeroMaxDeposits","inputs":[]},{"type":"error","name":"ZeroQueueLowestPriority","inputs":[]}] diff --git a/interfaces/CSVerifierV2.json b/interfaces/CSVerifierV2.json index 267204b21..ee3bc5f73 100644 --- a/interfaces/CSVerifierV2.json +++ b/interfaces/CSVerifierV2.json @@ -1 +1 @@ -[{"type":"constructor","inputs":[{"name":"withdrawalAddress","type":"address","internalType":"address"},{"name":"module","type":"address","internalType":"address"},{"name":"slotsPerEpoch","type":"uint64","internalType":"uint64"},{"name":"gindices","type":"tuple","internalType":"struct ICSVerifier.GIndices","components":[{"name":"gIFirstWithdrawalPrev","type":"bytes32","internalType":"GIndex"},{"name":"gIFirstWithdrawalCurr","type":"bytes32","internalType":"GIndex"},{"name":"gIFirstValidatorPrev","type":"bytes32","internalType":"GIndex"},{"name":"gIFirstValidatorCurr","type":"bytes32","internalType":"GIndex"},{"name":"gIHistoricalSummariesPrev","type":"bytes32","internalType":"GIndex"},{"name":"gIHistoricalSummariesCurr","type":"bytes32","internalType":"GIndex"}]},{"name":"firstSupportedSlot","type":"uint64","internalType":"Slot"},{"name":"pivotSlot","type":"uint64","internalType":"Slot"},{"name":"admin","type":"address","internalType":"address"}],"stateMutability":"nonpayable"},{"type":"function","name":"BEACON_ROOTS","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"DEFAULT_ADMIN_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"FIRST_SUPPORTED_SLOT","inputs":[],"outputs":[{"name":"","type":"uint64","internalType":"Slot"}],"stateMutability":"view"},{"type":"function","name":"GI_FIRST_VALIDATOR_CURR","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"GIndex"}],"stateMutability":"view"},{"type":"function","name":"GI_FIRST_VALIDATOR_PREV","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"GIndex"}],"stateMutability":"view"},{"type":"function","name":"GI_FIRST_WITHDRAWAL_CURR","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"GIndex"}],"stateMutability":"view"},{"type":"function","name":"GI_FIRST_WITHDRAWAL_PREV","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"GIndex"}],"stateMutability":"view"},{"type":"function","name":"GI_HISTORICAL_SUMMARIES_CURR","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"GIndex"}],"stateMutability":"view"},{"type":"function","name":"GI_HISTORICAL_SUMMARIES_PREV","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"GIndex"}],"stateMutability":"view"},{"type":"function","name":"MODULE","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ICSModule"}],"stateMutability":"view"},{"type":"function","name":"PAUSE_INFINITELY","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"PAUSE_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"PIVOT_SLOT","inputs":[],"outputs":[{"name":"","type":"uint64","internalType":"Slot"}],"stateMutability":"view"},{"type":"function","name":"RESUME_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"SLOTS_PER_EPOCH","inputs":[],"outputs":[{"name":"","type":"uint64","internalType":"uint64"}],"stateMutability":"view"},{"type":"function","name":"WITHDRAWAL_ADDRESS","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"getResumeSinceTimestamp","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getRoleAdmin","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"getRoleMember","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"index","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"getRoleMemberCount","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"grantRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"hasRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"isPaused","inputs":[],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"pauseFor","inputs":[{"name":"duration","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"processHistoricalWithdrawalProof","inputs":[{"name":"beaconBlock","type":"tuple","internalType":"struct ICSVerifier.ProvableBeaconBlockHeader","components":[{"name":"header","type":"tuple","internalType":"struct BeaconBlockHeader","components":[{"name":"slot","type":"uint64","internalType":"Slot"},{"name":"proposerIndex","type":"uint64","internalType":"uint64"},{"name":"parentRoot","type":"bytes32","internalType":"bytes32"},{"name":"stateRoot","type":"bytes32","internalType":"bytes32"},{"name":"bodyRoot","type":"bytes32","internalType":"bytes32"}]},{"name":"rootsTimestamp","type":"uint64","internalType":"uint64"}]},{"name":"oldBlock","type":"tuple","internalType":"struct ICSVerifier.HistoricalHeaderWitness","components":[{"name":"header","type":"tuple","internalType":"struct BeaconBlockHeader","components":[{"name":"slot","type":"uint64","internalType":"Slot"},{"name":"proposerIndex","type":"uint64","internalType":"uint64"},{"name":"parentRoot","type":"bytes32","internalType":"bytes32"},{"name":"stateRoot","type":"bytes32","internalType":"bytes32"},{"name":"bodyRoot","type":"bytes32","internalType":"bytes32"}]},{"name":"rootGIndex","type":"bytes32","internalType":"GIndex"},{"name":"proof","type":"bytes32[]","internalType":"bytes32[]"}]},{"name":"witness","type":"tuple","internalType":"struct ICSVerifier.WithdrawalWitness","components":[{"name":"withdrawalOffset","type":"uint8","internalType":"uint8"},{"name":"withdrawalIndex","type":"uint64","internalType":"uint64"},{"name":"validatorIndex","type":"uint64","internalType":"uint64"},{"name":"amount","type":"uint64","internalType":"uint64"},{"name":"withdrawalCredentials","type":"bytes32","internalType":"bytes32"},{"name":"effectiveBalance","type":"uint64","internalType":"uint64"},{"name":"slashed","type":"bool","internalType":"bool"},{"name":"activationEligibilityEpoch","type":"uint64","internalType":"uint64"},{"name":"activationEpoch","type":"uint64","internalType":"uint64"},{"name":"exitEpoch","type":"uint64","internalType":"uint64"},{"name":"withdrawableEpoch","type":"uint64","internalType":"uint64"},{"name":"withdrawalProof","type":"bytes32[]","internalType":"bytes32[]"},{"name":"validatorProof","type":"bytes32[]","internalType":"bytes32[]"}]},{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"keyIndex","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"processWithdrawalProof","inputs":[{"name":"beaconBlock","type":"tuple","internalType":"struct ICSVerifier.ProvableBeaconBlockHeader","components":[{"name":"header","type":"tuple","internalType":"struct BeaconBlockHeader","components":[{"name":"slot","type":"uint64","internalType":"Slot"},{"name":"proposerIndex","type":"uint64","internalType":"uint64"},{"name":"parentRoot","type":"bytes32","internalType":"bytes32"},{"name":"stateRoot","type":"bytes32","internalType":"bytes32"},{"name":"bodyRoot","type":"bytes32","internalType":"bytes32"}]},{"name":"rootsTimestamp","type":"uint64","internalType":"uint64"}]},{"name":"witness","type":"tuple","internalType":"struct ICSVerifier.WithdrawalWitness","components":[{"name":"withdrawalOffset","type":"uint8","internalType":"uint8"},{"name":"withdrawalIndex","type":"uint64","internalType":"uint64"},{"name":"validatorIndex","type":"uint64","internalType":"uint64"},{"name":"amount","type":"uint64","internalType":"uint64"},{"name":"withdrawalCredentials","type":"bytes32","internalType":"bytes32"},{"name":"effectiveBalance","type":"uint64","internalType":"uint64"},{"name":"slashed","type":"bool","internalType":"bool"},{"name":"activationEligibilityEpoch","type":"uint64","internalType":"uint64"},{"name":"activationEpoch","type":"uint64","internalType":"uint64"},{"name":"exitEpoch","type":"uint64","internalType":"uint64"},{"name":"withdrawableEpoch","type":"uint64","internalType":"uint64"},{"name":"withdrawalProof","type":"bytes32[]","internalType":"bytes32[]"},{"name":"validatorProof","type":"bytes32[]","internalType":"bytes32[]"}]},{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"keyIndex","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"renounceRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"callerConfirmation","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"resume","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"revokeRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"supportsInterface","inputs":[{"name":"interfaceId","type":"bytes4","internalType":"bytes4"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"event","name":"Paused","inputs":[{"name":"duration","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"Resumed","inputs":[],"anonymous":false},{"type":"event","name":"RoleAdminChanged","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"previousAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"newAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"}],"anonymous":false},{"type":"event","name":"RoleGranted","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"RoleRevoked","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"error","name":"AccessControlBadConfirmation","inputs":[]},{"type":"error","name":"AccessControlUnauthorizedAccount","inputs":[{"name":"account","type":"address","internalType":"address"},{"name":"neededRole","type":"bytes32","internalType":"bytes32"}]},{"type":"error","name":"IndexOutOfRange","inputs":[]},{"type":"error","name":"InvalidBlockHeader","inputs":[]},{"type":"error","name":"InvalidChainConfig","inputs":[]},{"type":"error","name":"InvalidGIndex","inputs":[]},{"type":"error","name":"InvalidPivotSlot","inputs":[]},{"type":"error","name":"InvalidWithdrawalAddress","inputs":[]},{"type":"error","name":"PartialWithdrawal","inputs":[]},{"type":"error","name":"PauseUntilMustBeInFuture","inputs":[]},{"type":"error","name":"PausedExpected","inputs":[]},{"type":"error","name":"ResumedExpected","inputs":[]},{"type":"error","name":"RootNotFound","inputs":[]},{"type":"error","name":"UnsupportedSlot","inputs":[{"name":"slot","type":"uint64","internalType":"Slot"}]},{"type":"error","name":"ValidatorNotWithdrawn","inputs":[]},{"type":"error","name":"ZeroAdminAddress","inputs":[]},{"type":"error","name":"ZeroModuleAddress","inputs":[]},{"type":"error","name":"ZeroPauseDuration","inputs":[]},{"type":"error","name":"ZeroWithdrawalAddress","inputs":[]}] +[{"type":"constructor","inputs":[{"name":"withdrawalAddress","type":"address","internalType":"address"},{"name":"module","type":"address","internalType":"address"},{"name":"slotsPerEpoch","type":"uint64","internalType":"uint64"},{"name":"slotsPerHistoricalRoot","type":"uint64","internalType":"uint64"},{"name":"gindices","type":"tuple","internalType":"struct ICSVerifier.GIndices","components":[{"name":"gIFirstWithdrawalPrev","type":"bytes32","internalType":"GIndex"},{"name":"gIFirstWithdrawalCurr","type":"bytes32","internalType":"GIndex"},{"name":"gIFirstValidatorPrev","type":"bytes32","internalType":"GIndex"},{"name":"gIFirstValidatorCurr","type":"bytes32","internalType":"GIndex"},{"name":"gIFirstHistoricalSummaryPrev","type":"bytes32","internalType":"GIndex"},{"name":"gIFirstHistoricalSummaryCurr","type":"bytes32","internalType":"GIndex"},{"name":"gIFirstBlockRootInSummaryPrev","type":"bytes32","internalType":"GIndex"},{"name":"gIFirstBlockRootInSummaryCurr","type":"bytes32","internalType":"GIndex"}]},{"name":"firstSupportedSlot","type":"uint64","internalType":"Slot"},{"name":"pivotSlot","type":"uint64","internalType":"Slot"},{"name":"capellaSlot","type":"uint64","internalType":"Slot"},{"name":"admin","type":"address","internalType":"address"}],"stateMutability":"nonpayable"},{"type":"function","name":"BEACON_ROOTS","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"CAPELLA_SLOT","inputs":[],"outputs":[{"name":"","type":"uint64","internalType":"Slot"}],"stateMutability":"view"},{"type":"function","name":"DEFAULT_ADMIN_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"FIRST_SUPPORTED_SLOT","inputs":[],"outputs":[{"name":"","type":"uint64","internalType":"Slot"}],"stateMutability":"view"},{"type":"function","name":"GI_FIRST_BLOCK_ROOT_IN_SUMMARY_CURR","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"GIndex"}],"stateMutability":"view"},{"type":"function","name":"GI_FIRST_BLOCK_ROOT_IN_SUMMARY_PREV","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"GIndex"}],"stateMutability":"view"},{"type":"function","name":"GI_FIRST_HISTORICAL_SUMMARY_CURR","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"GIndex"}],"stateMutability":"view"},{"type":"function","name":"GI_FIRST_HISTORICAL_SUMMARY_PREV","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"GIndex"}],"stateMutability":"view"},{"type":"function","name":"GI_FIRST_VALIDATOR_CURR","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"GIndex"}],"stateMutability":"view"},{"type":"function","name":"GI_FIRST_VALIDATOR_PREV","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"GIndex"}],"stateMutability":"view"},{"type":"function","name":"GI_FIRST_WITHDRAWAL_CURR","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"GIndex"}],"stateMutability":"view"},{"type":"function","name":"GI_FIRST_WITHDRAWAL_PREV","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"GIndex"}],"stateMutability":"view"},{"type":"function","name":"MODULE","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ICSModule"}],"stateMutability":"view"},{"type":"function","name":"PAUSE_INFINITELY","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"PAUSE_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"PIVOT_SLOT","inputs":[],"outputs":[{"name":"","type":"uint64","internalType":"Slot"}],"stateMutability":"view"},{"type":"function","name":"RESUME_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"SLOTS_PER_EPOCH","inputs":[],"outputs":[{"name":"","type":"uint64","internalType":"uint64"}],"stateMutability":"view"},{"type":"function","name":"SLOTS_PER_HISTORICAL_ROOT","inputs":[],"outputs":[{"name":"","type":"uint64","internalType":"uint64"}],"stateMutability":"view"},{"type":"function","name":"WITHDRAWAL_ADDRESS","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"getResumeSinceTimestamp","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getRoleAdmin","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"getRoleMember","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"index","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"getRoleMemberCount","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"grantRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"hasRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"isPaused","inputs":[],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"pauseFor","inputs":[{"name":"duration","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"processHistoricalWithdrawalProof","inputs":[{"name":"beaconBlock","type":"tuple","internalType":"struct ICSVerifier.ProvableBeaconBlockHeader","components":[{"name":"header","type":"tuple","internalType":"struct BeaconBlockHeader","components":[{"name":"slot","type":"uint64","internalType":"Slot"},{"name":"proposerIndex","type":"uint64","internalType":"uint64"},{"name":"parentRoot","type":"bytes32","internalType":"bytes32"},{"name":"stateRoot","type":"bytes32","internalType":"bytes32"},{"name":"bodyRoot","type":"bytes32","internalType":"bytes32"}]},{"name":"rootsTimestamp","type":"uint64","internalType":"uint64"}]},{"name":"oldBlock","type":"tuple","internalType":"struct ICSVerifier.HistoricalHeaderWitness","components":[{"name":"header","type":"tuple","internalType":"struct BeaconBlockHeader","components":[{"name":"slot","type":"uint64","internalType":"Slot"},{"name":"proposerIndex","type":"uint64","internalType":"uint64"},{"name":"parentRoot","type":"bytes32","internalType":"bytes32"},{"name":"stateRoot","type":"bytes32","internalType":"bytes32"},{"name":"bodyRoot","type":"bytes32","internalType":"bytes32"}]},{"name":"proof","type":"bytes32[]","internalType":"bytes32[]"}]},{"name":"witness","type":"tuple","internalType":"struct ICSVerifier.WithdrawalWitness","components":[{"name":"withdrawalOffset","type":"uint8","internalType":"uint8"},{"name":"withdrawalIndex","type":"uint64","internalType":"uint64"},{"name":"validatorIndex","type":"uint64","internalType":"uint64"},{"name":"amount","type":"uint64","internalType":"uint64"},{"name":"withdrawalCredentials","type":"bytes32","internalType":"bytes32"},{"name":"effectiveBalance","type":"uint64","internalType":"uint64"},{"name":"slashed","type":"bool","internalType":"bool"},{"name":"activationEligibilityEpoch","type":"uint64","internalType":"uint64"},{"name":"activationEpoch","type":"uint64","internalType":"uint64"},{"name":"exitEpoch","type":"uint64","internalType":"uint64"},{"name":"withdrawableEpoch","type":"uint64","internalType":"uint64"},{"name":"withdrawalProof","type":"bytes32[]","internalType":"bytes32[]"},{"name":"validatorProof","type":"bytes32[]","internalType":"bytes32[]"}]},{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"keyIndex","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"processWithdrawalProof","inputs":[{"name":"beaconBlock","type":"tuple","internalType":"struct ICSVerifier.ProvableBeaconBlockHeader","components":[{"name":"header","type":"tuple","internalType":"struct BeaconBlockHeader","components":[{"name":"slot","type":"uint64","internalType":"Slot"},{"name":"proposerIndex","type":"uint64","internalType":"uint64"},{"name":"parentRoot","type":"bytes32","internalType":"bytes32"},{"name":"stateRoot","type":"bytes32","internalType":"bytes32"},{"name":"bodyRoot","type":"bytes32","internalType":"bytes32"}]},{"name":"rootsTimestamp","type":"uint64","internalType":"uint64"}]},{"name":"witness","type":"tuple","internalType":"struct ICSVerifier.WithdrawalWitness","components":[{"name":"withdrawalOffset","type":"uint8","internalType":"uint8"},{"name":"withdrawalIndex","type":"uint64","internalType":"uint64"},{"name":"validatorIndex","type":"uint64","internalType":"uint64"},{"name":"amount","type":"uint64","internalType":"uint64"},{"name":"withdrawalCredentials","type":"bytes32","internalType":"bytes32"},{"name":"effectiveBalance","type":"uint64","internalType":"uint64"},{"name":"slashed","type":"bool","internalType":"bool"},{"name":"activationEligibilityEpoch","type":"uint64","internalType":"uint64"},{"name":"activationEpoch","type":"uint64","internalType":"uint64"},{"name":"exitEpoch","type":"uint64","internalType":"uint64"},{"name":"withdrawableEpoch","type":"uint64","internalType":"uint64"},{"name":"withdrawalProof","type":"bytes32[]","internalType":"bytes32[]"},{"name":"validatorProof","type":"bytes32[]","internalType":"bytes32[]"}]},{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"keyIndex","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"renounceRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"callerConfirmation","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"resume","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"revokeRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"supportsInterface","inputs":[{"name":"interfaceId","type":"bytes4","internalType":"bytes4"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"event","name":"Paused","inputs":[{"name":"duration","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"Resumed","inputs":[],"anonymous":false},{"type":"event","name":"RoleAdminChanged","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"previousAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"newAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"}],"anonymous":false},{"type":"event","name":"RoleGranted","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"RoleRevoked","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"error","name":"AccessControlBadConfirmation","inputs":[]},{"type":"error","name":"AccessControlUnauthorizedAccount","inputs":[{"name":"account","type":"address","internalType":"address"},{"name":"neededRole","type":"bytes32","internalType":"bytes32"}]},{"type":"error","name":"IndexOutOfRange","inputs":[]},{"type":"error","name":"InvalidBlockHeader","inputs":[]},{"type":"error","name":"InvalidCapellaSlot","inputs":[]},{"type":"error","name":"InvalidChainConfig","inputs":[]},{"type":"error","name":"InvalidPivotSlot","inputs":[]},{"type":"error","name":"InvalidWithdrawalAddress","inputs":[]},{"type":"error","name":"PartialWithdrawal","inputs":[]},{"type":"error","name":"PauseUntilMustBeInFuture","inputs":[]},{"type":"error","name":"PausedExpected","inputs":[]},{"type":"error","name":"ResumedExpected","inputs":[]},{"type":"error","name":"RootNotFound","inputs":[]},{"type":"error","name":"UnsupportedSlot","inputs":[{"name":"slot","type":"uint64","internalType":"Slot"}]},{"type":"error","name":"ValidatorNotWithdrawn","inputs":[]},{"type":"error","name":"ZeroAdminAddress","inputs":[]},{"type":"error","name":"ZeroModuleAddress","inputs":[]},{"type":"error","name":"ZeroPauseDuration","inputs":[]},{"type":"error","name":"ZeroWithdrawalAddress","inputs":[]}] diff --git a/scripts/ci/prepare_environment.py b/scripts/ci/prepare_environment.py index 3d8cfd0d2..0c89dc6ea 100644 --- a/scripts/ci/prepare_environment.py +++ b/scripts/ci/prepare_environment.py @@ -98,4 +98,4 @@ def retrieve_vote_script() -> Tuple[Callable, Callable] | None: f"'start_vote' and/or 'get_vote_items' not found in {script_path}." ) except Exception as e: - raise RuntimeError(f"An unexpected error occurred while importing from {script_path}: {e}") \ No newline at end of file + raise RuntimeError(f"An unexpected error occurred while importing from {script_path}: {e}") diff --git a/scripts/vote_tw_csm2_mainnet.py b/scripts/vote_tw_csm2_mainnet.py index d6d05df4d..0ff8d4059 100644 --- a/scripts/vote_tw_csm2_mainnet.py +++ b/scripts/vote_tw_csm2_mainnet.py @@ -148,19 +148,19 @@ FRAME_DURATION_IN_SEC = 48 # CSM -CS_MODULE_NEW_TARGET_SHARE_BP = 1600 # 16% -CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP = 2100 # 21% +CS_MODULE_NEW_TARGET_SHARE_BP = 3500 # 3.5% +CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP = 3750 # 3.75% -CS_ACCOUNTING_IMPL_V2_ADDRESS = "0x9483b34504292a0E4f6509e5887D2c68f7129638" -CS_FEE_DISTRIBUTOR_IMPL_V2_ADDRESS = "0xe05F7Aab7177D73f26e62a5296120583F5F18031" -CS_FEE_ORACLE_IMPL_V2_ADDRESS = "0x752fF00fcacdB66Bc512a067F15A5E0B0b50EADB" -CSM_IMPL_V2_ADDRESS = "0x9aE387EB2abA80B9B1ebc145597D593EFAE61f31" +CS_ACCOUNTING_IMPL_V2_ADDRESS = "0x6f09d2426c7405C5546413e6059F884D2D03f449" +CS_FEE_DISTRIBUTOR_IMPL_V2_ADDRESS = "0x5DCF7cF7c6645E9E822a379dF046a8b0390251A1" +CS_FEE_ORACLE_IMPL_V2_ADDRESS = "0xe0B234f99E413E27D9Bc31aBba9A49A3e570Da97" +CSM_IMPL_V2_ADDRESS = "0x1eB6d4da13ca9566c17F526aE0715325d7a07665" -CS_GATE_SEAL_V2_ADDRESS = "0x94a3aEB0E9148F64CB453Be2BDe2Bc0148f6AC24" -CS_EJECTOR_ADDRESS = "0x21e271cBa32672B106737AbeB3a45E53Fe9a0df4" -CS_PERMISSIONLESS_GATE_ADDRESS = "0x5553077102322689876A6AdFd48D75014c28acfb" -CS_VETTED_GATE_ADDRESS = "0x10a254E724fe2b7f305F76f3F116a3969c53845f" -CS_VERIFIER_V2_ADDRESS = "0xf805b3711cBB48F15Ae2bb27095ddC38c5339968" +CS_GATE_SEAL_V2_ADDRESS = "0xE1686C2E90eb41a48356c1cC7FaA17629af3ADB3" +CS_EJECTOR_ADDRESS = "0xc72b58aa02E0e98cF8A4a0E9Dce75e763800802C" +CS_PERMISSIONLESS_GATE_ADDRESS = "0xcF33a38111d0B1246A3F38a838fb41D626B454f0" +CS_VETTED_GATE_ADDRESS = "0xB314D4A76C457c93150d308787939063F4Cc67E0" +CS_VERIFIER_V2_ADDRESS = "0xdC5FE1782B6943f318E05230d688713a560063DC" CS_CURVES = [ ([1, 2.4 * 10**18], [2, 1.3 * 10**18]), # Default Curve @@ -178,7 +178,7 @@ EASYTRACK_EVMSCRIPT_EXECUTOR = "0x79a20FD0FA36453B2F45eAbab19bfef43575Ba9E" EASYTRACK_SDVT_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY = "0xAa3D6A8B52447F272c1E8FAaA06EA06658bd95E2" EASYTRACK_CURATED_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY = "0x397206ecdbdcb1A55A75e60Fc4D054feC72E5f63" -EASYTRACK_CS_SET_VETTED_GATE_TREE_FACTORY = "0xa890fc73e1b771Ee6073e2402E631c312FF92Cd9" +EASYTRACK_CS_SET_VETTED_GATE_TREE_FACTORY = "0xa890fc73e1b771Ee6073e2402E631c312FF92Cd9" # TODO: replace with the real one # ============================= Description ================================== IPFS_DESCRIPTION = "Triggerable withdrawals and CSM v2 upgrade voting" diff --git a/tests/acceptance/test_csm.py b/tests/acceptance/test_csm.py index ca33c1cef..861750918 100644 --- a/tests/acceptance/test_csm.py +++ b/tests/acceptance/test_csm.py @@ -24,8 +24,11 @@ CS_ORACLE_EPOCHS_PER_FRAME, ORACLE_QUORUM, ORACLE_COMMITTEE, + CS_PARAMS_REGISTRY_ADDRESS, + CS_EXIT_PENALTIES_ADDRESS, + CS_STRIKES_ADDRESS, + CS_EJECTOR_ADDRESS ) -from utils.test.helpers import ETH contracts: ContractsLazyLoader = contracts @@ -38,61 +41,104 @@ def _str_to_bytes32(s: str) -> str: def csm(): return contracts.csm -@pytest.fixture(scope="module") -def early_adoption(): - return contracts.cs_early_adoption @pytest.fixture(scope="module") def fee_distributor(): return contracts.cs_fee_distributor + @pytest.fixture(scope="module") def fee_oracle(): return contracts.cs_fee_oracle + @pytest.fixture(scope="module") def hash_consensus(): return contracts.csm_hash_consensus + @pytest.fixture(scope="module") def accounting(): return contracts.cs_accounting + @pytest.fixture(scope="module") def verifier(): return contracts.cs_verifier +@pytest.fixture(scope="module") +def permissionless_gate(): + return contracts.cs_permissionless_gate + + +@pytest.fixture(scope="module") +def vetted_gate(): + return contracts.cs_vetted_gate + + +@pytest.fixture(scope="module") +def parameters_registry(): + return contracts.cs_parameters_registry + + +@pytest.fixture(scope="module") +def ejector(): + return contracts.cs_ejector + + +@pytest.fixture(scope="module") +def strikes(): + return contracts.cs_strikes + + +@pytest.fixture(scope="module") +def exit_penalties(): + return contracts.cs_exit_penalties + + @pytest.fixture(scope="module") def lido(): return interface.Lido(LIDO) -def test_proxy(csm, accounting, fee_distributor, fee_oracle): + +def test_proxy( + csm, + accounting, + fee_distributor, + fee_oracle, + vetted_gate, + strikes, + exit_penalties, +): assert interface.OssifiableProxy(csm).proxy__getAdmin() == contracts.agent.address assert interface.OssifiableProxy(accounting).proxy__getAdmin() == contracts.agent.address assert interface.OssifiableProxy(fee_distributor).proxy__getAdmin() == contracts.agent.address assert interface.OssifiableProxy(fee_oracle).proxy__getAdmin() == contracts.agent.address + assert interface.OssifiableProxy(vetted_gate).proxy__getAdmin() == contracts.agent.address + assert interface.OssifiableProxy(strikes).proxy__getAdmin() == contracts.agent.address + assert interface.OssifiableProxy(exit_penalties).proxy__getAdmin() == contracts.agent.address class TestCSM: def test_init_state(self, csm): assert csm.getType() == _str_to_bytes32("community-onchain-v1") assert csm.LIDO_LOCATOR() == LIDO_LOCATOR - assert csm.accounting() == CS_ACCOUNTING_ADDRESS - assert csm.keyRemovalCharge() == 0 # Updated from 0.02 to 0 in vote 2025/07/16 + assert csm.PARAMETERS_REGISTRY() == CS_PARAMS_REGISTRY_ADDRESS + assert csm.ACCOUNTING() == CS_ACCOUNTING_ADDRESS + assert csm.EXIT_PENALTIES() == CS_EXIT_PENALTIES_ADDRESS assert not csm.isPaused() - assert csm.publicRelease() class TestAccounting: def test_initial_state(self, accounting): - assert accounting.CSM() == CSM_ADDRESS + assert accounting.MODULE() == CSM_ADDRESS assert accounting.LIDO_LOCATOR() == LIDO_LOCATOR assert accounting.LIDO() == LIDO assert accounting.WITHDRAWAL_QUEUE() == WITHDRAWAL_QUEUE assert accounting.WSTETH() == WSTETH_TOKEN - assert accounting.feeDistributor() == CS_FEE_DISTRIBUTOR_ADDRESS + assert accounting.FEE_DISTRIBUTOR() == CS_FEE_DISTRIBUTOR_ADDRESS assert accounting.chargePenaltyRecipient() == AGENT assert not accounting.isPaused() @@ -102,12 +148,14 @@ def test_allowances(self, lido): assert lido.allowance(CS_ACCOUNTING_ADDRESS, WITHDRAWAL_QUEUE) == uin256_max assert lido.allowance(CS_ACCOUNTING_ADDRESS, BURNER) == uin256_max + class TestFeeDistributor: def test_initial_state(self, fee_distributor): assert fee_distributor.STETH() == LIDO assert fee_distributor.ACCOUNTING() == CS_ACCOUNTING_ADDRESS assert fee_distributor.ORACLE() == CS_FEE_ORACLE_ADDRESS + assert fee_distributor.rebateRecipient() == AGENT class TestFeeOracle: @@ -115,13 +163,14 @@ class TestFeeOracle: def test_initial_state(self, fee_oracle): assert fee_oracle.SECONDS_PER_SLOT() == CHAIN_SECONDS_PER_SLOT assert fee_oracle.GENESIS_TIME() == CHAIN_GENESIS_TIME - assert fee_oracle.feeDistributor() == CS_FEE_DISTRIBUTOR_ADDRESS - assert fee_oracle.getContractVersion() == 1 + assert fee_oracle.FEE_DISTRIBUTOR() == CS_FEE_DISTRIBUTOR_ADDRESS + assert fee_oracle.STRIKES() == CS_STRIKES_ADDRESS + assert fee_oracle.getContractVersion() == 2 assert fee_oracle.getConsensusContract() == CS_ORACLE_HASH_CONSENSUS_ADDRESS - assert fee_oracle.getConsensusVersion() == 2 - assert fee_oracle.avgPerfLeewayBP() == 500 + assert fee_oracle.getConsensusVersion() == 3 assert not fee_oracle.isPaused() + class TestHashConsensus: def test_initial_state(self, hash_consensus): @@ -131,35 +180,69 @@ def test_initial_state(self, hash_consensus): assert chain_config["genesisTime"] == CHAIN_GENESIS_TIME frame_config = hash_consensus.getFrameConfig() - assert frame_config["initialEpoch"] >= 326715 + assert frame_config["initialEpoch"] == 326715 assert frame_config["epochsPerFrame"] == CS_ORACLE_EPOCHS_PER_FRAME assert frame_config["fastLaneLengthSlots"] == 1800 assert hash_consensus.getQuorum() == ORACLE_QUORUM - assert hash_consensus.getInitialRefSlot() >= 326715 * CHAIN_SLOTS_PER_EPOCH - 1 + assert hash_consensus.getInitialRefSlot() == 10454879 members = hash_consensus.getMembers() assert sorted(members["addresses"]) == sorted(ORACLE_COMMITTEE) assert hash_consensus.getReportProcessor() == CS_FEE_ORACLE_ADDRESS -def test_early_adoption_state(early_adoption): - assert early_adoption.MODULE() == CSM_ADDRESS - assert early_adoption.CURVE_ID() == 1 + +def test_permissionless_gate_state(permissionless_gate): + assert permissionless_gate.MODULE() == CSM_ADDRESS + assert permissionless_gate.CURVE_ID() == 0 + + +def test_vetted_gate_state(vetted_gate): + assert vetted_gate.MODULE() == CSM_ADDRESS + assert vetted_gate.curveId() == 2 + + +def test_ejector_state(ejector): + assert ejector.MODULE() == CSM_ADDRESS + assert ejector.STRIKES() == CS_STRIKES_ADDRESS + assert ejector.STAKING_MODULE_ID() == 3 + + +def test_strikes_state(strikes): + assert strikes.MODULE() == CSM_ADDRESS + assert strikes.EXIT_PENALTIES() == CS_EXIT_PENALTIES_ADDRESS + assert strikes.ORACLE() == CS_FEE_ORACLE_ADDRESS + assert strikes.PARAMETERS_REGISTRY() == CS_PARAMS_REGISTRY_ADDRESS + assert strikes.ejector() == CS_EJECTOR_ADDRESS + + +def test_exit_penalties_state(exit_penalties): + assert exit_penalties.MODULE() == CSM_ADDRESS + assert exit_penalties.PARAMETERS_REGISTRY() == CS_PARAMS_REGISTRY_ADDRESS + assert exit_penalties.STRIKES() == CS_STRIKES_ADDRESS + + +def test_parameters_registry_state(parameters_registry): + assert parameters_registry.QUEUE_LOWEST_PRIORITY() == 5 + assert parameters_registry.QUEUE_LEGACY_PRIORITY() == 4 + def test_verifier_state(verifier): assert verifier.WITHDRAWAL_ADDRESS() == WITHDRAWAL_VAULT assert verifier.MODULE() == CSM_ADDRESS assert verifier.SLOTS_PER_EPOCH() == CHAIN_SLOTS_PER_EPOCH - with reverts(): # The new CS Verifier (vote 2025/07/16) doesn't have these 2 methods - verifier.GI_HISTORICAL_SUMMARIES_PREV() - verifier.GI_HISTORICAL_SUMMARIES_CURR() - - assert verifier.GI_FIRST_WITHDRAWAL_PREV() == HexString("0x0000000000000000000000000000000000000000000000000000000000e1c004", "bytes") + assert verifier.GI_FIRST_WITHDRAWAL_PREV() == HexString("0x000000000000000000000000000000000000000000000000000000000161c004", "bytes") assert verifier.GI_FIRST_WITHDRAWAL_CURR() == HexString("0x000000000000000000000000000000000000000000000000000000000161c004", "bytes") - assert verifier.GI_FIRST_VALIDATOR_PREV() == HexString("0x0000000000000000000000000000000000000000000000000056000000000028", "bytes") + assert verifier.GI_FIRST_VALIDATOR_PREV() == HexString("0x0000000000000000000000000000000000000000000000000096000000000028", "bytes") assert verifier.GI_FIRST_VALIDATOR_CURR() == HexString("0x0000000000000000000000000000000000000000000000000096000000000028", "bytes") - assert verifier.FIRST_SUPPORTED_SLOT() == 8626176 - assert verifier.PIVOT_SLOT() == 11649024 + assert verifier.GI_FIRST_HISTORICAL_SUMMARY_PREV() == HexString("0x000000000000000000000000000000000000000000000000000000b600000018", "bytes") + assert verifier.GI_FIRST_HISTORICAL_SUMMARY_CURR() == HexString("0x000000000000000000000000000000000000000000000000000000b600000018", "bytes") + assert verifier.GI_FIRST_BLOCK_ROOT_IN_SUMMARY_PREV() == HexString("0x000000000000000000000000000000000000000000000000000000000040000d", "bytes") + assert verifier.GI_FIRST_BLOCK_ROOT_IN_SUMMARY_CURR() == HexString("0x000000000000000000000000000000000000000000000000000000000040000d", "bytes") + + assert verifier.FIRST_SUPPORTED_SLOT() == 364032 * CHAIN_SLOTS_PER_EPOCH + assert verifier.PIVOT_SLOT() == verifier.FIRST_SUPPORTED_SLOT() + assert verifier.CAPELLA_SLOT() == 194048 * CHAIN_SLOTS_PER_EPOCH diff --git a/tests/regression/test_csm.py b/tests/regression/test_csm.py index 2b69d294a..bb8ad16b2 100644 --- a/tests/regression/test_csm.py +++ b/tests/regression/test_csm.py @@ -1,6 +1,6 @@ import pytest -from brownie import reverts, web3, ZERO_ADDRESS, accounts +from brownie import reverts, web3, ZERO_ADDRESS, accounts, chain from utils.balance import set_balance_in_wei from utils.config import ( @@ -10,7 +10,7 @@ from utils.dsm import UnvetArgs, to_bytes, set_single_guardian from utils.evm_script import encode_error from utils.staking_module import calc_module_reward_shares -from utils.test.csm_helpers import csm_add_node_operator, get_ea_member, csm_upload_keys, get_ea_members +from utils.test.csm_helpers import csm_add_node_operator, csm_upload_keys, get_ics_members, csm_add_ics_node_operator from utils.test.deposits_helpers import fill_deposit_buffer from utils.test.helpers import ETH from utils.test.oracle_report_helpers import ( @@ -36,11 +36,26 @@ def csm(): return contracts.csm +@pytest.fixture(scope="module") +def permissionless_gate(): + return contracts.cs_permissionless_gate + + +@pytest.fixture(scope="module") +def vetted_gate(): + return contracts.cs_vetted_gate + + @pytest.fixture(scope="module") def accounting(): return contracts.cs_accounting +@pytest.fixture(scope="module") +def parameters_registry(): + return contracts.cs_parameters_registry + + @pytest.fixture(scope="module") def fee_distributor(): return contracts.cs_fee_distributor @@ -52,14 +67,14 @@ def fee_oracle(): @pytest.fixture(scope="module") -def early_adoption(): - return contracts.cs_early_adoption +def ejector(): + return contracts.cs_ejector @pytest.fixture -def node_operator(csm, accounting) -> int: - address, proof = get_ea_member() - return csm_add_node_operator(csm, accounting, address, proof) +def node_operator(csm, permissionless_gate, accounting, accounts) -> int: + address = accounts[7].address + return csm_add_node_operator(csm, permissionless_gate, accounting, address) @pytest.fixture @@ -83,6 +98,19 @@ def deposits_to_csm(csm, pause_modules, node_operator, remove_stake_limit): (_, _, depositable) = csm.getStakingModuleSummary() fill_deposit_buffer(depositable) increase_staking_module_share(module_id=CSM_MODULE_ID, share_multiplier=2) + + if contracts.withdrawal_queue.isBunkerModeActive(): + # Disable bunker mode to allow deposits + web3.provider.make_request( + "hardhat_setStorageAt", + [ + contracts.withdrawal_queue.address, + web3.keccak(text="lido.WithdrawalQueue.bunkerModeSinceTimestamp").hex(), + web3.to_hex(2**256 - 1) # type(uint256).max + ], + ) + assert not contracts.withdrawal_queue.isBunkerModeActive() + for i in range(0, depositable, MAX_DEPOSITS): contracts.lido.deposit(MAX_DEPOSITS, CSM_MODULE_ID, "0x", {"from": contracts.deposit_security_module}) @@ -117,19 +145,28 @@ def distribute_reward_tree(node_operator, ref_slot): return tree -@pytest.mark.parametrize("address, proof", get_ea_members()) -def test_add_ea_node_operator(csm, accounting, early_adoption, address, proof): - no_id = csm_add_node_operator(csm, accounting, address, proof) +def get_sys_fee_to_eject(): + withdrawal_request_sys_address = '0x00000961Ef480Eb55e80D19ad83579A64c007002' + val = web3.eth.call({ + "to": withdrawal_request_sys_address, + "data": "0x", + }) + return int.from_bytes(val, "big") + + +@pytest.mark.parametrize("address, proof", get_ics_members()) +def test_add_node_operator_ics(csm, vetted_gate, accounting, address, proof): + no_id = csm_add_ics_node_operator(csm, vetted_gate, accounting, address, proof) no = csm.getNodeOperator(no_id) assert no["managerAddress"] == address assert no["rewardAddress"] == address - assert accounting.getBondCurveId(no_id) == early_adoption.CURVE_ID() + assert accounting.getBondCurveId(no_id) == vetted_gate.curveId() -def test_add_node_operator_permissionless(csm, accounting, accounts): +def test_add_node_operator_permissionless(csm, permissionless_gate, accounting, accounts): address = accounts[8].address - no_id = csm_add_node_operator(csm, accounting, address, proof=[]) + no_id = csm_add_node_operator(csm, permissionless_gate, accounting, address) no = csm.getNodeOperator(no_id) assert no["managerAddress"] == address @@ -137,34 +174,6 @@ def test_add_node_operator_permissionless(csm, accounting, accounts): assert accounting.getBondCurveId(no_id) == accounting.DEFAULT_BOND_CURVE_ID() -def test_add_node_operator_keys_more_than_limit(csm, accounting): - address, proof = get_ea_member() - keys_count = csm.MAX_SIGNING_KEYS_PER_OPERATOR_BEFORE_PUBLIC_RELEASE() + 1 - no_id = csm_add_node_operator(csm, accounting, address, proof, keys_count=keys_count) - no = csm.getNodeOperator(no_id) - - assert no["totalAddedKeys"] == keys_count - - -def test_add_node_operator_permissionless_keys_more_than_limit(csm, accounting, accounts): - keys_count = csm.MAX_SIGNING_KEYS_PER_OPERATOR_BEFORE_PUBLIC_RELEASE() + 1 - address = accounts[8].address - no_id = csm_add_node_operator(csm, accounting, address, proof=[], keys_count=keys_count) - no = csm.getNodeOperator(no_id) - - assert no["totalAddedKeys"] == keys_count - - -def test_upload_keys_more_than_limit(csm, accounting, node_operator): - no = csm.getNodeOperator(node_operator) - keys_before = no["totalAddedKeys"] - keys_count = csm.MAX_SIGNING_KEYS_PER_OPERATOR_BEFORE_PUBLIC_RELEASE() - keys_before + 1 - csm_upload_keys(csm, accounting, node_operator, keys_count) - - no = csm.getNodeOperator(node_operator) - assert no["totalAddedKeys"] == keys_count + keys_before - - @pytest.mark.usefixtures("pause_modules") def test_deposit(node_operator, csm, remove_stake_limit): (_, _, depositable_validators_count) = csm.getStakingModuleSummary() @@ -203,19 +212,11 @@ def test_csm_target_limits(csm, node_operator): assert no["targetLimit"] == target_limit -def test_csm_update_refunded(node_operator): - refunded_validators_count = 1 - with reverts(encode_error("NotSupported()")): - contracts.staking_router.updateRefundedValidatorsCount( - CSM_MODULE_ID, node_operator, refunded_validators_count, {"from": contracts.agent} - ) - - @pytest.mark.usefixtures("deposits_to_csm") def test_csm_report_exited(csm, node_operator, extra_data_service): total_exited = csm.getStakingModuleSummary()["totalExitedValidators"] exited_keys = 5 - extra_data = extra_data_service.collect({}, {(CSM_MODULE_ID, node_operator): exited_keys}, exited_keys, exited_keys) + extra_data = extra_data_service.collect({(CSM_MODULE_ID, node_operator): exited_keys}, exited_keys, exited_keys) oracle_report( extraDataFormat=1, extraDataHashList=extra_data.extra_data_hash_list, @@ -229,24 +230,6 @@ def test_csm_report_exited(csm, node_operator, extra_data_service): assert no["totalExitedKeys"] == exited_keys -@pytest.mark.usefixtures("deposits_to_csm") -def test_csm_report_stuck(csm, node_operator, extra_data_service): - total_exited = csm.getStakingModuleSummary()["totalExitedValidators"] - stuck_keys = 5 - extra_data = extra_data_service.collect({(CSM_MODULE_ID, node_operator): stuck_keys}, {}, stuck_keys, stuck_keys) - oracle_report( - extraDataFormat=1, - extraDataHashList=extra_data.extra_data_hash_list, - extraDataItemsCount=1, - extraDataList=extra_data.extra_data_list, - stakingModuleIdsWithNewlyExitedValidators=[CSM_MODULE_ID], - numExitedValidatorsByStakingModule=[total_exited], - ) - - no = csm.getNodeOperator(node_operator) - assert no["stuckValidatorsCount"] == stuck_keys - - @pytest.mark.usefixtures("deposits_to_csm") def test_csm_get_staking_module_summary(csm, accounting, node_operator, extra_data_service, remove_stake_limit): (exited_before, deposited_before, depositable_before) = contracts.staking_router.getStakingModuleSummary( @@ -255,7 +238,7 @@ def test_csm_get_staking_module_summary(csm, accounting, node_operator, extra_da # Assure there are new exited keys exited_keys = 5 - extra_data = extra_data_service.collect({}, {(CSM_MODULE_ID, node_operator): exited_keys}, exited_keys, exited_keys) + extra_data = extra_data_service.collect({(CSM_MODULE_ID, node_operator): exited_keys}, exited_keys, exited_keys) oracle_report( extraDataFormat=1, extraDataHashList=extra_data.extra_data_hash_list, @@ -288,14 +271,13 @@ def test_csm_get_node_operator_summary(csm, node_operator, extra_data_service): total_exited = csm.getStakingModuleSummary()["totalExitedValidators"] no = csm.getNodeOperator(node_operator) exited_keys = 1 - stuck_keys = 1 extra_data = extra_data_service.collect( - {(CSM_MODULE_ID, node_operator): stuck_keys}, {(CSM_MODULE_ID, node_operator): exited_keys}, 2, 2 + {(CSM_MODULE_ID, node_operator): exited_keys}, exited_keys, exited_keys ) oracle_report( extraDataFormat=1, extraDataHashList=extra_data.extra_data_hash_list, - extraDataItemsCount=2, + extraDataItemsCount=1, extraDataList=extra_data.extra_data_list, stakingModuleIdsWithNewlyExitedValidators=[CSM_MODULE_ID], numExitedValidatorsByStakingModule=[total_exited], @@ -304,9 +286,11 @@ def test_csm_get_node_operator_summary(csm, node_operator, extra_data_service): summary = contracts.staking_router.getNodeOperatorSummary(CSM_MODULE_ID, node_operator) assert summary["targetLimitMode"] == 0 assert summary["targetValidatorsCount"] == 0 - assert summary["stuckValidatorsCount"] == stuck_keys + # DEPRECATED # + assert summary["stuckValidatorsCount"] == 0 assert summary["refundedValidatorsCount"] == 0 assert summary["stuckPenaltyEndTimestamp"] == 0 + ############## assert summary["totalExitedValidators"] == exited_keys assert summary["totalDepositedValidators"] == no["totalDepositedKeys"] assert summary["depositableValidatorsCount"] == 0 @@ -336,7 +320,8 @@ def test_csm_decrease_vetted_keys(csm, node_operator, stranger): @pytest.mark.usefixtures("deposits_to_csm") def test_csm_penalize_node_operator(csm, accounting, node_operator, helpers): bond_shares_before = accounting.getBondShares(node_operator) - tx = csm.submitInitialSlashing(node_operator, 0, {"from": contracts.cs_verifier}) + withdrawal_info = (node_operator, 0, ETH(30)) + tx = csm.submitWithdrawals([withdrawal_info], {"from": contracts.cs_verifier}) assert "StETHBurnRequested" in tx.events burnt_shares = tx.events["StETHBurnRequested"]["amountOfShares"] assert accounting.getBondShares(node_operator) == bond_shares_before - burnt_shares @@ -349,7 +334,7 @@ def test_csm_eth_bond(csm, accounting, node_operator): bond_shares_before = accounting.getBondShares(node_operator) shares = contracts.lido.getSharesByPooledEth(ETH(1)) - csm.depositETH(node_operator, {"from": manager_address, "value": ETH(1)}) + accounting.depositETH(node_operator, {"from": manager_address, "value": ETH(1)}) assert accounting.getBondShares(node_operator) == bond_shares_before + shares @@ -363,7 +348,7 @@ def test_csm_steth_bond(csm, accounting, node_operator): contracts.lido.approve(accounting, ETH(2), {"from": manager_address}) shares = contracts.lido.getSharesByPooledEth(ETH(1)) - csm.depositStETH(node_operator, ETH(1), (0, 0, 0, 0, 0), {"from": manager_address}) + accounting.depositStETH(node_operator, ETH(1), (0, 0, 0, 0, 0), {"from": manager_address}) assert accounting.getBondShares(node_operator) == bond_shares_before + shares @@ -380,14 +365,14 @@ def test_csm_wsteth_bond(csm, accounting, node_operator): contracts.wsteth.getStETHByWstETH(contracts.wsteth.balanceOf(manager_address)) ) bond_shares_before = accounting.getBondShares(node_operator) - csm.depositWstETH( + accounting.depositWstETH( node_operator, contracts.wsteth.balanceOf(manager_address), (0, 0, 0, 0, 0), {"from": manager_address} ) assert accounting.getBondShares(node_operator) == bond_shares_before + shares @pytest.mark.usefixtures("deposits_to_csm") -def test_csm_claim_rewards_steth(csm, node_operator, ref_slot): +def test_csm_claim_rewards_steth(csm, accounting, node_operator, ref_slot): reward_address = csm.getNodeOperator(node_operator)["rewardAddress"] shares_before = contracts.lido.sharesOf(reward_address) accounting_shares_before = contracts.lido.sharesOf(contracts.cs_accounting) @@ -396,48 +381,86 @@ def test_csm_claim_rewards_steth(csm, node_operator, ref_slot): shares = tree.values[0]["value"][1] proof = list(tree.get_proof(tree.find(tree.leaf((node_operator, shares))))) - csm.claimRewardsStETH(node_operator, ETH(1), shares, proof, {"from": reward_address}) + accounting.claimRewardsStETH(node_operator, ETH(1), shares, proof, {"from": reward_address}) shares_after = contracts.lido.sharesOf(reward_address) accounting_shares_after = contracts.lido.sharesOf(contracts.cs_accounting) assert shares_after == shares_before + (accounting_shares_before + shares - accounting_shares_after) @pytest.mark.usefixtures("deposits_to_csm") -def test_csm_claim_rewards_wsteth(csm, node_operator, ref_slot): +def test_csm_claim_rewards_wsteth(csm, accounting, node_operator, ref_slot): tree = distribute_reward_tree(node_operator, ref_slot).tree shares = tree.values[0]["value"][1] proof = list(tree.get_proof(tree.find(tree.leaf((node_operator, shares))))) reward_address = csm.getNodeOperator(node_operator)["rewardAddress"] wsteth_before = contracts.wsteth.balanceOf(reward_address) - csm.claimRewardsWstETH(node_operator, ETH(1), shares, proof, {"from": reward_address}) + accounting.claimRewardsWstETH(node_operator, ETH(1), shares, proof, {"from": reward_address}) assert contracts.wsteth.balanceOf(reward_address) > wsteth_before @pytest.mark.usefixtures("deposits_to_csm") -def test_csm_claim_rewards_eth(csm, node_operator, ref_slot): +def test_csm_claim_rewards_eth(csm, accounting, node_operator, ref_slot): tree = distribute_reward_tree(node_operator, ref_slot).tree shares = tree.values[0]["value"][1] proof = list(tree.get_proof(tree.find(tree.leaf((node_operator, shares))))) reward_address = csm.getNodeOperator(node_operator)["rewardAddress"] withdrawal_requests = contracts.withdrawal_queue.getWithdrawalRequests(reward_address) - csm.claimRewardsUnstETH(node_operator, ETH(1), shares, proof, {"from": reward_address}) + accounting.claimRewardsUnstETH(node_operator, ETH(1), shares, proof, {"from": reward_address}) assert len(contracts.withdrawal_queue.getWithdrawalRequests(reward_address)) == len(withdrawal_requests) + 1 -def test_csm_remove_key(csm, node_operator): +def test_csm_remove_key(csm, parameters_registry, accounting, node_operator): no = csm.getNodeOperator(node_operator) keys_before = no["totalAddedKeys"] manager_address = csm.getNodeOperator(node_operator)["managerAddress"] tx = csm.removeKeys(node_operator, 0, 1, {"from": manager_address}) - assert "KeyRemovalChargeApplied" not in tx.events - assert "BondCharged" not in tx.events - charge_amount = contracts.lido.getPooledEthByShares( - contracts.lido.getSharesByPooledEth(csm.keyRemovalCharge()) - ) - assert charge_amount == 0 # keyRemovalCharge is zero since vote 2025/07/16 + assert "KeyRemovalChargeApplied" in tx.events + assert "BondCharged" in tx.events + + expected_charge_amount = contracts.lido.getPooledEthByShares( + contracts.lido.getSharesByPooledEth(parameters_registry.getKeyRemovalCharge(accounting.DEFAULT_BOND_CURVE_ID())) + ) + assert tx.events["BondCharged"]["toChargeAmount"] == expected_charge_amount no = csm.getNodeOperator(node_operator) assert no["totalAddedKeys"] == keys_before - 1 + + +@pytest.mark.usefixtures("deposits_to_csm") +def test_eject_bad_performer(csm, ejector, node_operator): + eject_payment_value = get_sys_fee_to_eject() + + tx = ejector.ejectBadPerformer( + node_operator, 0, ZERO_ADDRESS, {"value": eject_payment_value, "from": contracts.cs_strikes} + ) + assert "TriggeredExitFeeRecorded" in tx.events + + +@pytest.mark.usefixtures("deposits_to_csm") +def test_voluntary_eject(csm, ejector, node_operator): + eject_payment_value = get_sys_fee_to_eject() + operator_address = csm.getNodeOperator(node_operator)["rewardAddress"] + + tx = ejector.voluntaryEject( + node_operator, 0, 1, ZERO_ADDRESS, {"value": eject_payment_value, "from": operator_address} + ) + assert "TriggeredExitFeeRecorded" not in tx.events + + +def test_report_validator_exit_delay(csm, node_operator): + key, *_ = csm.getSigningKeys(node_operator, 0, 1) + day_in_seconds = 60 * 60 * 24 + + tx = csm.reportValidatorExitDelay(node_operator, 0, key, 7 * day_in_seconds, {"from": contracts.staking_router}) + assert "ValidatorExitDelayProcessed" in tx.events + + +def test_on_validator_exit_triggered(csm, node_operator): + key, *_ = csm.getSigningKeys(node_operator, 0, 1) + exit_type = 3 + + tx = csm.onValidatorExitTriggered(node_operator, key, 1, exit_type, {"from": contracts.staking_router}) + assert "TriggeredExitFeeRecorded" in tx.events diff --git a/utils/config.py b/utils/config.py index a8877702b..4abf5b202 100644 --- a/utils/config.py +++ b/utils/config.py @@ -210,11 +210,6 @@ def simple_dvt(self) -> interface.SimpleDVT: def csm(self) -> interface.CSModule: return interface.CSModule(CSM_ADDRESS) - @property - def cs_early_adoption(self) -> interface.CSEarlyAdoption: - """Deprecated""" - return interface.CSEarlyAdoption(CS_EARLY_ADOPTION_ADDRESS) - @property def cs_permissionless_gate(self) -> interface.CSPermissionlessGate: return interface.CSPermissionlessGate(CS_PERMISSIONLESS_GATE_ADDRESS) @@ -227,6 +222,10 @@ def cs_vetted_gate(self) -> interface.CSVettedGate: def cs_accounting(self) -> interface.CSAccounting: return interface.CSAccounting(CS_ACCOUNTING_ADDRESS) + @property + def cs_parameters_registry(self) -> interface.CSParametersRegistry: + return interface.CSParametersRegistry(CS_PARAMS_REGISTRY_ADDRESS) + @property def cs_fee_distributor(self) -> interface.CSFeeDistributor: return interface.CSFeeDistributor(CS_FEE_DISTRIBUTOR_ADDRESS) @@ -241,15 +240,11 @@ def csm_hash_consensus(self) -> interface.CSHashConsensus: @property def cs_verifier(self) -> interface.CSVerifier: - return interface.CSVerifier(CS_VERIFIER_ADDRESS) - - @property - def cs_verifier_v2(self) -> interface.CSVerifierV2: - return interface.CSVerifierV2(CS_VERIFIER_V2_ADDRESS) + return interface.CSVerifier(CS_VERIFIER_V2_ADDRESS) @property def cs_exit_penalties(self) -> interface.CSExitPenalties: - return interface.CSExitPenalties(CS_EXIT_PENALTIES) + return interface.CSExitPenalties(CS_EXIT_PENALTIES_ADDRESS) @property def cs_ejector(self) -> interface.CSEjector: diff --git a/utils/test/csm_helpers.py b/utils/test/csm_helpers.py index a99bb0be9..c4ed1cb18 100644 --- a/utils/test/csm_helpers.py +++ b/utils/test/csm_helpers.py @@ -5,140 +5,97 @@ from utils.test.keys_helpers import random_pubkeys_batch, random_signatures_batch from utils.config import contracts -def get_ea_member(): - """ - Random address and proof for EA member - """ - address = "0x00200f4e638e81ebe172daa18c9193a33a50bbbd" - proof = [ - "0x6afd64d1f8e5feed98652d45b758fcbff17eea77665d51f0e531d692a5054756", - "0x52e265b49b47b47690ed87febf862cd32a651b9ab187cad973bc9b77749bb219", - "0x35e699543254ce0682e153798e663901c7b14a637c6823def95687ce98c3bfd2", - "0x90c4d893c062e47126e1fb88c62d7f1addb6787d7681c8b4783e77848fd94ce3", - "0xcc571b6d9faf0a49b61d00cb56d518a9ac9bc61b9ef63c7b6376a3ead99bd455", - "0x190eb8e475726914932a14a9f62b854636a9dcb6323c4d97ac6630fcd29dc33c", - "0x4ac93583eb5d1fb5546b438eac0a489b07b0d62910c4bab3e7b41f0042831d48", - "0xcdc54828056fbe5307ece8e4138766177cd9568ffd68564b37d3deaaf112bb6c", - "0x4d63ec7d0dcc7a38ac4984b6ea8fad8255dfd6419c6c66684e49676d3112e062", - "0x5c39f6b822174cc0267fa29cb2c74340b837859bbc95beca29997689334b4895", - "0x2980e52feb24b69169c73a9618107b58ae5bea120649a045aba137b07e822172", - "0xdbaa84b6f34f08ec11a23797a3497898e75dec4e99bf42d63e7cbfee0dee67d6", - "0xc4556dc19f0330ccc6c929b09a965e05c360d32a5c71c3f64b4123fda973b8dd", - "0x617a04e701d0b1c8e0e96c278ba4caf00e2d787e4287e52fcc4b5f248d89c2b3" - ] - return address, proof - - -def get_ea_members(): - """Each ea member from different source""" + +def get_ics_members(): + """Few ICS members from mainnet list""" return (( - "0x113e5bA177D3021E4515e847bc4779B074AA0813", [ # good performer - "0xb3f1d62e731a0ac46f103f3423265baaae773036410890c1ee4bc4ba4a5b6806", - "0xdd218546f8029d89f8bb325d50e9a272543ac9642e88d60c6d5b0f1d11db14ea", - "0x82a14915d66df3004c15749f90a53606faaa8adcf890ef9159974a470df16a1f", - "0x9f7ee78a4e733ab2715190ae5481a1456b81b3d5b65a05cd070bcf95fe7a7c92", - "0x68431bdd53ada7d0fcbc0eeae8a7e0f614cbd3da6b54b16214bfedc9e42ea753", - "0x2006bffe956465add92037dd50b5001f7bfdc9ed531fb40b9bbcdff3586ffb63", - "0xbf0015b0b477df4cd5a81eda856a20d65f1a631f033eeb4d630fbebf962a8310", - "0x03c02b7b15ef3c91ae99e86c4c3b1eee48c776e38ffff1a99dcbe4f78942679f", - "0xacbd1f9b565d87a3156b972c1a860a71b5365992f503821166f2c11f591748ec", - "0x8ac7d39a7d9d96d17f5b42f8ef026c44ebb17bd62c995f12e3124b5ca4bfc5e7", - "0x582edbfcd0fb5f0a95caca952bdb943a8cd008c4d114c586e4e03c839bc7c7cd", - "0x772f2c70f39b9a6848799e13c16fe05bdfd1eded3c2b588834bf751b79a9fce5", - "0x3f53e44db24145c061bbbf7d1df796a0ab059b7125c9c2cacf7064bc3904c9d1", - "0x617a04e701d0b1c8e0e96c278ba4caf00e2d787e4287e52fcc4b5f248d89c2b3" - ]), - ("0x6D08b74BD14b2D6Deb468BA31D578a002D0AdDE8", [ # Galxe point holder - "0x6184b17c37f752a58be2c14d26abf9220efff1349fb5c561d9b688b798237d13", - "0xe2d16f320a6de8ef9c8fdca825bad92bb3df1da7995b035d4c0ce2a68cbd3e2a", - "0x35f55c85e9331c8767bf00735389eebc9ba335f52922809cc9cf8d8487646d27", - "0x6442dd1037d0faced9476b99c7f93987326845cd36114be02abebf734759e8a9", - "0xc7f4e2bc84d3a89a6046c9feae416160dad7b28a6209b1e3dff004a3d2b4d0de", - "0xc69995256422fbd2478a7bb8201c777383493e4c1a2fc6a45620341d8108103d", - "0xd703c9506f78ffe85059902bf94a1da7d0efa195424ee10d436af20867700d7c", - "0xfa6b80e968a2f48fc65a45e6763f5a0d470f7640f75edf648d001cb46acefe3c", - "0x9950a0f220017fcd05a338574cbc289a3c00de804ca8d10867a177afd673c347", - "0x83389a6b368766d86b6d57720596f25ff3aeccd4ad21a3b683dbbd231755a2df", - "0x2980e52feb24b69169c73a9618107b58ae5bea120649a045aba137b07e822172", - "0xdbaa84b6f34f08ec11a23797a3497898e75dec4e99bf42d63e7cbfee0dee67d6", - "0xc4556dc19f0330ccc6c929b09a965e05c360d32a5c71c3f64b4123fda973b8dd", - "0x617a04e701d0b1c8e0e96c278ba4caf00e2d787e4287e52fcc4b5f248d89c2b3" - ]), - ("0xe95fb9768cef2893445bc02e7056dead0c32fe6a", [ # dappnode buyer - "0x6fdf504e61ce21367058bc13a34c21f94a4320e29b75c632aa371dd228f2595e", - "0xeeda87c6ce2ef88e9748f7987a64a7147a93be2297f62f44c75f38e5c5756111", - "0x852b5fdd3cf28c632af3270443231205b4d5fa8186b6e241e4f8d3414bfbb540", - "0xa4d359ba49c62fe93c99b49ac4453cf544252e6bf1a42fababa321bb23850163", - "0x8a9297667d1dbe4f17916ff6bc052e58790a3df7703b22baac3f4d224c06a444", - "0x696335ac8a25acf05c2b7b85bd97e0473219f8fff3bc89f49601ba6084f54e51", - "0x6aa7a7a69448a2170b3dc9f6f6227cd0926dd71962e4c15e63448a984369c7a4", - "0x5f87b1e6bfecfd3440114bd9829647532aad1328699af183aeb490d1406003cd", - "0x9d117f35be949e6db5e479949f91cb0710ea3e85be2a58deed5a0b4c05763fe3", - "0x70d5df1f59c0f5fd1667e832f91b8e389adc70f69a520a9f9ca333861bdb27e2", - "0x398e90a61a92850edce556da82fbb16b5f520bcf3fb3c1a5d7cdc6a1baf4883c", - "0xdbaa84b6f34f08ec11a23797a3497898e75dec4e99bf42d63e7cbfee0dee67d6", - "0xc4556dc19f0330ccc6c929b09a965e05c360d32a5c71c3f64b4123fda973b8dd", - "0x617a04e701d0b1c8e0e96c278ba4caf00e2d787e4287e52fcc4b5f248d89c2b3" - ]), - ("0x024813b4972428003c725ea756348dcd79b826e6", [ # obol teche credentials - "0xfc49117ff5d49126e2ed0ee2a6229678604428fc175670aaf6dfcacfba55c414", - "0xa9011da71acb5f3c61c0cc80f5c8b89f916345efb9c149ead010aac852dfbac3", - "0xa0af25f19dde818bb362aae34d967c6d141cfe4b2666a9aeef5fb03cf705ab1b", - "0xb8a34c5bdc302c3944e1f1919f304aa25168e0db81b7e2b67c6afe8a7fa8cc46", - "0x6c209589c3c08d2b8441263874648617f70ebfd255d513840aa191284b5815a9", - "0x45493cc5f6e07014c06f4fe700bc91cedbe7947bdae3d3bdf960ae67abab3adf", - "0xa6df3cbb3e9113c1c429e842c8999b3597d1b6b55c9c979c2703e995b0f762c6", - "0x9e70b4cb13a9517ad1a4fe4920b02abd9eeab2236b9a541e20beaee5557ad7fd", - "0x0a9dc8737db2646bbfc1539e073b563f203e9bfed2aabacfcd03d9d16e8f9739", - "0x2f362f8032842941fe910be787723b082ab7a21effb5cd38022b36c75a103013", - "0x6a5e8cf1bacfe83bee183d9ed803f679d8714103a8106301ad9e355f7790e901", - "0xd001326ce1fa4bfc303be10f953c87ad779c22268ea03d357da5d8e26659e50b", - "0xd597d21fed5e65b2a6de1c6fe70dfdb2df43ab5495a5c0a01c915e60c14c6edb", - "0xf99292f2fccc3f4fa8cef73512bd5f21a46214d922dfed8e8a65f763c13dfb72" - ]), - ("0xe3a2417f8eaafb93a93dc896724e20d0bc1a1feb", [ # rated - "0x2faac9fec99b1a1d464422f5cc64c153514da1d3a438362ef7f1aaa5f585cf65", - "0xf17a0bdf45def725c1ad7bf6c457d4c749705f02ff4282c6739e54dc8965340b", - "0xa0530504a2c0e61ab5de781f0ee4467097595b7a9815b9b2371e33daf920e25c", - "0x1d95475075f06c85ba13b81f01891bde5cf0af4df6f2693b15586884b4a3fac7", - "0x4a8ebe10d4e6f7bb1cadf1e54b58471a6933a62fd7fd6b4750c645f87347c8bd", - "0x96f7f6c9f3b8c3c45392e1598c4ee9ff2aa0eb655bb428c3977e939a8c2cacf5", - "0x404ba635ed5cce8cbc77c4b0eb581c8383e52a7be1507d9fbb053d86fe132fd4", - "0xa680f8f19b75770eee3435719f5731dccd057b968fabd81b40528a9b689a7b6c", - "0x78fe6adcb23cf69e7533e4a3d0558fdc6f0bf13384e85c7679b6d054b05b34ed", - "0xbab879d3c26f5d5e3816a4ce99f35a6ac8139c8df8053608bea4a76951b17e0d", - "0x15b1fc08779715ad26f61b07d0665a82f118104391b56863bd54e6bbe3ec0ff0", - "0xbe7a61521ebadab96f18fdce4dbcfed777f7799c1a02400052ee9dd838ff1ad4", - "0x5894e79a333e76f3e367a65aaad4cc2ca21650c4a532ce89b28009b0d35ca075", - "0xd597d21fed5e65b2a6de1c6fe70dfdb2df43ab5495a5c0a01c915e60c14c6edb", - "0xf99292f2fccc3f4fa8cef73512bd5f21a46214d922dfed8e8a65f763c13dfb72" - ]), - ("0x61ad82d4466437d4cc250a0ceffbcbd7e07b8f96", [ # stake cat - "0xc863e03646d118cf51af3581cacc457f166134a78b3f4253b219e7f694becc50", - "0x52b3bb9a9105a40e8270cd7e6687f3b010213bd9297748d90b7f90dad779defd", - "0x82e0aec8e35aa0c9b8732a77dc5470b13f3d9d36870acec8568ce73807674a15", - "0x096a86c63fccf92230d8d445d7df591d20f9d71ed5c77141e4bb85a47acbb2e3", - "0x4b875dfece281e9d8ab00c0b8544fa7431dc99661c44e0e6cbaad66f942e5c62", - "0x0590fd2e84b7f5a152881a0d17a6fe0732be6ffd020ada4e91693f8e94696cd8", - "0x1f99300883319c93920319ed5159329a98f2efc356165d9587c316abd6d4cbac", - "0x516c84f2139897f30531bd6e08f3372c0a06bdccd9f17ce91bd2565c79b1afca", - "0x5b698237e78d7b2ef3227a5bc652d030bba9bfa8f21aec555eee0b4f65a24b40", - "0x0a125fd7e859f5e8a67214923c80caaa3e48da3ea985ab0d346ed36a0a92989a", - "0xefb4a879db517af0fb7e4f0731a12d8360bc6a155fcfc7546ace79b55cdafa52", - "0xd2af30f01b69d3f2d1d94e5b401418ffa90b566b1450d7b3310a097701ac694a", - "0x769a53742322902c2080251b628f262577d620d70831c142a59b77910c464a63", - "0xf99292f2fccc3f4fa8cef73512bd5f21a46214d922dfed8e8a65f763c13dfb72"]) + "0xf4c1b69a65f3fdbafcae0786c5fb02dad3e0f353", + [ + "0x5f1fbf1cda5a3dd4d863cd96f6513c24f4f5973e9de0d4524ba5c65bdbff09c6", + "0x459f8832de04e639e148bfdf73d008f9496bc5473b76c76fcb2681dd2806b34f", + "0x38b9c0886c7f5a0115688d538e14318a22856470d265c03778b63e775bfce55a", + "0x007c11b18270c5b5ec10e821b3b2763fd7b28f889b11ec0ae297ab3c55ab0dba", + "0x5cb1b7f8a3505a0d36cb64886bfd5d48e28e62d2ff0fd52aa12d3f5933fe1916", + "0x429e5ae3d28582cb7efcebca05bae5430e9915f8f5bef58c79563938479fa791", + "0x31003203efa870c41458f35927908e17c10f24b615b0e6af863d01c0d8ea3065", + "0xbe5b3c65dec940f408d96c86777263868e45fa74b9848871c1f508bde4d731e1" + ] + ), ("0x9b4064c9d9801f062f377512e61bd19484e7f365", + [ + "0x3dca0828b389d4a4f72eb381ac3edd6f96f51a04b0446db2e7a77892b61ba7c7", + "0x8f5af01242e34310a430415a1bda6ad42ea09b7ed487de5b38c2626d7acb08b1", + "0x2ae5c4b9c69f91edb90caf2594e595e01758c58ae9719311cd3d5d41a32f0b66", + "0x1f7e8e488cf08018ea5796a648b39f2218f1aad23223dcd6c3733cf775950dff", + "0xdbc36608e64ffee165ab914565b18e83b526b81771c46fc4689e7579c426a567", + "0xf676e62b1ca138f69927c196ec23e6f43e4e430e2865637fa5db83cc26670372", + "0x31003203efa870c41458f35927908e17c10f24b615b0e6af863d01c0d8ea3065", + "0xbe5b3c65dec940f408d96c86777263868e45fa74b9848871c1f508bde4d731e1" + ] + ), ("0xb8f8e5751b2c5bad790ff0d2f5574ab38246272e", + [ + "0x96441bf0ea1e2d069560e692ff9b5baec46e83a364ffe3203c5b16d91bc0321f", + "0x5e7c84656af7b03dc12353898f2cafda93166fc9c85aec6d797e7410a38390b2", + "0x90efa708c8677e4589f86f98d788a2b6096b1202358cabc31558ccc716bab269", + "0x1392ec14e24fb65c06527743cafc6c408653a312511fbeb4f7a385ee62cbb201", + "0xc656eee8bb516c8ef59fa3c73f68276c87aa2e707b1394cfe0d0d2151a60ecb8", + "0x994eb932575dc2f3b0a55262fcdfd0108cdf5573228a2fdac5c82bc689cbb90d", + "0xc878b4f250b6b2616245fe079be412dac4605b48aede5ac8f695fe219931051d", + "0xf0e2720fdd888df5369e9aa081347d97603fadbd22f5a1978b08fbaa7c13e6f7" + ] + ), ( + "0x88792bee0d8a4c46acb7a2d8bfbef7e3a678639e", + [ + "0x955c8105dfeed6dd47fccc580e67b00090043c2e0fe00dd9269adaf1864ac073", + "0xfb254edbb3d5dc888dd77e1779146b94268fb5964d0dc9f71815fad8da58612c", + "0x90efa708c8677e4589f86f98d788a2b6096b1202358cabc31558ccc716bab269", + "0x1392ec14e24fb65c06527743cafc6c408653a312511fbeb4f7a385ee62cbb201", + "0xc656eee8bb516c8ef59fa3c73f68276c87aa2e707b1394cfe0d0d2151a60ecb8", + "0x994eb932575dc2f3b0a55262fcdfd0108cdf5573228a2fdac5c82bc689cbb90d", + "0xc878b4f250b6b2616245fe079be412dac4605b48aede5ac8f695fe219931051d", + "0xf0e2720fdd888df5369e9aa081347d97603fadbd22f5a1978b08fbaa7c13e6f7" + ] + ), ( + "0x1ea60eaa2883173e2f8d6b7b025fce33ebc08738", + [ + "0xd5d55039d3530cc365d80d5bdb249c6a21024ecd2d0f3629ab256da3030e5f4a", + "0xad535120c80dea856727178e9ffc03a549ae69c71fa8fd69e7da87500d94ed5e", + "0x18c929c35a4632f9aea2684bba2fb918a1a32035c2c2aa1c50d7d48ab6f84960", + "0x1eae092568547d900432cc755ab381fedac95d4847e6de94bbdec79ca7706b47", + "0xe8c3fe7bc103e7c4da1d5a7d2bafbc6e9d1b1d42cbdb8b75bc9136701e18dd4d", + "0xd456f32b3f050d9204e43c123bb5a81c01c482ea56c9a0249ad60e36c64468af", + "0xbf3f96fd42d14dc9db9126b57923d8845d8434c7e64dcf9a1a23f17afec30aad", + "0xf0e2720fdd888df5369e9aa081347d97603fadbd22f5a1978b08fbaa7c13e6f7" + ] + )) + + +def csm_add_node_operator(csm, permissionless_gate, accounting, node_operator, keys_count=5, curve_id=0): + pubkeys_batch = random_pubkeys_batch(keys_count) + signatures_batch = random_signatures_batch(keys_count) + + value = accounting.getBondAmountByKeysCount(keys_count, curve_id) + set_balance_in_wei(node_operator, value + ETH(10)) + + permissionless_gate.addNodeOperatorETH( + keys_count, + pubkeys_batch, + signatures_batch, + (ZERO_ADDRESS, ZERO_ADDRESS, False), + ZERO_ADDRESS, + {"from": node_operator, "value": value} ) + return csm.getNodeOperatorsCount() - 1 + -def csm_add_node_operator(csm, accounting, node_operator, proof, keys_count=5, curve_id=0): +def csm_add_ics_node_operator(csm, vetted_gate, accounting, node_operator, proof, keys_count=5, curve_id=2): pubkeys_batch = random_pubkeys_batch(keys_count) signatures_batch = random_signatures_batch(keys_count) - value = accounting.getBondAmountByKeysCount['uint256,uint256'](keys_count, curve_id) + value = accounting.getBondAmountByKeysCount(keys_count, curve_id) set_balance_in_wei(node_operator, value + ETH(10)) - csm.addNodeOperatorETH( + vetted_gate.addNodeOperatorETH( keys_count, pubkeys_batch, signatures_batch, @@ -162,8 +119,9 @@ def csm_upload_keys(csm, accounting, no_id, keys_count=5): pubkeys_batch = random_pubkeys_batch(keys_batch) signatures_batch = random_signatures_batch(keys_batch) value = accounting.getRequiredBondForNextKeys(no_id, keys_count) - csm.addValidatorKeysETH(no_id, keys_batch, pubkeys_batch, signatures_batch, { - "from": csm.getNodeOperator(no_id)["managerAddress"], + address = csm.getNodeOperator(no_id)["managerAddress"] + csm.addValidatorKeysETH(address, no_id, keys_batch, pubkeys_batch, signatures_batch, { + "from": address, "value": value }) remaining_keys -= keys_batch @@ -179,7 +137,7 @@ def fill_csm_operators_with_keys(target_operators_count, keys_count): assert contracts.csm.getNodeOperator(no_id)["depositableValidatorsCount"] == keys_count while csm_node_operators_before + added_operators_count < target_operators_count: node_operator = f"0xbb{str(added_operators_count).zfill(38)}" - csm_add_node_operator(contracts.csm, contracts.cs_accounting, node_operator, [], keys_count=keys_count) + csm_add_node_operator(contracts.csm, contracts.cs_permissionless_gate, contracts.cs_accounting, node_operator, + keys_count=keys_count) added_operators_count += 1 return csm_node_operators_before, added_operators_count - diff --git a/utils/test/extra_data.py b/utils/test/extra_data.py index c2c51227e..ea7245784 100644 --- a/utils/test/extra_data.py +++ b/utils/test/extra_data.py @@ -14,7 +14,6 @@ class ItemType(Enum): - EXTRA_DATA_TYPE_STUCK_VALIDATORS = 1 EXTRA_DATA_TYPE_EXITED_VALIDATORS = 2 UNSUPPORTED = 3 @@ -61,8 +60,8 @@ class ItemPayload: node_operator_ids: Sequence[int] vals_counts: Sequence[int] + class ExtraDataLengths: - NEXT_HASH = 32 ITEM_INDEX = 3 ITEM_TYPE = 2 MODULE_ID = 3 @@ -70,6 +69,7 @@ class ExtraDataLengths: NODE_OPERATOR_IDS = 8 STUCK_OR_EXITED_VALS_COUNT = 16 + class ExtraDataService: """ Service that encodes extra data into bytes in correct order. @@ -88,14 +88,12 @@ class ExtraDataService: @classmethod def collect( cls, - stuck_validators: dict[NodeOperatorGlobalIndex, int], exited_validators: dict[NodeOperatorGlobalIndex, int], max_items_count: int, max_no_in_payload_count: int, ) -> ExtraData: - stuck_payloads = cls.build_validators_payloads(stuck_validators, max_no_in_payload_count) exited_payloads = cls.build_validators_payloads(exited_validators, max_no_in_payload_count) - items_count, txs = cls.build_extra_transactions_data(stuck_payloads, exited_payloads, max_items_count) + items_count, txs = cls.build_extra_transactions_data(exited_payloads, max_items_count) extra_data_hash_list, hashed_txs = cls.add_hashes_to_transactions(txs) if items_count: @@ -142,12 +140,10 @@ def build_validators_payloads( @classmethod def build_extra_transactions_data( cls, - stuck_payloads: list[ItemPayload], exited_payloads: list[ItemPayload], max_items_count: int, ) -> tuple[int, list[bytes]]: all_payloads = [ - *[(ItemType.EXTRA_DATA_TYPE_STUCK_VALIDATORS, payload) for payload in stuck_payloads], *[(ItemType.EXTRA_DATA_TYPE_EXITED_VALIDATORS, payload) for payload in exited_payloads], ] diff --git a/utils/test/oracle_report_helpers.py b/utils/test/oracle_report_helpers.py index 7ace0ca5e..ee7df2ef6 100644 --- a/utils/test/oracle_report_helpers.py +++ b/utils/test/oracle_report_helpers.py @@ -127,6 +127,9 @@ def prepare_csm_report(node_operators_rewards: dict, ref_slot): str(tree_cid), str(log_cid), sum(shares.values()), + 0, # rebate + HexBytes(ZERO_HASH), # strikesTreeRoot + "", # strikesTreeCid ) report_data = encode_data_from_abi(report, contracts.cs_fee_oracle.abi, "submitReportData") report_hash = web3.keccak(report_data) diff --git a/utils/test/staking_router_helpers.py b/utils/test/staking_router_helpers.py index c91d50cab..ff76859ce 100644 --- a/utils/test/staking_router_helpers.py +++ b/utils/test/staking_router_helpers.py @@ -2,11 +2,15 @@ from utils.config import contracts from enum import IntEnum +TOTAL_BASIS_POINTS = 10_000 + + class StakingModuleStatus(IntEnum): Active = 0 DepositsPaused = 1 Stopped = 2 + def set_staking_module_status(module_id, staking_module_status: StakingModuleStatus): contracts.staking_router.setStakingModuleStatus(module_id, staking_module_status, {"from": contracts.agent}) @@ -16,8 +20,8 @@ def increase_staking_module_share(module_id, share_multiplier): contracts.staking_router.updateStakingModule( module_id, - module["stakeShareLimit"] * share_multiplier, - module["priorityExitShareThreshold"] * share_multiplier, + min(module["stakeShareLimit"] * share_multiplier, TOTAL_BASIS_POINTS), + min(module["priorityExitShareThreshold"] * share_multiplier, TOTAL_BASIS_POINTS), module["stakingModuleFee"], module["treasuryFee"], module["maxDepositsPerBlock"], From aa7ddb5221544ae8855af7968b8b00a486f5dd11 Mon Sep 17 00:00:00 2001 From: hweawer Date: Thu, 18 Sep 2025 09:32:39 +0200 Subject: [PATCH 20/28] Nethermind voting --- scripts/vote_tw_csm2_mainnet.py | 58 +++++++++++++++++++++++++----- tests/test_vote_tw_csm2_mainnet.py | 52 ++++++++++++++++++++++----- utils/dsm.py | 13 +++++++ 3 files changed, 107 insertions(+), 16 deletions(-) diff --git a/scripts/vote_tw_csm2_mainnet.py b/scripts/vote_tw_csm2_mainnet.py index 0ff8d4059..d2c1d83fd 100644 --- a/scripts/vote_tw_csm2_mainnet.py +++ b/scripts/vote_tw_csm2_mainnet.py @@ -79,10 +79,16 @@ --- ResealManager --- 65. Grant PAUSE_ROLE on TriggerableWithdrawalsGateway to ResealManager 66. Grant RESUME_ROLE on TriggerableWithdrawalsGateway to ResealManager +--- Node Operators Registry rename and reward address change --- +67. Rename Node Operator ID 25 from Nethermind to Twinstake +68. Change Node Operator ID 25 reward address from 0x237DeE529A47750bEcdFa8A59a1D766e3e7B5F91 to 0x36201ed66DbC284132046ee8d99272F8eEeb24c8 +-- DSM rotate guardian --- +69. Remove old Kiln guardian +70. Add new Kiln guardian --- EasyTrack --- -67. Add CSSetVettedGateTree factory to EasyTrack with permissions -68. Add `SubmitValidatorsExitRequestHashes` (SDVT) EVM script factory to Easy Track -69. Add `SubmitValidatorsExitRequestHashes` (Curated Module) EVM script factory to Easy Track +71. Add CSSetVettedGateTree factory to EasyTrack with permissions +72. Add `SubmitValidatorsExitRequestHashes` (SDVT) EVM script factory to Easy Track +73. Add `SubmitValidatorsExitRequestHashes` (Curated Module) EVM script factory to Easy Track # TODO (after vote) Vote #{vote number} passed & executed on ${date+time}, block ${blockNumber}. """ @@ -109,6 +115,7 @@ AGENT, contracts, ) +from utils.dsm import encode_remove_guardian, encode_add_guardian from utils.ipfs import upload_vote_ipfs_description, calculate_vote_ipfs_description from utils.permissions import encode_oz_grant_role, encode_oz_revoke_role from utils.easy_track import ( @@ -119,6 +126,7 @@ from utils.dual_governance import submit_proposals from utils.mainnet_fork import pass_and_exec_dao_vote from utils.config import get_deployer_account, get_priority_fee, get_is_live +from utils.node_operators import encode_set_node_operator_name, encode_set_node_operator_reward_address # ============================== Addresses =================================== # New core contracts implementations @@ -836,6 +844,30 @@ def get_vote_items(): ) ] ), + # "67. Rename Node Operator ID 25 from Nethermind to Twinstake" + agent_forward( + [ + encode_set_node_operator_name(id=25, name="Twinstake", registry=contracts.node_operators_registry), + ] + ), + # "68. Change Node Operator ID 25 reward address from 0x237DeE529A47750bEcdFa8A59a1D766e3e7B5F91 to 0x36201ed66DbC284132046ee8d99272F8eEeb24c8" + agent_forward( + [ + encode_set_node_operator_reward_address(id=17, rewardAddress="0x36201ed66DbC284132046ee8d99272F8eEeb24c8", registry=contracts.node_operators_registry), + ] + ), + # "69. Remove Kiln guardian" + #agent_forward( + # [ + # encode_remove_guardian(guardian_address="", quorum_size=4), + # ] + #), + # "70. Add new Kiln guardian" + #agent_forward( + # [ + # encode_add_guardian(guardian_address="", quorum_size=4), + # ] + #), ] dg_call_script = submit_proposals( [ @@ -847,7 +879,8 @@ def get_vote_items(): ) vote_desc_items, call_script_items = zip( - (""" + ( + """ --- Locator 1. Update locator implementation --- VEB @@ -925,23 +958,32 @@ def get_vote_items(): 64. Grant PAUSE_ROLE on TriggerableWithdrawalsGateway to the new Triggerable Withdrawals GateSeal --- ResealManager --- 65. Grant PAUSE_ROLE on TriggerableWithdrawalsGateway to ResealManager -66. Grant RESUME_ROLE on TriggerableWithdrawalsGateway to ResealManager""", dg_call_script[0]), +66. Grant RESUME_ROLE on TriggerableWithdrawalsGateway to ResealManager +--- Node Operators Registry rename and reward address change --- +67. Rename Node Operator ID 25 from Nethermind to Twinstake +68. Change Node Operator ID 25 reward address from 0x237DeE529A47750bEcdFa8A59a1D766e3e7B5F91 to 0x36201ed66DbC284132046ee8d99272F8eEeb24c8 +--- EasyTrack --- +69. Add CSSetVettedGateTree factory to EasyTrack with permissions +70. Add `SubmitValidatorsExitRequestHashes` (SDVT) EVM script factory to Easy Track +71. Add `SubmitValidatorsExitRequestHashes` (Curated Module) EVM script factory to Easy Track""", + dg_call_script[0], + ), ( - "67. Add CSSetVettedGateTree factory to EasyTrack with permissions", + "69. Add CSSetVettedGateTree factory to EasyTrack with permissions", add_evmscript_factory( factory=EASYTRACK_CS_SET_VETTED_GATE_TREE_FACTORY, permissions=(create_permissions(interface.CSVettedGate(CS_VETTED_GATE_ADDRESS), "setTreeParams")), ), ), ( - "68. Add `SubmitValidatorsExitRequestHashes` (SDVT) EVM script factory to Easy Track", + "70. Add `SubmitValidatorsExitRequestHashes` (SDVT) EVM script factory to Easy Track", add_evmscript_factory( factory=EASYTRACK_SDVT_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY, permissions=(create_permissions(contracts.validators_exit_bus_oracle, "submitExitRequestsHash")), ), ), ( - "69. Add `SubmitValidatorsExitRequestHashes` (Curated Module) EVM script factory to Easy Track", + "71. Add `SubmitValidatorsExitRequestHashes` (Curated Module) EVM script factory to Easy Track", add_evmscript_factory( factory=EASYTRACK_CURATED_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY, permissions=(create_permissions(contracts.validators_exit_bus_oracle, "submitExitRequestsHash")), diff --git a/tests/test_vote_tw_csm2_mainnet.py b/tests/test_vote_tw_csm2_mainnet.py index 4abeb1246..5b70cf080 100644 --- a/tests/test_vote_tw_csm2_mainnet.py +++ b/tests/test_vote_tw_csm2_mainnet.py @@ -23,14 +23,18 @@ from utils.voting import find_metadata_by_vote_id from utils.ipfs import get_lido_vote_cid_from_str from utils.dual_governance import PROPOSAL_STATUS +from utils.test.event_validators.node_operators_registry import ( + validate_node_operator_name_set_event, + validate_node_operator_reward_address_set_event, + NodeOperatorNameSetItem, + NodeOperatorRewardAddressSetItem, +) from utils.test.event_validators.dual_governance import validate_dual_governance_submit_event from utils.test.tx_tracing_helpers import group_voting_events_from_receipt, group_dg_events_from_receipt from utils.test.event_validators.easy_track import validate_evmscript_factory_added_event, EVMScriptFactoryAdded from utils.test.event_validators.dual_governance import validate_dual_governance_submit_event from utils.dual_governance import wait_for_noon_utc_to_satisfy_time_constrains from utils.config import ( - DUAL_GOVERNANCE_EXECUTORS, - LDO_HOLDER_ADDRESS_FOR_TESTS, CS_MODULE_ID, CS_MODULE_MODULE_FEE_BP, CS_MODULE_MAX_DEPOSITS_PER_BLOCK, @@ -38,8 +42,6 @@ CS_MODULE_TREASURY_FEE_BP, CS_GATE_SEAL_ADDRESS, CSM_COMMITTEE_MS, - ARAGON_KERNEL, - AGENT, contracts, ) @@ -182,8 +184,9 @@ def check_proxy_implementation(proxy_address, expected_impl): VOTING = "0x2e59A20f205bB85a89C53f1936454680651E618e" EMERGENCY_PROTECTED_TIMELOCK = "0xCE0425301C85c5Ea2A0873A2dEe44d78E02D2316" DUAL_GOVERNANCE = "0xcdF49b058D606AD34c5789FD8c3BF8B3E54bA2db" -DUAL_GOVERNANCE_ADMIN_EXECUTOR = "" -AGENT = "" +DUAL_GOVERNANCE_ADMIN_EXECUTOR = "0x23E0B465633FF5178808F4A75186E2F2F9537021" +AGENT = "0x3e40D73EB977Dc6a537aF587D48316feE66E9C8c" +ARAGON_KERNEL = "0xb8FFC3Cd6e7Cf5a098A1c92F48009765B24088Dc" # New core contracts implementations LIDO_LOCATOR_IMPL = "0x003f20CD17e7683A7F88A7AfF004f0C44F0cfB31" @@ -251,6 +254,13 @@ def check_proxy_implementation(proxy_address, expected_impl): EXPECTED_DG_EVENTS_COUNT = 1 IPFS_DESCRIPTION_HASH = "" +NETHERMIND_NO_ID = 25 +NETHERMIND_NO_NAME_OLD = "Nethermind" +NETHERMIND_NO_NAME_NEW = "Twinstake" +NETHERMIND_NO_STAKING_REWARDS_ADDRESS_OLD = "0x237DeE529A47750bEcdFa8A59a1D766e3e7B5F91" +NETHERMIND_NO_STAKING_REWARDS_ADDRESS_NEW = "0x36201ed66DbC284132046ee8d99272F8eEeb24c8" +NODE_OPERATORS_REGISTRY_ADDRESS = "0x55032650b14df07b85bF18A3a3eC8E0Af2e028d5" + def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_governance_proposal_calls): # Save original implementations for comparison @@ -276,6 +286,8 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g cs_vetted_gate = interface.CSVettedGate(CS_VETTED_GATE_ADDRESS) cs_verifier_v2 = interface.CSVerifierV2(CS_VERIFIER_V2_ADDRESS) + no_registry = interface.NodeOperatorsRegistry(NODE_OPERATORS_REGISTRY_ADDRESS) + # START VOTE if vote_ids_from_env: @@ -481,6 +493,12 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g display_voting_events(vote_tx) vote_events = group_voting_events_from_receipt(vote_tx) + # Rename Nethermind NO + nethermind_no_data_before = no_registry.getNodeOperator(NETHERMIND_NO_ID, True) + + assert nethermind_no_data_before["rewardAddress"] == NETHERMIND_NO_STAKING_REWARDS_ADDRESS_OLD + assert nethermind_no_data_before["name"] == NETHERMIND_NO_NAME_OLD + # ======================================================================= # ========================= After voting checks ========================= @@ -657,7 +675,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g # --- VALIDATE EVENTS --- voting_events = group_voting_events_from_receipt(vote_tx) - dg_execution_events = group_dg_events_from_receipt(dg_tx, timelock=TIMELOCK, admin_executor=DUAL_GOVERNANCE_EXECUTORS[0]) + dg_execution_events = group_dg_events_from_receipt(dg_tx, timelock=TIMELOCK, admin_executor=DUAL_GOVERNANCE_ADMIN_EXECUTOR) # Validate voting events structure assert len(voting_events) == 4, "Unexpected number of voting events" @@ -1145,4 +1163,22 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g role_hash=triggerable_withdrawals_gateway.RESUME_ROLE().hex(), account=RESEAL_MANAGER, emitted_by=triggerable_withdrawals_gateway - ) \ No newline at end of file + ) + + # Validate Nethermind NO name change + validate_node_operator_name_set_event( + dg_events[66], + NodeOperatorNameSetItem(nodeOperatorId=NETHERMIND_NO_ID, name=NETHERMIND_NO_NAME_NEW), + emitted_by=no_registry, + is_dg_event=True, + ) + + # Validate Nethermind NO rewards address change + validate_node_operator_reward_address_set_event( + dg_events[67], + NodeOperatorRewardAddressSetItem( + nodeOperatorId=NETHERMIND_NO_ID, reward_address=NETHERMIND_NO_STAKING_REWARDS_ADDRESS_NEW + ), + emitted_by=no_registry, + is_dg_event=True, + ) diff --git a/utils/dsm.py b/utils/dsm.py index 9b28aed29..a0f6d47fc 100644 --- a/utils/dsm.py +++ b/utils/dsm.py @@ -126,3 +126,16 @@ def set_single_guardian(dsm, agent, new_guardian): assert len(dsm.getGuardians()) == 1 assert dsm.isGuardian(new_guardian.address) + + +def encode_add_guardian(dsm, guardian_address, quorum_size): + return ( + dsm.address, + dsm.addGuardian.encode_input(guardian_address, quorum_size) + ) + +def encode_remove_guardian(dsm, guardian_address, quorum_size): + return ( + dsm.address, + dsm.removeGuardian.encode_input(guardian_address, quorum_size) + ) \ No newline at end of file From 1e4c70a85a9f63e4dff78508486f8a0bafe58060 Mon Sep 17 00:00:00 2001 From: hweawer Date: Thu, 18 Sep 2025 10:50:06 +0200 Subject: [PATCH 21/28] dg_proposal_calls in tests --- tests/test_vote_tw_csm2_mainnet.py | 583 ++++++++++++++++++++++++++++- 1 file changed, 570 insertions(+), 13 deletions(-) diff --git a/tests/test_vote_tw_csm2_mainnet.py b/tests/test_vote_tw_csm2_mainnet.py index 5b70cf080..68975bb17 100644 --- a/tests/test_vote_tw_csm2_mainnet.py +++ b/tests/test_vote_tw_csm2_mainnet.py @@ -196,7 +196,7 @@ def check_proxy_implementation(proxy_address, expected_impl): STAKING_ROUTER_IMPL = "0xd5F04A81ac472B2cB32073CE9dDABa6FaF022827" NODE_OPERATORS_REGISTRY_IMPL = "0x95F00b016bB31b7182D96D25074684518246E42a" -TRIGGERABLE_WITHDRAWALS_GATEWAY = "0x6679090D92b08a2a686eF8614feECD8cDFE209db" +TRIGGERABLE_WITHDRAWALS_GATEWAY = "0xDC00116a0D3E064427dA2600449cfD2566B3037B" VALIDATOR_EXIT_VERIFIER = "0xFd4386A8795956f4B6D01cbb6dB116749731D7bD" # Add missing constants @@ -220,19 +220,40 @@ def check_proxy_implementation(proxy_address, expected_impl): NOR_EXIT_DEADLINE_IN_SEC = 172800 # CSM -CS_MODULE_NEW_TARGET_SHARE_BP = 1600 # 16% -CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP = 2100 # 21% +CS_MODULE_NEW_TARGET_SHARE_BP = 3500 # 3.5% +CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP = 3750 # 3.75% -CS_ACCOUNTING_IMPL_V2_ADDRESS = "0x9483b34504292a0E4f6509e5887D2c68f7129638" -CS_FEE_DISTRIBUTOR_IMPL_V2_ADDRESS = "0xe05F7Aab7177D73f26e62a5296120583F5F18031" -CS_FEE_ORACLE_IMPL_V2_ADDRESS = "0x752fF00fcacdB66Bc512a067F15A5E0B0b50EADB" -CSM_IMPL_V2_ADDRESS = "0x9aE387EB2abA80B9B1ebc145597D593EFAE61f31" +CS_ACCOUNTING_IMPL_V2_ADDRESS = "0x6f09d2426c7405C5546413e6059F884D2D03f449" +CS_FEE_DISTRIBUTOR_IMPL_V2_ADDRESS = "0x5DCF7cF7c6645E9E822a379dF046a8b0390251A1" +CS_FEE_ORACLE_IMPL_V2_ADDRESS = "0xe0B234f99E413E27D9Bc31aBba9A49A3e570Da97" +CSM_IMPL_V2_ADDRESS = "0x1eB6d4da13ca9566c17F526aE0715325d7a07665" -CS_GATE_SEAL_V2_ADDRESS = "0x94a3aEB0E9148F64CB453Be2BDe2Bc0148f6AC24" -CS_EJECTOR_ADDRESS = "0x21e271cBa32672B106737AbeB3a45E53Fe9a0df4" -CS_PERMISSIONLESS_GATE_ADDRESS = "0x5553077102322689876A6AdFd48D75014c28acfb" -CS_VETTED_GATE_ADDRESS = "0x10a254E724fe2b7f305F76f3F116a3969c53845f" -CS_VERIFIER_V2_ADDRESS = "0xf805b3711cBB48F15Ae2bb27095ddC38c5339968" +CS_GATE_SEAL_V2_ADDRESS = "0xE1686C2E90eb41a48356c1cC7FaA17629af3ADB3" + +# CSM consensus version +CSM_CONSENSUS_VERSION = 3 + +# Bond curves for CS Accounting +CS_CURVES = [ + ([1, 2.4 * 10**18], [2, 1.3 * 10**18]), # Default Curve + ([1, 1.5 * 10**18], [2, 1.3 * 10**18]), # Legacy EA Curve +] +CS_ICS_GATE_BOND_CURVE = ([1, 1.5 * 10**18], [2, 1.3 * 10**18]) # Identified Community Stakers Gate Bond Curve + +# CSM committee and config addresses (imported from config in actual script) +CSM_COMMITTEE_MS = "0x7a7a6e7dcF36Bc4FaAC3A5070D85b8b9E2D5e4d3" # TODO: Get actual address from config +CS_GATE_SEAL_ADDRESS = "0x7a7a6e7dcF36Bc4FaAC3A5070D85b8b9E2D5e4d3" # TODO: Get actual address from config + +# CSM staking module constants (from config) +CS_MODULE_ID = 3 +CS_MODULE_MODULE_FEE_BP = 800 # 8% +CS_MODULE_TREASURY_FEE_BP = 200 # 2% +CS_MODULE_MAX_DEPOSITS_PER_BLOCK = 50 +CS_MODULE_MIN_DEPOSIT_BLOCK_DISTANCE = 25 +CS_EJECTOR_ADDRESS = "0xc72b58aa02E0e98cF8A4a0E9Dce75e763800802C" +CS_PERMISSIONLESS_GATE_ADDRESS = "0xcF33a38111d0B1246A3F38a838fb41D626B454f0" +CS_VETTED_GATE_ADDRESS = "0xB314D4A76C457c93150d308787939063F4Cc67E0" +CS_VERIFIER_V2_ADDRESS = "0xdC5FE1782B6943f318E05230d688713a560063DC" CS_CURVES = [ ([1, 2.4 * 10**18], [2, 1.3 * 10**18]), # Default Curve @@ -261,6 +282,542 @@ def check_proxy_implementation(proxy_address, expected_impl): NETHERMIND_NO_STAKING_REWARDS_ADDRESS_NEW = "0x36201ed66DbC284132046ee8d99272F8eEeb24c8" NODE_OPERATORS_REGISTRY_ADDRESS = "0x55032650b14df07b85bF18A3a3eC8E0Af2e028d5" +NODE_OPERATORS_REGISTRY_ARAGON_APP_ID = "0x7071f283424072341f856ac9e947e7ec0eb68719f757a7e785979b6b8717579d" +SIMPLE_DVT_ARAGON_APP_ID = "0xe1635b63b5f7b5e545f2a637558a4029dea7905361a2f0fc28c66e9136cf86a4" + + +import pytest +from utils.agent import agent_forward +from utils.permissions import encode_oz_grant_role, encode_oz_revoke_role +from utils.node_operators import encode_set_node_operator_name, encode_set_node_operator_reward_address + + +@pytest.fixture(scope="module") +def dual_governance_proposal_calls(): + """Returns list of dual governance proposal calls for events checking""" + + # Helper function to encode proxy upgrades + def encode_proxy_upgrade_to(proxy_contract, new_impl_address): + return (proxy_contract.address, proxy_contract.proxy__upgradeTo.encode_input(new_impl_address)) + + # Helper function to encode oracle consensus upgrades + def encode_oracle_upgrade_consensus(oracle_contract, new_version): + return (oracle_contract.address, oracle_contract.setConsensusVersion.encode_input(new_version)) + + # Cast contracts to OssifiableProxy interface to access proxy methods + lido_locator_proxy = interface.OssifiableProxy(contracts.lido_locator.address) + vebo_proxy = interface.OssifiableProxy(contracts.validators_exit_bus_oracle.address) + withdrawal_vault_proxy = interface.OssifiableProxy(contracts.withdrawal_vault.address) + accounting_oracle_proxy = interface.OssifiableProxy(contracts.accounting_oracle.address) + staking_router_proxy = interface.OssifiableProxy(contracts.staking_router.address) + csm_proxy = interface.OssifiableProxy(contracts.csm.address) + cs_accounting_proxy = interface.OssifiableProxy(contracts.cs_accounting.address) + cs_fee_oracle_proxy = interface.OssifiableProxy(contracts.cs_fee_oracle.address) + cs_fee_distributor_proxy = interface.OssifiableProxy(contracts.cs_fee_distributor.address) + + # Create all the dual governance calls that match the voting script + dg_items = [ + # 1. Update locator implementation + agent_forward([encode_proxy_upgrade_to(lido_locator_proxy, LIDO_LOCATOR_IMPL)]), + + # 2. Update VEBO implementation + agent_forward([encode_proxy_upgrade_to(vebo_proxy, VALIDATORS_EXIT_BUS_ORACLE_IMPL)]), + + # 3. Call finalizeUpgrade_v2 on VEBO + agent_forward([ + (contracts.validators_exit_bus_oracle.address, + contracts.validators_exit_bus_oracle.finalizeUpgrade_v2.encode_input(600, 11200, 1, 48*3600)) + ]), + + # 4. Grant VEBO role MANAGE_CONSENSUS_VERSION_ROLE to the AGENT + agent_forward([ + encode_oz_grant_role( + contract=contracts.validators_exit_bus_oracle, + role_name="MANAGE_CONSENSUS_VERSION_ROLE", + grant_to=contracts.agent + ) + ]), + + # 5. Bump VEBO consensus version to 4 + agent_forward([encode_oracle_upgrade_consensus(contracts.validators_exit_bus_oracle, VEBO_CONSENSUS_VERSION)]), + + # 6. Revoke VEBO role MANAGE_CONSENSUS_VERSION_ROLE from the AGENT + agent_forward([ + encode_oz_revoke_role( + contract=contracts.validators_exit_bus_oracle, + role_name="MANAGE_CONSENSUS_VERSION_ROLE", + revoke_from=contracts.agent + ) + ]), + + # 7. Grant SUBMIT_REPORT_HASH_ROLE on VEBO to EasyTrack executor + agent_forward([ + encode_oz_grant_role( + contract=contracts.validators_exit_bus_oracle, + role_name="SUBMIT_REPORT_HASH_ROLE", + grant_to=EASYTRACK_EVMSCRIPT_EXECUTOR + ) + ]), + + # 8. Grant TWG role ADD_FULL_WITHDRAWAL_REQUEST_ROLE to CS Ejector + agent_forward([ + encode_oz_grant_role( + contract=interface.TriggerableWithdrawalsGateway(TRIGGERABLE_WITHDRAWALS_GATEWAY), + role_name="ADD_FULL_WITHDRAWAL_REQUEST_ROLE", + grant_to=CS_EJECTOR_ADDRESS + ) + ]), + + # 9. Grant TWG role ADD_FULL_WITHDRAWAL_REQUEST_ROLE to VEBO + agent_forward([ + encode_oz_grant_role( + contract=interface.TriggerableWithdrawalsGateway(TRIGGERABLE_WITHDRAWALS_GATEWAY), + role_name="ADD_FULL_WITHDRAWAL_REQUEST_ROLE", + grant_to=contracts.validators_exit_bus_oracle.address + ) + ]), + + # 10. Connect TWG to Dual Governance tiebreaker + agent_forward([ + (interface.DualGovernance(DUAL_GOVERNANCE).address, + interface.DualGovernance(DUAL_GOVERNANCE).addTiebreakerSealableWithdrawalBlocker.encode_input(TRIGGERABLE_WITHDRAWALS_GATEWAY)) + ]), + + # 11. Update WithdrawalVault implementation + agent_forward([encode_proxy_upgrade_to(withdrawal_vault_proxy, WITHDRAWAL_VAULT_IMPL)]), + + # 12. Call finalizeUpgrade_v2() on WithdrawalVault + agent_forward([ + (contracts.withdrawal_vault.address, contracts.withdrawal_vault.finalizeUpgrade_v2.encode_input()) + ]), + + # 13. Update Accounting Oracle implementation + agent_forward([encode_proxy_upgrade_to(accounting_oracle_proxy, ACCOUNTING_ORACLE_IMPL)]), + + # 14. Grant AO MANAGE_CONSENSUS_VERSION_ROLE to the AGENT + agent_forward([ + encode_oz_grant_role( + contract=contracts.accounting_oracle, + role_name="MANAGE_CONSENSUS_VERSION_ROLE", + grant_to=contracts.agent + ) + ]), + + # 15. Bump AO consensus version to 4 + agent_forward([encode_oracle_upgrade_consensus(contracts.accounting_oracle, AO_CONSENSUS_VERSION)]), + + # 16. Revoke AO MANAGE_CONSENSUS_VERSION_ROLE from the AGENT + agent_forward([ + encode_oz_revoke_role( + contract=contracts.accounting_oracle, + role_name="MANAGE_CONSENSUS_VERSION_ROLE", + revoke_from=contracts.agent + ) + ]), + + # 17. Call finalizeUpgrade_v3() on AO + agent_forward([ + (contracts.accounting_oracle.address, contracts.accounting_oracle.finalizeUpgrade_v3.encode_input()) + ]), + + # 18. Update SR implementation + agent_forward([encode_proxy_upgrade_to(staking_router_proxy, STAKING_ROUTER_IMPL)]), + + # 19. Call finalizeUpgrade_v3() on SR + agent_forward([ + (contracts.staking_router.address, contracts.staking_router.finalizeUpgrade_v3.encode_input()) + ]), + + # 20. Grant SR role REPORT_VALIDATOR_EXITING_STATUS_ROLE to ValidatorExitVerifier + agent_forward([ + encode_oz_grant_role( + contract=contracts.staking_router, + role_name="REPORT_VALIDATOR_EXITING_STATUS_ROLE", + grant_to=VALIDATOR_EXIT_VERIFIER + ) + ]), + + # 21. Grant SR role REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE to TWG + agent_forward([ + encode_oz_grant_role( + contract=contracts.staking_router, + role_name="REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE", + grant_to=TRIGGERABLE_WITHDRAWALS_GATEWAY + ) + ]), + + # 22-27: Kernel and registry upgrades + # 22. Grant APP_MANAGER_ROLE role to the AGENT + agent_forward([ + (contracts.acl.address, + contracts.acl.grantPermission.encode_input( + AGENT, + ARAGON_KERNEL, + web3.keccak(text="APP_MANAGER_ROLE") + )) + ]), + + # 23. Update NodeOperatorsRegistry implementation + agent_forward([ + (contracts.kernel.address, + contracts.kernel.setApp.encode_input( + contracts.kernel.APP_BASES_NAMESPACE(), + NODE_OPERATORS_REGISTRY_ARAGON_APP_ID, + NODE_OPERATORS_REGISTRY_IMPL + )) + ]), + + # 24. Call finalizeUpgrade_v4 on Curated Staking Module + agent_forward([ + (interface.NodeOperatorsRegistry(contracts.node_operators_registry).address, + interface.NodeOperatorsRegistry(contracts.node_operators_registry).finalizeUpgrade_v4.encode_input(NOR_EXIT_DEADLINE_IN_SEC)) + ]), + + # 25. Update SDVT implementation + agent_forward([ + (contracts.kernel.address, + contracts.kernel.setApp.encode_input( + contracts.kernel.APP_BASES_NAMESPACE(), + SIMPLE_DVT_ARAGON_APP_ID, + NODE_OPERATORS_REGISTRY_IMPL + )) + ]), + + # 26. Call finalizeUpgrade_v4 on SDVT + agent_forward([ + (interface.NodeOperatorsRegistry(contracts.simple_dvt).address, + interface.NodeOperatorsRegistry(contracts.simple_dvt).finalizeUpgrade_v4.encode_input(NOR_EXIT_DEADLINE_IN_SEC)) + ]), + + # 27. Revoke APP_MANAGER_ROLE role from the AGENT + agent_forward([ + (contracts.acl.address, + contracts.acl.revokePermission.encode_input( + AGENT, + ARAGON_KERNEL, + web3.keccak(text="APP_MANAGER_ROLE") + )) + ]), + + # 28-33: Oracle daemon config changes + agent_forward([ + encode_oz_grant_role( + contract=contracts.oracle_daemon_config, + role_name="CONFIG_MANAGER_ROLE", + grant_to=contracts.agent + ) + ]), + + agent_forward([ + (contracts.oracle_daemon_config.address, + contracts.oracle_daemon_config.unset.encode_input('NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP')) + ]), + + agent_forward([ + (contracts.oracle_daemon_config.address, + contracts.oracle_daemon_config.unset.encode_input('VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS')) + ]), + + agent_forward([ + (contracts.oracle_daemon_config.address, + contracts.oracle_daemon_config.unset.encode_input('VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS')) + ]), + + agent_forward([ + (contracts.oracle_daemon_config.address, + contracts.oracle_daemon_config.set.encode_input('EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS', EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS)) + ]), + + agent_forward([ + encode_oz_revoke_role( + contract=contracts.oracle_daemon_config, + role_name="CONFIG_MANAGER_ROLE", + revoke_from=contracts.agent + ) + ]), + + # CSM upgrades and role changes (steps 34-59) + # 34. Upgrade CSM implementation on proxy + agent_forward([encode_proxy_upgrade_to(csm_proxy, CSM_IMPL_V2_ADDRESS)]), + + # 35. Call finalizeUpgradeV2() on CSM contract + agent_forward([(contracts.csm.address, contracts.csm.finalizeUpgradeV2.encode_input())]), + + # 36. Upgrade CSAccounting implementation on proxy + agent_forward([encode_proxy_upgrade_to(cs_accounting_proxy, CS_ACCOUNTING_IMPL_V2_ADDRESS)]), + + # 37. Call finalizeUpgradeV2(bondCurves) on CSAccounting contract + agent_forward([ + (contracts.cs_accounting.address, + contracts.cs_accounting.finalizeUpgradeV2.encode_input(CS_CURVES)) + ]), + + # 38. Upgrade CSFeeOracle implementation on proxy + agent_forward([encode_proxy_upgrade_to(cs_fee_oracle_proxy, CS_FEE_ORACLE_IMPL_V2_ADDRESS)]), + + # 39. Call finalizeUpgradeV2(consensusVersion) on CSFeeOracle contract + agent_forward([ + (contracts.cs_fee_oracle.address, + contracts.cs_fee_oracle.finalizeUpgradeV2.encode_input(CSM_CONSENSUS_VERSION)) + ]), + + # 40. Upgrade CSFeeDistributor implementation on proxy + agent_forward([encode_proxy_upgrade_to(cs_fee_distributor_proxy, CS_FEE_DISTRIBUTOR_IMPL_V2_ADDRESS)]), + + # 41. Call finalizeUpgradeV2(admin) on CSFeeDistributor contract + agent_forward([ + (contracts.cs_fee_distributor.address, + contracts.cs_fee_distributor.finalizeUpgradeV2.encode_input(contracts.agent)) + ]), + + # 42. Revoke CSAccounting role SET_BOND_CURVE_ROLE from the CSM contract + agent_forward([ + encode_oz_revoke_role( + contract=contracts.cs_accounting, + role_name="SET_BOND_CURVE_ROLE", + revoke_from=contracts.csm + ) + ]), + + # 43. Revoke CSAccounting role RESET_BOND_CURVE_ROLE from the CSM contract + agent_forward([ + encode_oz_revoke_role( + contract=contracts.cs_accounting, + role_name="RESET_BOND_CURVE_ROLE", + revoke_from=contracts.csm + ) + ]), + + # 44. Revoke CSAccounting role RESET_BOND_CURVE_ROLE from the CSM committee + agent_forward([ + encode_oz_revoke_role( + contract=contracts.cs_accounting, + role_name="RESET_BOND_CURVE_ROLE", + revoke_from=CSM_COMMITTEE_MS + ) + ]), + + # 45. Grant CSM role CREATE_NODE_OPERATOR_ROLE for the permissionless gate + agent_forward([ + encode_oz_grant_role( + contract=contracts.csm, + role_name="CREATE_NODE_OPERATOR_ROLE", + grant_to=CS_PERMISSIONLESS_GATE_ADDRESS + ) + ]), + + # 46. Grant CSM role CREATE_NODE_OPERATOR_ROLE for the vetted gate + agent_forward([ + encode_oz_grant_role( + contract=contracts.csm, + role_name="CREATE_NODE_OPERATOR_ROLE", + grant_to=CS_VETTED_GATE_ADDRESS + ) + ]), + + # 47. Grant CSAccounting role SET_BOND_CURVE_ROLE for the vetted gate + agent_forward([ + encode_oz_grant_role( + contract=contracts.cs_accounting, + role_name="SET_BOND_CURVE_ROLE", + grant_to=CS_VETTED_GATE_ADDRESS + ) + ]), + + # 48. Revoke role VERIFIER_ROLE from the previous instance of the Verifier contract + agent_forward([ + encode_oz_revoke_role( + contract=contracts.csm, + role_name="VERIFIER_ROLE", + revoke_from=contracts.cs_verifier + ) + ]), + + # 49. Grant role VERIFIER_ROLE to the new instance of the Verifier contract + agent_forward([ + encode_oz_grant_role( + contract=contracts.csm, + role_name="VERIFIER_ROLE", + grant_to=CS_VERIFIER_V2_ADDRESS + ) + ]), + + # 50. Revoke CSM role PAUSE_ROLE from the previous GateSeal instance + agent_forward([ + encode_oz_revoke_role( + contract=contracts.csm, + role_name="PAUSE_ROLE", + revoke_from=CS_GATE_SEAL_ADDRESS + ) + ]), + + # 51. Revoke CSAccounting role PAUSE_ROLE from the previous GateSeal instance + agent_forward([ + encode_oz_revoke_role( + contract=contracts.cs_accounting, + role_name="PAUSE_ROLE", + revoke_from=CS_GATE_SEAL_ADDRESS + ) + ]), + + # 52. Revoke CSFeeOracle role PAUSE_ROLE from the previous GateSeal instance + agent_forward([ + encode_oz_revoke_role( + contract=contracts.cs_fee_oracle, + role_name="PAUSE_ROLE", + revoke_from=CS_GATE_SEAL_ADDRESS + ) + ]), + + # 53. Grant CSM role PAUSE_ROLE for the new GateSeal instance + agent_forward([ + encode_oz_grant_role( + contract=contracts.csm, + role_name="PAUSE_ROLE", + grant_to=CS_GATE_SEAL_V2_ADDRESS + ) + ]), + + # 54. Grant CSAccounting role PAUSE_ROLE for the new GateSeal instance + agent_forward([ + encode_oz_grant_role( + contract=contracts.cs_accounting, + role_name="PAUSE_ROLE", + grant_to=CS_GATE_SEAL_V2_ADDRESS + ) + ]), + + # 55. Grant CSFeeOracle role PAUSE_ROLE for the new GateSeal instance + agent_forward([ + encode_oz_grant_role( + contract=contracts.cs_fee_oracle, + role_name="PAUSE_ROLE", + grant_to=CS_GATE_SEAL_V2_ADDRESS + ) + ]), + + # 56. Grant MANAGE_BOND_CURVES_ROLE to the AGENT + agent_forward([ + encode_oz_grant_role( + contract=contracts.cs_accounting, + role_name="MANAGE_BOND_CURVES_ROLE", + grant_to=contracts.agent + ) + ]), + + # 57. Add Identified Community Stakers Gate Bond Curve + agent_forward([ + (contracts.cs_accounting.address, + contracts.cs_accounting.addBondCurve.encode_input(CS_ICS_GATE_BOND_CURVE)) + ]), + + # 58. Revoke MANAGE_BOND_CURVES_ROLE from the AGENT + agent_forward([ + encode_oz_revoke_role( + contract=contracts.cs_accounting, + role_name="MANAGE_BOND_CURVES_ROLE", + revoke_from=contracts.agent + ) + ]), + + # 59. Increase CSM share in Staking Router from 15% to 16% + agent_forward([ + (contracts.staking_router.address, + contracts.staking_router.updateStakingModule.encode_input( + CS_MODULE_ID, + CS_MODULE_NEW_TARGET_SHARE_BP, + CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP, + CS_MODULE_MODULE_FEE_BP, + CS_MODULE_TREASURY_FEE_BP, + CS_MODULE_MAX_DEPOSITS_PER_BLOCK, + CS_MODULE_MIN_DEPOSIT_BLOCK_DISTANCE + )) + ]), + + # Gate seals and node operator changes (steps 60-68) + # 60. Revoke PAUSE_ROLE on WithdrawalQueue from the old GateSeal + agent_forward([ + encode_oz_revoke_role( + contract=contracts.withdrawal_queue, + role_name="PAUSE_ROLE", + revoke_from=OLD_GATE_SEAL_ADDRESS + ) + ]), + + # 61. Revoke PAUSE_ROLE on ValidatorsExitBusOracle from the old GateSeal + agent_forward([ + encode_oz_revoke_role( + contract=contracts.validators_exit_bus_oracle, + role_name="PAUSE_ROLE", + revoke_from=OLD_GATE_SEAL_ADDRESS + ) + ]), + + # 62. Grant PAUSE_ROLE on WithdrawalQueue to the new WithdrawalQueue GateSeal + agent_forward([ + encode_oz_grant_role( + contract=contracts.withdrawal_queue, + role_name="PAUSE_ROLE", + grant_to=NEW_WQ_GATE_SEAL + ) + ]), + + # 63. Grant PAUSE_ROLE on ValidatorsExitBusOracle to the new Triggerable Withdrawals GateSeal + agent_forward([ + encode_oz_grant_role( + contract=contracts.validators_exit_bus_oracle, + role_name="PAUSE_ROLE", + grant_to=NEW_TW_GATE_SEAL + ) + ]), + + # 64. Grant PAUSE_ROLE on TriggerableWithdrawalsGateway to the new Triggerable Withdrawals GateSeal + agent_forward([ + encode_oz_grant_role( + contract=interface.TriggerableWithdrawalsGateway(TRIGGERABLE_WITHDRAWALS_GATEWAY), + role_name="PAUSE_ROLE", + grant_to=NEW_TW_GATE_SEAL + ) + ]), + + # 65. Grant PAUSE_ROLE on TriggerableWithdrawalsGateway to ResealManager + agent_forward([ + encode_oz_grant_role( + contract=interface.TriggerableWithdrawalsGateway(TRIGGERABLE_WITHDRAWALS_GATEWAY), + role_name="PAUSE_ROLE", + grant_to=RESEAL_MANAGER + ) + ]), + + # 66. Grant RESUME_ROLE on TriggerableWithdrawalsGateway to ResealManager + agent_forward([ + encode_oz_grant_role( + contract=interface.TriggerableWithdrawalsGateway(TRIGGERABLE_WITHDRAWALS_GATEWAY), + role_name="RESUME_ROLE", + grant_to=RESEAL_MANAGER + ) + ]), + + # Node operator changes + # 67. Rename Node Operator ID 25 from Nethermind to Twinstake + agent_forward([encode_set_node_operator_name(id=25, name="Twinstake", registry=contracts.node_operators_registry)]), + + # 68. Change Node Operator ID 17 reward address + agent_forward([encode_set_node_operator_reward_address(id=17, rewardAddress="0x36201ed66DbC284132046ee8d99272F8eEeb24c8", registry=contracts.node_operators_registry)]) + ] + + # Convert each dg_item to the expected format + proposal_calls = [] + for dg_item in dg_items: + target, data = dg_item # agent_forward returns (target, data) + proposal_calls.append({ + "target": target, + "value": 0, + "data": data + }) + + return proposal_calls + def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_governance_proposal_calls): # Save original implementations for comparison @@ -675,7 +1232,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g # --- VALIDATE EVENTS --- voting_events = group_voting_events_from_receipt(vote_tx) - dg_execution_events = group_dg_events_from_receipt(dg_tx, timelock=TIMELOCK, admin_executor=DUAL_GOVERNANCE_ADMIN_EXECUTOR) + dg_execution_events = group_dg_events_from_receipt(dg_tx, timelock=EMERGENCY_PROTECTED_TIMELOCK, admin_executor=DUAL_GOVERNANCE_ADMIN_EXECUTOR) # Validate voting events structure assert len(voting_events) == 4, "Unexpected number of voting events" From cc4149e959a6320aaf435f5d1bef14f33220db32 Mon Sep 17 00:00:00 2001 From: hweawer Date: Thu, 18 Sep 2025 14:22:55 +0200 Subject: [PATCH 22/28] Fix prevoting checks --- tests/test_vote_tw_csm2_mainnet.py | 179 ++++++++++++++--------------- 1 file changed, 89 insertions(+), 90 deletions(-) diff --git a/tests/test_vote_tw_csm2_mainnet.py b/tests/test_vote_tw_csm2_mainnet.py index 68975bb17..293fc73d3 100644 --- a/tests/test_vote_tw_csm2_mainnet.py +++ b/tests/test_vote_tw_csm2_mainnet.py @@ -41,7 +41,6 @@ CS_MODULE_MIN_DEPOSIT_BLOCK_DISTANCE, CS_MODULE_TREASURY_FEE_BP, CS_GATE_SEAL_ADDRESS, - CSM_COMMITTEE_MS, contracts, ) @@ -241,13 +240,13 @@ def check_proxy_implementation(proxy_address, expected_impl): CS_ICS_GATE_BOND_CURVE = ([1, 1.5 * 10**18], [2, 1.3 * 10**18]) # Identified Community Stakers Gate Bond Curve # CSM committee and config addresses (imported from config in actual script) -CSM_COMMITTEE_MS = "0x7a7a6e7dcF36Bc4FaAC3A5070D85b8b9E2D5e4d3" # TODO: Get actual address from config -CS_GATE_SEAL_ADDRESS = "0x7a7a6e7dcF36Bc4FaAC3A5070D85b8b9E2D5e4d3" # TODO: Get actual address from config +CSM_COMMITTEE_MS = "0xC52fC3081123073078698F1EAc2f1Dc7Bd71880f" +CS_GATE_SEAL_ADDRESS = "0x16Dbd4B85a448bE564f1742d5c8cCdD2bB3185D0" # CSM staking module constants (from config) CS_MODULE_ID = 3 CS_MODULE_MODULE_FEE_BP = 800 # 8% -CS_MODULE_TREASURY_FEE_BP = 200 # 2% +CS_MODULE_TREASURY_FEE_BP = 200 # 2% CS_MODULE_MAX_DEPOSITS_PER_BLOCK = 50 CS_MODULE_MIN_DEPOSIT_BLOCK_DISTANCE = 25 CS_EJECTOR_ADDRESS = "0xc72b58aa02E0e98cF8A4a0E9Dce75e763800802C" @@ -255,6 +254,8 @@ def check_proxy_implementation(proxy_address, expected_impl): CS_VETTED_GATE_ADDRESS = "0xB314D4A76C457c93150d308787939063F4Cc67E0" CS_VERIFIER_V2_ADDRESS = "0xdC5FE1782B6943f318E05230d688713a560063DC" +CS_VERIFIER_ADDRESS_OLD = "0xeC6Cc185f671F627fb9b6f06C8772755F587b05d" + CS_CURVES = [ ([1, 2.4 * 10**18], [2, 1.3 * 10**18]), # Default Curve ([1, 1.5 * 10**18], [2, 1.3 * 10**18]), # Legacy EA Curve @@ -273,7 +274,7 @@ def check_proxy_implementation(proxy_address, expected_impl): EXPECTED_DG_PROPOSAL_ID = 1 EXPECTED_VOTE_EVENTS_COUNT = 66 EXPECTED_DG_EVENTS_COUNT = 1 -IPFS_DESCRIPTION_HASH = "" +IPFS_DESCRIPTION_HASH = "bafkreih5app23xbevhswk56r6d2cjdqui5tckki6szo7loi7xe25bfgol4" NETHERMIND_NO_ID = 25 NETHERMIND_NO_NAME_OLD = "Nethermind" @@ -295,15 +296,15 @@ def check_proxy_implementation(proxy_address, expected_impl): @pytest.fixture(scope="module") def dual_governance_proposal_calls(): """Returns list of dual governance proposal calls for events checking""" - + # Helper function to encode proxy upgrades def encode_proxy_upgrade_to(proxy_contract, new_impl_address): return (proxy_contract.address, proxy_contract.proxy__upgradeTo.encode_input(new_impl_address)) - + # Helper function to encode oracle consensus upgrades def encode_oracle_upgrade_consensus(oracle_contract, new_version): return (oracle_contract.address, oracle_contract.setConsensusVersion.encode_input(new_version)) - + # Cast contracts to OssifiableProxy interface to access proxy methods lido_locator_proxy = interface.OssifiableProxy(contracts.lido_locator.address) vebo_proxy = interface.OssifiableProxy(contracts.validators_exit_bus_oracle.address) @@ -314,21 +315,21 @@ def encode_oracle_upgrade_consensus(oracle_contract, new_version): cs_accounting_proxy = interface.OssifiableProxy(contracts.cs_accounting.address) cs_fee_oracle_proxy = interface.OssifiableProxy(contracts.cs_fee_oracle.address) cs_fee_distributor_proxy = interface.OssifiableProxy(contracts.cs_fee_distributor.address) - + # Create all the dual governance calls that match the voting script dg_items = [ # 1. Update locator implementation agent_forward([encode_proxy_upgrade_to(lido_locator_proxy, LIDO_LOCATOR_IMPL)]), - + # 2. Update VEBO implementation agent_forward([encode_proxy_upgrade_to(vebo_proxy, VALIDATORS_EXIT_BUS_ORACLE_IMPL)]), - + # 3. Call finalizeUpgrade_v2 on VEBO agent_forward([ (contracts.validators_exit_bus_oracle.address, contracts.validators_exit_bus_oracle.finalizeUpgrade_v2.encode_input(600, 11200, 1, 48*3600)) ]), - + # 4. Grant VEBO role MANAGE_CONSENSUS_VERSION_ROLE to the AGENT agent_forward([ encode_oz_grant_role( @@ -337,10 +338,10 @@ def encode_oracle_upgrade_consensus(oracle_contract, new_version): grant_to=contracts.agent ) ]), - + # 5. Bump VEBO consensus version to 4 agent_forward([encode_oracle_upgrade_consensus(contracts.validators_exit_bus_oracle, VEBO_CONSENSUS_VERSION)]), - + # 6. Revoke VEBO role MANAGE_CONSENSUS_VERSION_ROLE from the AGENT agent_forward([ encode_oz_revoke_role( @@ -349,7 +350,7 @@ def encode_oracle_upgrade_consensus(oracle_contract, new_version): revoke_from=contracts.agent ) ]), - + # 7. Grant SUBMIT_REPORT_HASH_ROLE on VEBO to EasyTrack executor agent_forward([ encode_oz_grant_role( @@ -358,7 +359,7 @@ def encode_oracle_upgrade_consensus(oracle_contract, new_version): grant_to=EASYTRACK_EVMSCRIPT_EXECUTOR ) ]), - + # 8. Grant TWG role ADD_FULL_WITHDRAWAL_REQUEST_ROLE to CS Ejector agent_forward([ encode_oz_grant_role( @@ -367,7 +368,7 @@ def encode_oracle_upgrade_consensus(oracle_contract, new_version): grant_to=CS_EJECTOR_ADDRESS ) ]), - + # 9. Grant TWG role ADD_FULL_WITHDRAWAL_REQUEST_ROLE to VEBO agent_forward([ encode_oz_grant_role( @@ -376,24 +377,24 @@ def encode_oracle_upgrade_consensus(oracle_contract, new_version): grant_to=contracts.validators_exit_bus_oracle.address ) ]), - + # 10. Connect TWG to Dual Governance tiebreaker agent_forward([ (interface.DualGovernance(DUAL_GOVERNANCE).address, interface.DualGovernance(DUAL_GOVERNANCE).addTiebreakerSealableWithdrawalBlocker.encode_input(TRIGGERABLE_WITHDRAWALS_GATEWAY)) ]), - + # 11. Update WithdrawalVault implementation agent_forward([encode_proxy_upgrade_to(withdrawal_vault_proxy, WITHDRAWAL_VAULT_IMPL)]), - + # 12. Call finalizeUpgrade_v2() on WithdrawalVault agent_forward([ (contracts.withdrawal_vault.address, contracts.withdrawal_vault.finalizeUpgrade_v2.encode_input()) ]), - + # 13. Update Accounting Oracle implementation agent_forward([encode_proxy_upgrade_to(accounting_oracle_proxy, ACCOUNTING_ORACLE_IMPL)]), - + # 14. Grant AO MANAGE_CONSENSUS_VERSION_ROLE to the AGENT agent_forward([ encode_oz_grant_role( @@ -402,10 +403,10 @@ def encode_oracle_upgrade_consensus(oracle_contract, new_version): grant_to=contracts.agent ) ]), - + # 15. Bump AO consensus version to 4 agent_forward([encode_oracle_upgrade_consensus(contracts.accounting_oracle, AO_CONSENSUS_VERSION)]), - + # 16. Revoke AO MANAGE_CONSENSUS_VERSION_ROLE from the AGENT agent_forward([ encode_oz_revoke_role( @@ -414,20 +415,20 @@ def encode_oracle_upgrade_consensus(oracle_contract, new_version): revoke_from=contracts.agent ) ]), - + # 17. Call finalizeUpgrade_v3() on AO agent_forward([ (contracts.accounting_oracle.address, contracts.accounting_oracle.finalizeUpgrade_v3.encode_input()) ]), - + # 18. Update SR implementation agent_forward([encode_proxy_upgrade_to(staking_router_proxy, STAKING_ROUTER_IMPL)]), - + # 19. Call finalizeUpgrade_v3() on SR agent_forward([ (contracts.staking_router.address, contracts.staking_router.finalizeUpgrade_v3.encode_input()) ]), - + # 20. Grant SR role REPORT_VALIDATOR_EXITING_STATUS_ROLE to ValidatorExitVerifier agent_forward([ encode_oz_grant_role( @@ -436,7 +437,7 @@ def encode_oracle_upgrade_consensus(oracle_contract, new_version): grant_to=VALIDATOR_EXIT_VERIFIER ) ]), - + # 21. Grant SR role REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE to TWG agent_forward([ encode_oz_grant_role( @@ -445,7 +446,7 @@ def encode_oracle_upgrade_consensus(oracle_contract, new_version): grant_to=TRIGGERABLE_WITHDRAWALS_GATEWAY ) ]), - + # 22-27: Kernel and registry upgrades # 22. Grant APP_MANAGER_ROLE role to the AGENT agent_forward([ @@ -456,7 +457,7 @@ def encode_oracle_upgrade_consensus(oracle_contract, new_version): web3.keccak(text="APP_MANAGER_ROLE") )) ]), - + # 23. Update NodeOperatorsRegistry implementation agent_forward([ (contracts.kernel.address, @@ -466,13 +467,13 @@ def encode_oracle_upgrade_consensus(oracle_contract, new_version): NODE_OPERATORS_REGISTRY_IMPL )) ]), - + # 24. Call finalizeUpgrade_v4 on Curated Staking Module agent_forward([ (interface.NodeOperatorsRegistry(contracts.node_operators_registry).address, interface.NodeOperatorsRegistry(contracts.node_operators_registry).finalizeUpgrade_v4.encode_input(NOR_EXIT_DEADLINE_IN_SEC)) ]), - + # 25. Update SDVT implementation agent_forward([ (contracts.kernel.address, @@ -482,13 +483,13 @@ def encode_oracle_upgrade_consensus(oracle_contract, new_version): NODE_OPERATORS_REGISTRY_IMPL )) ]), - + # 26. Call finalizeUpgrade_v4 on SDVT agent_forward([ (interface.NodeOperatorsRegistry(contracts.simple_dvt).address, interface.NodeOperatorsRegistry(contracts.simple_dvt).finalizeUpgrade_v4.encode_input(NOR_EXIT_DEADLINE_IN_SEC)) ]), - + # 27. Revoke APP_MANAGER_ROLE role from the AGENT agent_forward([ (contracts.acl.address, @@ -498,7 +499,7 @@ def encode_oracle_upgrade_consensus(oracle_contract, new_version): web3.keccak(text="APP_MANAGER_ROLE") )) ]), - + # 28-33: Oracle daemon config changes agent_forward([ encode_oz_grant_role( @@ -507,27 +508,27 @@ def encode_oracle_upgrade_consensus(oracle_contract, new_version): grant_to=contracts.agent ) ]), - + agent_forward([ (contracts.oracle_daemon_config.address, contracts.oracle_daemon_config.unset.encode_input('NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP')) ]), - + agent_forward([ (contracts.oracle_daemon_config.address, contracts.oracle_daemon_config.unset.encode_input('VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS')) ]), - + agent_forward([ (contracts.oracle_daemon_config.address, contracts.oracle_daemon_config.unset.encode_input('VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS')) ]), - + agent_forward([ (contracts.oracle_daemon_config.address, contracts.oracle_daemon_config.set.encode_input('EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS', EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS)) ]), - + agent_forward([ encode_oz_revoke_role( contract=contracts.oracle_daemon_config, @@ -535,41 +536,41 @@ def encode_oracle_upgrade_consensus(oracle_contract, new_version): revoke_from=contracts.agent ) ]), - + # CSM upgrades and role changes (steps 34-59) # 34. Upgrade CSM implementation on proxy agent_forward([encode_proxy_upgrade_to(csm_proxy, CSM_IMPL_V2_ADDRESS)]), - - # 35. Call finalizeUpgradeV2() on CSM contract + + # 35. Call finalizeUpgradeV2() on CSM contract agent_forward([(contracts.csm.address, contracts.csm.finalizeUpgradeV2.encode_input())]), - + # 36. Upgrade CSAccounting implementation on proxy agent_forward([encode_proxy_upgrade_to(cs_accounting_proxy, CS_ACCOUNTING_IMPL_V2_ADDRESS)]), - + # 37. Call finalizeUpgradeV2(bondCurves) on CSAccounting contract agent_forward([ (contracts.cs_accounting.address, contracts.cs_accounting.finalizeUpgradeV2.encode_input(CS_CURVES)) ]), - + # 38. Upgrade CSFeeOracle implementation on proxy agent_forward([encode_proxy_upgrade_to(cs_fee_oracle_proxy, CS_FEE_ORACLE_IMPL_V2_ADDRESS)]), - + # 39. Call finalizeUpgradeV2(consensusVersion) on CSFeeOracle contract agent_forward([ (contracts.cs_fee_oracle.address, contracts.cs_fee_oracle.finalizeUpgradeV2.encode_input(CSM_CONSENSUS_VERSION)) ]), - + # 40. Upgrade CSFeeDistributor implementation on proxy agent_forward([encode_proxy_upgrade_to(cs_fee_distributor_proxy, CS_FEE_DISTRIBUTOR_IMPL_V2_ADDRESS)]), - + # 41. Call finalizeUpgradeV2(admin) on CSFeeDistributor contract agent_forward([ (contracts.cs_fee_distributor.address, contracts.cs_fee_distributor.finalizeUpgradeV2.encode_input(contracts.agent)) ]), - + # 42. Revoke CSAccounting role SET_BOND_CURVE_ROLE from the CSM contract agent_forward([ encode_oz_revoke_role( @@ -578,7 +579,7 @@ def encode_oracle_upgrade_consensus(oracle_contract, new_version): revoke_from=contracts.csm ) ]), - + # 43. Revoke CSAccounting role RESET_BOND_CURVE_ROLE from the CSM contract agent_forward([ encode_oz_revoke_role( @@ -587,7 +588,7 @@ def encode_oracle_upgrade_consensus(oracle_contract, new_version): revoke_from=contracts.csm ) ]), - + # 44. Revoke CSAccounting role RESET_BOND_CURVE_ROLE from the CSM committee agent_forward([ encode_oz_revoke_role( @@ -596,7 +597,7 @@ def encode_oracle_upgrade_consensus(oracle_contract, new_version): revoke_from=CSM_COMMITTEE_MS ) ]), - + # 45. Grant CSM role CREATE_NODE_OPERATOR_ROLE for the permissionless gate agent_forward([ encode_oz_grant_role( @@ -605,7 +606,7 @@ def encode_oracle_upgrade_consensus(oracle_contract, new_version): grant_to=CS_PERMISSIONLESS_GATE_ADDRESS ) ]), - + # 46. Grant CSM role CREATE_NODE_OPERATOR_ROLE for the vetted gate agent_forward([ encode_oz_grant_role( @@ -614,7 +615,7 @@ def encode_oracle_upgrade_consensus(oracle_contract, new_version): grant_to=CS_VETTED_GATE_ADDRESS ) ]), - + # 47. Grant CSAccounting role SET_BOND_CURVE_ROLE for the vetted gate agent_forward([ encode_oz_grant_role( @@ -623,7 +624,7 @@ def encode_oracle_upgrade_consensus(oracle_contract, new_version): grant_to=CS_VETTED_GATE_ADDRESS ) ]), - + # 48. Revoke role VERIFIER_ROLE from the previous instance of the Verifier contract agent_forward([ encode_oz_revoke_role( @@ -632,7 +633,7 @@ def encode_oracle_upgrade_consensus(oracle_contract, new_version): revoke_from=contracts.cs_verifier ) ]), - + # 49. Grant role VERIFIER_ROLE to the new instance of the Verifier contract agent_forward([ encode_oz_grant_role( @@ -641,7 +642,7 @@ def encode_oracle_upgrade_consensus(oracle_contract, new_version): grant_to=CS_VERIFIER_V2_ADDRESS ) ]), - + # 50. Revoke CSM role PAUSE_ROLE from the previous GateSeal instance agent_forward([ encode_oz_revoke_role( @@ -650,7 +651,7 @@ def encode_oracle_upgrade_consensus(oracle_contract, new_version): revoke_from=CS_GATE_SEAL_ADDRESS ) ]), - + # 51. Revoke CSAccounting role PAUSE_ROLE from the previous GateSeal instance agent_forward([ encode_oz_revoke_role( @@ -659,7 +660,7 @@ def encode_oracle_upgrade_consensus(oracle_contract, new_version): revoke_from=CS_GATE_SEAL_ADDRESS ) ]), - + # 52. Revoke CSFeeOracle role PAUSE_ROLE from the previous GateSeal instance agent_forward([ encode_oz_revoke_role( @@ -668,7 +669,7 @@ def encode_oracle_upgrade_consensus(oracle_contract, new_version): revoke_from=CS_GATE_SEAL_ADDRESS ) ]), - + # 53. Grant CSM role PAUSE_ROLE for the new GateSeal instance agent_forward([ encode_oz_grant_role( @@ -677,7 +678,7 @@ def encode_oracle_upgrade_consensus(oracle_contract, new_version): grant_to=CS_GATE_SEAL_V2_ADDRESS ) ]), - + # 54. Grant CSAccounting role PAUSE_ROLE for the new GateSeal instance agent_forward([ encode_oz_grant_role( @@ -686,7 +687,7 @@ def encode_oracle_upgrade_consensus(oracle_contract, new_version): grant_to=CS_GATE_SEAL_V2_ADDRESS ) ]), - + # 55. Grant CSFeeOracle role PAUSE_ROLE for the new GateSeal instance agent_forward([ encode_oz_grant_role( @@ -695,7 +696,7 @@ def encode_oracle_upgrade_consensus(oracle_contract, new_version): grant_to=CS_GATE_SEAL_V2_ADDRESS ) ]), - + # 56. Grant MANAGE_BOND_CURVES_ROLE to the AGENT agent_forward([ encode_oz_grant_role( @@ -704,13 +705,13 @@ def encode_oracle_upgrade_consensus(oracle_contract, new_version): grant_to=contracts.agent ) ]), - + # 57. Add Identified Community Stakers Gate Bond Curve agent_forward([ (contracts.cs_accounting.address, contracts.cs_accounting.addBondCurve.encode_input(CS_ICS_GATE_BOND_CURVE)) ]), - + # 58. Revoke MANAGE_BOND_CURVES_ROLE from the AGENT agent_forward([ encode_oz_revoke_role( @@ -719,7 +720,7 @@ def encode_oracle_upgrade_consensus(oracle_contract, new_version): revoke_from=contracts.agent ) ]), - + # 59. Increase CSM share in Staking Router from 15% to 16% agent_forward([ (contracts.staking_router.address, @@ -733,7 +734,7 @@ def encode_oracle_upgrade_consensus(oracle_contract, new_version): CS_MODULE_MIN_DEPOSIT_BLOCK_DISTANCE )) ]), - + # Gate seals and node operator changes (steps 60-68) # 60. Revoke PAUSE_ROLE on WithdrawalQueue from the old GateSeal agent_forward([ @@ -743,7 +744,7 @@ def encode_oracle_upgrade_consensus(oracle_contract, new_version): revoke_from=OLD_GATE_SEAL_ADDRESS ) ]), - + # 61. Revoke PAUSE_ROLE on ValidatorsExitBusOracle from the old GateSeal agent_forward([ encode_oz_revoke_role( @@ -752,7 +753,7 @@ def encode_oracle_upgrade_consensus(oracle_contract, new_version): revoke_from=OLD_GATE_SEAL_ADDRESS ) ]), - + # 62. Grant PAUSE_ROLE on WithdrawalQueue to the new WithdrawalQueue GateSeal agent_forward([ encode_oz_grant_role( @@ -761,7 +762,7 @@ def encode_oracle_upgrade_consensus(oracle_contract, new_version): grant_to=NEW_WQ_GATE_SEAL ) ]), - + # 63. Grant PAUSE_ROLE on ValidatorsExitBusOracle to the new Triggerable Withdrawals GateSeal agent_forward([ encode_oz_grant_role( @@ -770,7 +771,7 @@ def encode_oracle_upgrade_consensus(oracle_contract, new_version): grant_to=NEW_TW_GATE_SEAL ) ]), - + # 64. Grant PAUSE_ROLE on TriggerableWithdrawalsGateway to the new Triggerable Withdrawals GateSeal agent_forward([ encode_oz_grant_role( @@ -779,7 +780,7 @@ def encode_oracle_upgrade_consensus(oracle_contract, new_version): grant_to=NEW_TW_GATE_SEAL ) ]), - + # 65. Grant PAUSE_ROLE on TriggerableWithdrawalsGateway to ResealManager agent_forward([ encode_oz_grant_role( @@ -788,7 +789,7 @@ def encode_oracle_upgrade_consensus(oracle_contract, new_version): grant_to=RESEAL_MANAGER ) ]), - + # 66. Grant RESUME_ROLE on TriggerableWithdrawalsGateway to ResealManager agent_forward([ encode_oz_grant_role( @@ -797,15 +798,15 @@ def encode_oracle_upgrade_consensus(oracle_contract, new_version): grant_to=RESEAL_MANAGER ) ]), - + # Node operator changes # 67. Rename Node Operator ID 25 from Nethermind to Twinstake agent_forward([encode_set_node_operator_name(id=25, name="Twinstake", registry=contracts.node_operators_registry)]), - - # 68. Change Node Operator ID 17 reward address + + # 68. Change Node Operator ID 17 reward address agent_forward([encode_set_node_operator_reward_address(id=17, rewardAddress="0x36201ed66DbC284132046ee8d99272F8eEeb24c8", registry=contracts.node_operators_registry)]) ] - + # Convert each dg_item to the expected format proposal_calls = [] for dg_item in dg_items: @@ -815,7 +816,7 @@ def encode_oracle_upgrade_consensus(oracle_contract, new_version): "value": 0, "data": data }) - + return proposal_calls @@ -845,7 +846,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g no_registry = interface.NodeOperatorsRegistry(NODE_OPERATORS_REGISTRY_ADDRESS) - + # START VOTE if vote_ids_from_env: vote_id = vote_ids_from_env[0] @@ -855,7 +856,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g vote_id = EXPECTED_VOTE_ID else: vote_id, _ = start_vote({"from": ldo_holder}, silent=True) - + _, call_script_items = get_vote_items() onchain_script = voting.getVote(vote_id)["script"] assert onchain_script == encode_call_script(call_script_items) @@ -1008,7 +1009,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g assert not contracts.cs_accounting.hasRole(contracts.cs_accounting.SET_BOND_CURVE_ROLE(), cs_vetted_gate.address), "Vetted gate should not have SET_BOND_CURVE_ROLE on CSAccounting before vote" # CSM Steps 44-45: Verifier roles (pre-vote state) - assert contracts.csm.hasRole(contracts.csm.VERIFIER_ROLE(), contracts.cs_verifier.address), "Old verifier should have VERIFIER_ROLE on CSM before vote" + assert contracts.csm.hasRole(contracts.csm.VERIFIER_ROLE(), CS_VERIFIER_ADDRESS_OLD), "Old verifier should have VERIFIER_ROLE on CSM before vote" assert not contracts.csm.hasRole(contracts.csm.VERIFIER_ROLE(), cs_verifier_v2.address), "New verifier should not have VERIFIER_ROLE on CSM before vote" # CSM Steps 46-51: GateSeal roles (pre-vote state) @@ -1043,19 +1044,17 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g # ResealManager: Check initial states before vote assert not triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.PAUSE_ROLE(), RESEAL_MANAGER), "ResealManager should not have PAUSE_ROLE on TWG before vote" assert not triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.RESUME_ROLE(), RESEAL_MANAGER), "ResealManager should not have RESUME_ROLE on TWG before vote" - - assert get_lido_vote_cid_from_str(find_metadata_by_vote_id(vote_id)) == IPFS_DESCRIPTION_HASH - - vote_tx: TransactionReceipt = helpers.execute_vote(vote_id=vote_id, accounts=accounts, dao_voting=voting) - display_voting_events(vote_tx) - vote_events = group_voting_events_from_receipt(vote_tx) - # Rename Nethermind NO nethermind_no_data_before = no_registry.getNodeOperator(NETHERMIND_NO_ID, True) assert nethermind_no_data_before["rewardAddress"] == NETHERMIND_NO_STAKING_REWARDS_ADDRESS_OLD assert nethermind_no_data_before["name"] == NETHERMIND_NO_NAME_OLD + assert get_lido_vote_cid_from_str(find_metadata_by_vote_id(vote_id)) == IPFS_DESCRIPTION_HASH + + vote_tx: TransactionReceipt = helpers.execute_vote(vote_id=vote_id, accounts=accounts, dao_voting=voting) + display_voting_events(vote_tx) + vote_events = group_voting_events_from_receipt(vote_tx) # ======================================================================= # ========================= After voting checks ========================= From ba439c8922d9518e5c2e826601607a7075191518 Mon Sep 17 00:00:00 2001 From: hweawer Date: Thu, 18 Sep 2025 16:31:43 +0200 Subject: [PATCH 23/28] Fix: voting changes verification, dg event submition --- .yarn/install-state.gz | Bin 0 -> 334018 bytes .yarnrc.yml | 1 + package.json | 2 +- tests/test_vote_tw_csm2_mainnet.py | 539 +- .../test/event_validators/dual_governance.py | 8 +- yarn.lock | 6603 ++++++++++------- 6 files changed, 4416 insertions(+), 2737 deletions(-) create mode 100644 .yarn/install-state.gz create mode 100644 .yarnrc.yml diff --git a/.yarn/install-state.gz b/.yarn/install-state.gz new file mode 100644 index 0000000000000000000000000000000000000000..8d9d80bcdb330e08a6ce82300f0eeef5cc0dd4f6 GIT binary patch literal 334018 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�Ft~Ik@qxQz8!&=~m;M=H5w31mFI0u9fB6 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

@Z|P$at+H4~M#I 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 2.1.2 < 3" - -ieee754@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" - integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== - -immutable@^4.0.0-rc.12: - version "4.3.7" - resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.7.tgz#c70145fc90d89fb02021e65c84eb0226e4e5a381" - integrity sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw== - -indent-string@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" - integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@2.0.4, inherits@^2.0.3, inherits@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -io-ts@1.10.4: - version "1.10.4" - resolved "https://registry.yarnpkg.com/io-ts/-/io-ts-1.10.4.tgz#cd5401b138de88e4f920adbcb7026e2d1967e6e2" - integrity sha512-b23PteSnYXSONJ6JQXRAlvJhuw8KOtkqa87W4wDtvMrud/DTJd5X+NpOOI+O/zZwVq6v0VLAaJ+1EDViKEuN9g== - dependencies: - fp-ts "^1.0.0" - -is-arguments@^1.0.4: - version "1.2.0" - resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.2.0.tgz#ad58c6aecf563b78ef2bf04df540da8f5d7d8e1b" - integrity sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA== - dependencies: - call-bound "^1.0.2" - has-tostringtag "^1.0.2" - -is-binary-path@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" - integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== - dependencies: - binary-extensions "^2.0.0" - -is-buffer@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" - integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== - -is-callable@^1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" - integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== - -is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== - -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - -is-generator-function@^1.0.7: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.1.0.tgz#bf3eeda931201394f57b5dba2800f91a238309ca" - integrity sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ== - dependencies: - call-bound "^1.0.3" - get-proto "^1.0.0" - has-tostringtag "^1.0.2" - safe-regex-test "^1.1.0" - -is-glob@^4.0.1, is-glob@~4.0.1: - version "4.0.3" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" - integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== - dependencies: - is-extglob "^2.1.1" - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-plain-obj@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" - integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== - -is-regex@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.2.1.tgz#76d70a3ed10ef9be48eb577887d74205bf0cad22" - integrity sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g== - dependencies: - call-bound "^1.0.2" - gopd "^1.2.0" - has-tostringtag "^1.0.2" - hasown "^2.0.2" - -is-typed-array@^1.1.3: - version "1.1.15" - resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.15.tgz#4bfb4a45b61cee83a5a46fba778e4e8d59c0ce0b" - integrity sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ== - dependencies: - which-typed-array "^1.1.16" - -is-unicode-supported@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" - integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== - -isomorphic-ws@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz#e5529148912ecb9b451b46ed44d53dae1ce04bbf" - integrity sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw== - -js-sha3@0.8.0: - version "0.8.0" - resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" - integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== - -js-yaml@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" - integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== - dependencies: - argparse "^2.0.1" - -json-stream-stringify@^3.1.4: - version "3.1.6" - resolved "https://registry.yarnpkg.com/json-stream-stringify/-/json-stream-stringify-3.1.6.tgz#ebe32193876fb99d4ec9f612389a8d8e2b5d54d4" - integrity sha512-x7fpwxOkbhFCaJDJ8vb1fBY3DdSa4AlITaz+HHILQJzdPMnHEFjxPwVUi1ALIbcIxDE0PNe/0i7frnY8QnBQog== - -jsonfile@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" - integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg== - optionalDependencies: - graceful-fs "^4.1.6" - -keccak@3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.2.tgz#4c2c6e8c54e04f2670ee49fa734eb9da152206e0" - integrity sha512-PyKKjkH53wDMLGrvmRGSNWgmSxZOUqbnXwKL9tmgbFYA1iAYqW21kfR7mZXV0MlESiefxQQE9X9fTa3X+2MPDQ== - dependencies: - node-addon-api "^2.0.0" - node-gyp-build "^4.2.0" - readable-stream "^3.6.0" - -keccak@^3.0.2: - version "3.0.4" - resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.4.tgz#edc09b89e633c0549da444432ecf062ffadee86d" - integrity sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q== - dependencies: - node-addon-api "^2.0.0" - node-gyp-build "^4.2.0" - readable-stream "^3.6.0" - -level-concat-iterator@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/level-concat-iterator/-/level-concat-iterator-3.1.0.tgz#5235b1f744bc34847ed65a50548aa88d22e881cf" - integrity sha512-BWRCMHBxbIqPxJ8vHOvKUsaO0v1sLYZtjN3K2iZJsRBYtp+ONsY6Jfi6hy9K3+zolgQRryhIn2NRZjZnWJ9NmQ== - dependencies: - catering "^2.1.0" - -level-supports@^2.0.1: - version "2.1.0" - resolved "https://registry.yarnpkg.com/level-supports/-/level-supports-2.1.0.tgz#9af908d853597ecd592293b2fad124375be79c5f" - integrity sha512-E486g1NCjW5cF78KGPrMDRBYzPuueMZ6VBXHT6gC7A8UYWGiM14fGgp+s/L1oFfDWSPV/+SFkYCmZ0SiESkRKA== - -level-supports@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/level-supports/-/level-supports-4.0.1.tgz#431546f9d81f10ff0fea0e74533a0e875c08c66a" - integrity sha512-PbXpve8rKeNcZ9C1mUicC9auIYFyGpkV9/i6g76tLgANwWhtG2v7I4xNBUlkn3lE2/dZF3Pi0ygYGtLc4RXXdA== - -level-transcoder@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/level-transcoder/-/level-transcoder-1.0.1.tgz#f8cef5990c4f1283d4c86d949e73631b0bc8ba9c" - integrity sha512-t7bFwFtsQeD8cl8NIoQ2iwxA0CL/9IFw7/9gAjOonH0PWTTiRfY7Hq+Ejbsxh86tXobDQ6IOiddjNYIfOBs06w== - dependencies: - buffer "^6.0.3" - module-error "^1.0.1" - -leveldown@6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/leveldown/-/leveldown-6.1.0.tgz#7ab1297706f70c657d1a72b31b40323aa612b9ee" - integrity sha512-8C7oJDT44JXxh04aSSsfcMI8YiaGRhOFI9/pMEL7nWJLVsWajDPTRxsSHTM2WcTVY5nXM+SuRHzPPi0GbnDX+w== - dependencies: - abstract-leveldown "^7.2.0" - napi-macros "~2.0.0" - node-gyp-build "^4.3.0" - -locate-path@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" - integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== - dependencies: - p-locate "^5.0.0" - -lodash@^4.17.11, lodash@^4.17.14: - version "4.17.21" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== - -log-symbols@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" - integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== - dependencies: - chalk "^4.1.0" - is-unicode-supported "^0.1.0" - -lru_map@^0.3.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd" - integrity sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ== - -math-intrinsics@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9" - integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g== - -memorystream@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" - integrity sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw== - -micro-eth-signer@^0.14.0: - version "0.14.0" - resolved "https://registry.yarnpkg.com/micro-eth-signer/-/micro-eth-signer-0.14.0.tgz#8aa1fe997d98d6bdf42f2071cef7eb01a66ecb22" - integrity sha512-5PLLzHiVYPWClEvZIXXFu5yutzpadb73rnQCpUqIHu3No3coFuWQNfE5tkBQJ7djuLYl6aRLaS0MgWJYGoqiBw== - dependencies: - "@noble/curves" "~1.8.1" - "@noble/hashes" "~1.7.1" - micro-packed "~0.7.2" - -micro-packed@~0.7.2: - version "0.7.3" - resolved "https://registry.yarnpkg.com/micro-packed/-/micro-packed-0.7.3.tgz#59e96b139dffeda22705c7a041476f24cabb12b6" - integrity sha512-2Milxs+WNC00TRlem41oRswvw31146GiSaoCT7s3Xi2gMUglW5QBeqlQaZeHr5tJx9nm3i57LNXPqxOOaWtTYg== - dependencies: - "@scure/base" "~1.2.5" - -minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" - integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== - -minimalistic-crypto-utils@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" - integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== - -minimatch@^5.0.1, minimatch@^5.1.6: - version "5.1.6" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" - integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== - dependencies: - brace-expansion "^2.0.1" - -mnemonist@^0.38.0: - version "0.38.5" - resolved "https://registry.yarnpkg.com/mnemonist/-/mnemonist-0.38.5.tgz#4adc7f4200491237fe0fa689ac0b86539685cade" - integrity sha512-bZTFT5rrPKtPJxj8KSV0WkPyNxl72vQepqqVUAW2ARUpUSF2qXMB6jZj7hW5/k7C1rtpzqbD/IIbJwLXUjCHeg== - dependencies: - obliterator "^2.0.0" - -mocha@^10.0.0: - version "10.8.2" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.8.2.tgz#8d8342d016ed411b12a429eb731b825f961afb96" - integrity sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg== - dependencies: - ansi-colors "^4.1.3" - browser-stdout "^1.3.1" - chokidar "^3.5.3" - debug "^4.3.5" - diff "^5.2.0" - escape-string-regexp "^4.0.0" - find-up "^5.0.0" - glob "^8.1.0" - he "^1.2.0" - js-yaml "^4.1.0" - log-symbols "^4.1.0" - minimatch "^5.1.6" - ms "^2.1.3" - serialize-javascript "^6.0.2" - strip-json-comments "^3.1.1" - supports-color "^8.1.1" - workerpool "^6.5.1" - yargs "^16.2.0" - yargs-parser "^20.2.9" - yargs-unparser "^2.0.0" - -module-error@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/module-error/-/module-error-1.0.2.tgz#8d1a48897ca883f47a45816d4fb3e3c6ba404d86" - integrity sha512-0yuvsqSCv8LbaOKhnsQ/T5JhyFlCYLPXK3U2sgV10zoKQwzs/MyfuQUOZQ1V/6OCOJsK/TRgNVrPuPDqtdMFtA== - -ms@^2.1.3: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== - -napi-macros@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/napi-macros/-/napi-macros-2.0.0.tgz#2b6bae421e7b96eb687aa6c77a7858640670001b" - integrity sha512-A0xLykHtARfueITVDernsAWdtIMbOJgKgcluwENp3AlsKN/PloyO10HtmoqnFAQAcxPkgZN7wdfPfEd0zNGxbg== - -node-addon-api@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" - integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA== - -node-fetch@^2.7.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" - integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== - dependencies: - whatwg-url "^5.0.0" - -node-gyp-build@4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.4.0.tgz#42e99687ce87ddeaf3a10b99dc06abc11021f3f4" - integrity sha512-amJnQCcgtRVw9SvoebO3BKGESClrfXGCUTX9hSn1OuGQTQBOZmVd0Z0OlecpuRksKvbsUqALE8jls/ErClAPuQ== - -node-gyp-build@^4.2.0, node-gyp-build@^4.3.0: - version "4.8.0" - resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.8.0.tgz#3fee9c1731df4581a3f9ead74664369ff00d26dd" - integrity sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og== - -normalize-path@^3.0.0, normalize-path@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -obliterator@^2.0.0: - version "2.0.5" - resolved "https://registry.yarnpkg.com/obliterator/-/obliterator-2.0.5.tgz#031e0145354b0c18840336ae51d41e7d6d2c76aa" - integrity sha512-42CPE9AhahZRsMNslczq0ctAEtqk8Eka26QofnqC346BZdHDySk3LWka23LI7ULIw11NmltpiLagIq8gBozxTw== - -once@^1.3.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== - dependencies: - wrappy "1" - -os-tmpdir@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== - -p-limit@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" - integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== - dependencies: - yocto-queue "^0.1.0" - -p-locate@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" - integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== - dependencies: - p-limit "^3.0.2" - -p-map@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" - integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== - dependencies: - aggregate-error "^3.0.0" - -path-exists@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== - -path-parse@^1.0.6: - version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" - integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== - -picocolors@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" - integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== - -picomatch@^2.0.4, picomatch@^2.2.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== - -picomatch@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.2.tgz#77c742931e8f3b8820946c76cd0c1f13730d1dab" - integrity sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg== - -possible-typed-array-names@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz#93e3582bc0e5426586d9d07b79ee40fc841de4ae" - integrity sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg== - -queue-microtask@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" - integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== - -randombytes@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" - integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== - dependencies: - safe-buffer "^5.1.0" - -raw-body@^2.4.1: - version "2.5.2" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" - integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA== - dependencies: - bytes "3.1.2" - http-errors "2.0.0" - iconv-lite "0.4.24" - unpipe "1.0.0" - -readable-stream@^3.6.0: - version "3.6.2" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" - integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -readdirp@^4.0.1: - version "4.1.2" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-4.1.2.tgz#eb85801435fbf2a7ee58f19e0921b068fc69948d" - integrity sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg== - -readdirp@~3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" - integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== - dependencies: - picomatch "^2.2.1" - -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== - -resolve-pkg-maps@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" - integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== - -resolve@1.17.0: - version "1.17.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" - integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== - dependencies: - path-parse "^1.0.6" - -safe-buffer@^5.1.0, safe-buffer@~5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -safe-regex-test@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.1.0.tgz#7f87dfb67a3150782eaaf18583ff5d1711ac10c1" - integrity sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw== - dependencies: - call-bound "^1.0.2" - es-errors "^1.3.0" - is-regex "^1.2.1" - -"safer-buffer@>= 2.1.2 < 3": - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - -secp256k1@4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-4.0.3.tgz#c4559ecd1b8d3c1827ed2d1b94190d69ce267303" - integrity sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA== - dependencies: - elliptic "^6.5.4" - node-addon-api "^2.0.0" - node-gyp-build "^4.2.0" - -semver@^5.5.0: - version "5.7.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" - integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== - -semver@^6.3.0: - version "6.3.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" - integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== - -serialize-javascript@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" - integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g== - dependencies: - randombytes "^2.1.0" - -set-function-length@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" - integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== - dependencies: - define-data-property "^1.1.4" - es-errors "^1.3.0" - function-bind "^1.1.2" - get-intrinsic "^1.2.4" - gopd "^1.0.1" - has-property-descriptors "^1.0.2" - -setimmediate@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" - integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== - -setprototypeof@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" - integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== - -solc@0.8.26: - version "0.8.26" - resolved "https://registry.yarnpkg.com/solc/-/solc-0.8.26.tgz#afc78078953f6ab3e727c338a2fefcd80dd5b01a" - integrity sha512-yiPQNVf5rBFHwN6SIf3TUUvVAFKcQqmSUFeq+fb6pNRCo0ZCgpYOZDi3BVoezCPIAcKrVYd/qXlBLUP9wVrZ9g== - dependencies: - command-exists "^1.2.8" - commander "^8.1.0" - follow-redirects "^1.12.1" - js-sha3 "0.8.0" - memorystream "^0.3.1" - semver "^5.5.0" - tmp "0.0.33" - -source-map-support@^0.5.13: - version "0.5.21" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" - integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map@^0.6.0: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -stacktrace-parser@^0.1.10: - version "0.1.11" - resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.11.tgz#c7c08f9b29ef566b9a6f7b255d7db572f66fabc4" - integrity sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg== - dependencies: - type-fest "^0.7.1" - -statuses@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" - integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== - -string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string_decoder@^1.1.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-json-comments@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" - integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== - -supports-color@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== - dependencies: - has-flag "^4.0.0" - -supports-color@^8.1.1: - version "8.1.1" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" - integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== - dependencies: - has-flag "^4.0.0" - -tinyglobby@^0.2.6: - version "0.2.12" - resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.12.tgz#ac941a42e0c5773bd0b5d08f32de82e74a1a61b5" - integrity sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww== - dependencies: - fdir "^6.4.3" - picomatch "^4.0.2" - -tmp@0.0.33: - version "0.0.33" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" - integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== - dependencies: - os-tmpdir "~1.0.2" - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -toidentifier@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" - integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== - -tr46@~0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" - integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== - -tslib@^1.9.3: - version "1.14.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" - integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== - -tsort@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/tsort/-/tsort-0.0.1.tgz#e2280f5e817f8bf4275657fd0f9aebd44f5a2786" - integrity sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw== - -tsx@^4.19.4: - version "4.19.4" - resolved "https://registry.yarnpkg.com/tsx/-/tsx-4.19.4.tgz#647b4141f4fdd9d773a9b564876773d2846901f4" - integrity sha512-gK5GVzDkJK1SI1zwHf32Mqxf2tSJkNx+eYcNly5+nHvWqXUJYUkWBQtKauoESz3ymezAI++ZwT855x5p5eop+Q== - dependencies: - esbuild "~0.25.0" - get-tsconfig "^4.7.5" - optionalDependencies: - fsevents "~2.3.3" - -type-fest@^0.20.2: - version "0.20.2" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" - integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== - -type-fest@^0.21.3: - version "0.21.3" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" - integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== - -type-fest@^0.7.1: - version "0.7.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.7.1.tgz#8dda65feaf03ed78f0a3f9678f1869147f7c5c48" - integrity sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg== - -undici-types@~5.26.4: - version "5.26.5" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" - integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== - -undici@^5.14.0: - version "5.28.5" - resolved "https://registry.yarnpkg.com/undici/-/undici-5.28.5.tgz#b2b94b6bf8f1d919bc5a6f31f2c01deb02e54d4b" - integrity sha512-zICwjrDrcrUE0pyyJc1I2QzBkLM8FINsgOrt6WjA+BgajVq9Nxu2PbFFXUrAggLfDXlZGZBVZYw7WNV5KiBiBA== - dependencies: - "@fastify/busboy" "^2.0.0" - -universalify@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" - integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== - -unpipe@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== - -utf-8-validate@5.0.7: - version "5.0.7" - resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.7.tgz#c15a19a6af1f7ad9ec7ddc425747ca28c3644922" - integrity sha512-vLt1O5Pp+flcArHGIyKEQq883nBt8nN8tVBcoL0qUXj2XT1n7p70yGIq2VK98I5FdZ1YHc0wk/koOnHjnXWk1Q== - dependencies: - node-gyp-build "^4.3.0" - -utf-8-validate@6.0.3: - version "6.0.3" - resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-6.0.3.tgz#7d8c936d854e86b24d1d655f138ee27d2636d777" - integrity sha512-uIuGf9TWQ/y+0Lp+KGZCMuJWc3N9BHA+l/UmHd/oUHwJJDeysyTRxNQVkbzsIWfGFbRe3OcgML/i0mvVRPOyDA== - dependencies: - node-gyp-build "^4.3.0" - -util-deprecate@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== - -util@^0.12.5: - version "0.12.5" - resolved "https://registry.yarnpkg.com/util/-/util-0.12.5.tgz#5f17a6059b73db61a875668781a1c2b136bd6fbc" - integrity sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA== - dependencies: - inherits "^2.0.3" - is-arguments "^1.0.4" - is-generator-function "^1.0.7" - is-typed-array "^1.1.3" - which-typed-array "^1.1.2" - -uuid@^8.3.2: - version "8.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" - integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== - -web3-core@^4.4.0, web3-core@^4.5.0, web3-core@^4.6.0, web3-core@^4.7.1: - version "4.7.1" - resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-4.7.1.tgz#bc56cd7959fe44ee77139d591211f69851140009" - integrity sha512-9KSeASCb/y6BG7rwhgtYC4CvYY66JfkmGNEYb7q1xgjt9BWfkf09MJPaRyoyT5trdOxYDHkT9tDlypvQWaU8UQ== - dependencies: - web3-errors "^1.3.1" - web3-eth-accounts "^4.3.1" - web3-eth-iban "^4.0.7" - web3-providers-http "^4.2.0" - web3-providers-ws "^4.0.8" - web3-types "^1.10.0" - web3-utils "^4.3.3" - web3-validator "^2.0.6" - optionalDependencies: - web3-providers-ipc "^4.0.7" - -web3-errors@^1.1.3, web3-errors@^1.2.0, web3-errors@^1.3.0, web3-errors@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/web3-errors/-/web3-errors-1.3.1.tgz#163bc4d869f98614760b683d733c3ed1fb415d98" - integrity sha512-w3NMJujH+ZSW4ltIZZKtdbkbyQEvBzyp3JRn59Ckli0Nz4VMsVq8aF1bLWM7A2kuQ+yVEm3ySeNU+7mSRwx7RQ== - dependencies: - web3-types "^1.10.0" - -web3-eth-abi@^4.4.1: - version "4.4.1" - resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-4.4.1.tgz#1dca9d80341b3cd7a1ae07dc98080c2073d62a29" - integrity sha512-60ecEkF6kQ9zAfbTY04Nc9q4eEYM0++BySpGi8wZ2PD1tw/c0SDvsKhV6IKURxLJhsDlb08dATc3iD6IbtWJmg== - dependencies: - abitype "0.7.1" - web3-errors "^1.3.1" - web3-types "^1.10.0" - web3-utils "^4.3.3" - web3-validator "^2.0.6" - -web3-eth-accounts@^4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-4.3.1.tgz#6712ea915940d03d596015a87f9167171e8306a6" - integrity sha512-rTXf+H9OKze6lxi7WMMOF1/2cZvJb2AOnbNQxPhBDssKOllAMzLhg1FbZ4Mf3lWecWfN6luWgRhaeSqO1l+IBQ== - dependencies: - "@ethereumjs/rlp" "^4.0.1" - crc-32 "^1.2.2" - ethereum-cryptography "^2.0.0" - web3-errors "^1.3.1" - web3-types "^1.10.0" - web3-utils "^4.3.3" - web3-validator "^2.0.6" - -web3-eth-contract@^4.5.0, web3-eth-contract@^4.7.2: - version "4.7.2" - resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-4.7.2.tgz#a1851e566ceb4b0da3792ff4d8f7cb6fd91d3401" - integrity sha512-3ETqs2pMNPEAc7BVY/C3voOhTUeJdkf2aM3X1v+edbngJLHAxbvxKpOqrcO0cjXzC4uc2Q8Zpf8n8zT5r0eLnA== - dependencies: - "@ethereumjs/rlp" "^5.0.2" - web3-core "^4.7.1" - web3-errors "^1.3.1" - web3-eth "^4.11.1" - web3-eth-abi "^4.4.1" - web3-types "^1.10.0" - web3-utils "^4.3.3" - web3-validator "^2.0.6" - -web3-eth-ens@^4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-4.4.0.tgz#bc0d11d755cb15ed4b82e38747c5104622d9a4b9" - integrity sha512-DeyVIS060hNV9g8dnTx92syqvgbvPricE3MerCxe/DquNZT3tD8aVgFfq65GATtpCgDDJffO2bVeHp3XBemnSQ== - dependencies: - "@adraffy/ens-normalize" "^1.8.8" - web3-core "^4.5.0" - web3-errors "^1.2.0" - web3-eth "^4.8.0" - web3-eth-contract "^4.5.0" - web3-net "^4.1.0" - web3-types "^1.7.0" - web3-utils "^4.3.0" - web3-validator "^2.0.6" - -web3-eth-iban@^4.0.7: - version "4.0.7" - resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-4.0.7.tgz#ee504f845d7b6315f0be78fcf070ccd5d38e4aaf" - integrity sha512-8weKLa9KuKRzibC87vNLdkinpUE30gn0IGY027F8doeJdcPUfsa4IlBgNC4k4HLBembBB2CTU0Kr/HAOqMeYVQ== - dependencies: - web3-errors "^1.1.3" - web3-types "^1.3.0" - web3-utils "^4.0.7" - web3-validator "^2.0.3" - -web3-eth-personal@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-4.1.0.tgz#f5b506a4570bf1241d1db2de12cb413ea0bb4486" - integrity sha512-RFN83uMuvA5cu1zIwwJh9A/bAj0OBxmGN3tgx19OD/9ygeUZbifOL06jgFzN0t+1ekHqm3DXYQM8UfHpXi7yDQ== - dependencies: - web3-core "^4.6.0" - web3-eth "^4.9.0" - web3-rpc-methods "^1.3.0" - web3-types "^1.8.0" - web3-utils "^4.3.1" - web3-validator "^2.0.6" - -web3-eth@^4.11.1, web3-eth@^4.8.0, web3-eth@^4.9.0: - version "4.11.1" - resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-4.11.1.tgz#f558ab1482d4196de0f0a7da5985de42d06664ea" - integrity sha512-q9zOkzHnbLv44mwgLjLXuyqszHuUgZWsQayD2i/rus2uk0G7hMn11bE2Q3hOVnJS4ws4VCtUznlMxwKQ+38V2w== - dependencies: - setimmediate "^1.0.5" - web3-core "^4.7.1" - web3-errors "^1.3.1" - web3-eth-abi "^4.4.1" - web3-eth-accounts "^4.3.1" - web3-net "^4.1.0" - web3-providers-ws "^4.0.8" - web3-rpc-methods "^1.3.0" - web3-types "^1.10.0" - web3-utils "^4.3.3" - web3-validator "^2.0.6" - -web3-net@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-4.1.0.tgz#db7bde675e58b153339e4f149f29ec0410d6bab2" - integrity sha512-WWmfvHVIXWEoBDWdgKNYKN8rAy6SgluZ0abyRyXOL3ESr7ym7pKWbfP4fjApIHlYTh8tNqkrdPfM4Dyi6CA0SA== - dependencies: - web3-core "^4.4.0" - web3-rpc-methods "^1.3.0" - web3-types "^1.6.0" - web3-utils "^4.3.0" - -web3-providers-http@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-4.2.0.tgz#0f4bf424681a068d49994aa7fabc69bed45ac50b" - integrity sha512-IPMnDtHB7dVwaB7/mMxAZzyq7d5ezfO1+Vw0bNfAeIi7gaDlJiggp85SdyAfOgov8AMUA/dyiY72kQ0KmjXKvQ== - dependencies: - cross-fetch "^4.0.0" - web3-errors "^1.3.0" - web3-types "^1.7.0" - web3-utils "^4.3.1" - -web3-providers-ipc@^4.0.7: - version "4.0.7" - resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-4.0.7.tgz#9ec4c8565053af005a5170ba80cddeb40ff3e3d3" - integrity sha512-YbNqY4zUvIaK2MHr1lQFE53/8t/ejHtJchrWn9zVbFMGXlTsOAbNoIoZWROrg1v+hCBvT2c9z8xt7e/+uz5p1g== - dependencies: - web3-errors "^1.1.3" - web3-types "^1.3.0" - web3-utils "^4.0.7" - -web3-providers-ws@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-4.0.8.tgz#6de7b262f7ec6df1a2dff466ba91d7ebdac2c45e" - integrity sha512-goJdgata7v4pyzHRsg9fSegUG4gVnHZSHODhNnn6J93ykHkBI1nz4fjlGpcQLUMi4jAMz6SHl9Ibzs2jj9xqPw== - dependencies: - "@types/ws" "8.5.3" - isomorphic-ws "^5.0.0" - web3-errors "^1.2.0" - web3-types "^1.7.0" - web3-utils "^4.3.1" - ws "^8.17.1" - -web3-rpc-methods@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/web3-rpc-methods/-/web3-rpc-methods-1.3.0.tgz#d5ee299a69389d63822d354ddee2c6a121a6f670" - integrity sha512-/CHmzGN+IYgdBOme7PdqzF+FNeMleefzqs0LVOduncSaqsppeOEoskLXb2anSpzmQAP3xZJPaTrkQPWSJMORig== - dependencies: - web3-core "^4.4.0" - web3-types "^1.6.0" - web3-validator "^2.0.6" - -web3-rpc-providers@^1.0.0-rc.4: - version "1.0.0-rc.4" - resolved "https://registry.yarnpkg.com/web3-rpc-providers/-/web3-rpc-providers-1.0.0-rc.4.tgz#93cec88175eb2f7972e12be30af4c2f296b1923f" - integrity sha512-PXosCqHW0EADrYzgmueNHP3Y5jcSmSwH+Dkqvn7EYD0T2jcsdDAIHqk6szBiwIdhumM7gv9Raprsu/s/f7h1fw== - dependencies: - web3-errors "^1.3.1" - web3-providers-http "^4.2.0" - web3-providers-ws "^4.0.8" - web3-types "^1.10.0" - web3-utils "^4.3.3" - web3-validator "^2.0.6" - -web3-types@^1.10.0, web3-types@^1.3.0, web3-types@^1.6.0, web3-types@^1.7.0, web3-types@^1.8.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/web3-types/-/web3-types-1.10.0.tgz#41b0b4d2dd75e919d5b6f37bf139e29f445db04e" - integrity sha512-0IXoaAFtFc8Yin7cCdQfB9ZmjafrbP6BO0f0KT/khMhXKUpoJ6yShrVhiNpyRBo8QQjuOagsWzwSK2H49I7sbw== - -web3-utils@^4.0.7, web3-utils@^4.3.0, web3-utils@^4.3.1, web3-utils@^4.3.3: - version "4.3.3" - resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-4.3.3.tgz#e380a1c03a050d3704f94bd08c1c9f50a1487205" - integrity sha512-kZUeCwaQm+RNc2Bf1V3BYbF29lQQKz28L0y+FA4G0lS8IxtJVGi5SeDTUkpwqqkdHHC7JcapPDnyyzJ1lfWlOw== - dependencies: - ethereum-cryptography "^2.0.0" - eventemitter3 "^5.0.1" - web3-errors "^1.3.1" - web3-types "^1.10.0" - web3-validator "^2.0.6" - -web3-validator@^2.0.3, web3-validator@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/web3-validator/-/web3-validator-2.0.6.tgz#a0cdaa39e1d1708ece5fae155b034e29d6a19248" - integrity sha512-qn9id0/l1bWmvH4XfnG/JtGKKwut2Vokl6YXP5Kfg424npysmtRLe9DgiNBM9Op7QL/aSiaA0TVXibuIuWcizg== - dependencies: - ethereum-cryptography "^2.0.0" - util "^0.12.5" - web3-errors "^1.2.0" - web3-types "^1.6.0" - zod "^3.21.4" - -web3@^4.16.0: - version "4.16.0" - resolved "https://registry.yarnpkg.com/web3/-/web3-4.16.0.tgz#1da10d8405bf27a76de6cbbce3de9fa93f7c0449" - integrity sha512-SgoMSBo6EsJ5GFCGar2E/pR2lcR/xmUSuQ61iK6yDqzxmm42aPPxSqZfJz2z/UCR6pk03u77pU8TGV6lgMDdIQ== - dependencies: - web3-core "^4.7.1" - web3-errors "^1.3.1" - web3-eth "^4.11.1" - web3-eth-abi "^4.4.1" - web3-eth-accounts "^4.3.1" - web3-eth-contract "^4.7.2" - web3-eth-ens "^4.4.0" - web3-eth-iban "^4.0.7" - web3-eth-personal "^4.1.0" - web3-net "^4.1.0" - web3-providers-http "^4.2.0" - web3-providers-ws "^4.0.8" - web3-rpc-methods "^1.3.0" - web3-rpc-providers "^1.0.0-rc.4" - web3-types "^1.10.0" - web3-utils "^4.3.3" - web3-validator "^2.0.6" - -webidl-conversions@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" - integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== - -whatwg-url@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" - integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== - dependencies: - tr46 "~0.0.3" - webidl-conversions "^3.0.0" - -which-typed-array@^1.1.16, which-typed-array@^1.1.2: - version "1.1.19" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.19.tgz#df03842e870b6b88e117524a4b364b6fc689f956" - integrity sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw== - dependencies: - available-typed-arrays "^1.0.7" - call-bind "^1.0.8" - call-bound "^1.0.4" - for-each "^0.3.5" - get-proto "^1.0.1" - gopd "^1.2.0" - has-tostringtag "^1.0.2" - -widest-line@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca" - integrity sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg== - dependencies: - string-width "^4.0.0" - -workerpool@^6.5.1: - version "6.5.1" - resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.5.1.tgz#060f73b39d0caf97c6db64da004cd01b4c099544" - integrity sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA== - -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== - -ws@8.13.0: - version "8.13.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0" - integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA== - -ws@^7.4.6: - version "7.5.10" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9" - integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ== - -ws@^8.17.1: - version "8.18.2" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.2.tgz#42738b2be57ced85f46154320aabb51ab003705a" - integrity sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ== - -y18n@^5.0.5: - version "5.0.8" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" - integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== - -yargs-parser@^20.2.2, yargs-parser@^20.2.9: - version "20.2.9" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" - integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== - -yargs-unparser@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" - integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== - dependencies: - camelcase "^6.0.0" - decamelize "^4.0.0" - flat "^5.0.2" - is-plain-obj "^2.1.0" - -yargs@^16.2.0: - version "16.2.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" - integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== - dependencies: - cliui "^7.0.2" - escalade "^3.1.1" - get-caller-file "^2.0.5" - require-directory "^2.1.1" - string-width "^4.2.0" - y18n "^5.0.5" - yargs-parser "^20.2.2" - -yocto-queue@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" - integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== - -zod@^3.21.4: - version "3.25.48" - resolved "https://registry.yarnpkg.com/zod/-/zod-3.25.48.tgz#6c2b536fbb519905e8f4a4ac58743de4d5331bb2" - integrity sha512-0X1mz8FtgEIvaxGjdIImYpZEaZMrund9pGXm3M6vM7Reba0e2eI71KPjSCGXBfwKDPwPoywf6waUKc3/tFvX2Q== +# This file is generated by running "yarn install" inside your project. +# Manual changes might be lost - proceed with caution! + +__metadata: + version: 8 + cacheKey: 10c0 + +"@adraffy/ens-normalize@npm:^1.8.8": + version: 1.11.0 + resolution: "@adraffy/ens-normalize@npm:1.11.0" + checksum: 10c0/5111d0f1a273468cb5661ed3cf46ee58de8f32f84e2ebc2365652e66c1ead82649df94c736804e2b9cfa831d30ef24e1cc3575d970dbda583416d3a98d8870a6 + languageName: node + linkType: hard + +"@esbuild/aix-ppc64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/aix-ppc64@npm:0.25.5" + conditions: os=aix & cpu=ppc64 + languageName: node + linkType: hard + +"@esbuild/android-arm64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/android-arm64@npm:0.25.5" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/android-arm@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/android-arm@npm:0.25.5" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + +"@esbuild/android-x64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/android-x64@npm:0.25.5" + conditions: os=android & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/darwin-arm64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/darwin-arm64@npm:0.25.5" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/darwin-x64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/darwin-x64@npm:0.25.5" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/freebsd-arm64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/freebsd-arm64@npm:0.25.5" + conditions: os=freebsd & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/freebsd-x64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/freebsd-x64@npm:0.25.5" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/linux-arm64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/linux-arm64@npm:0.25.5" + conditions: os=linux & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/linux-arm@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/linux-arm@npm:0.25.5" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@esbuild/linux-ia32@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/linux-ia32@npm:0.25.5" + conditions: os=linux & cpu=ia32 + languageName: node + linkType: hard + +"@esbuild/linux-loong64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/linux-loong64@npm:0.25.5" + conditions: os=linux & cpu=loong64 + languageName: node + linkType: hard + +"@esbuild/linux-mips64el@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/linux-mips64el@npm:0.25.5" + conditions: os=linux & cpu=mips64el + languageName: node + linkType: hard + +"@esbuild/linux-ppc64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/linux-ppc64@npm:0.25.5" + conditions: os=linux & cpu=ppc64 + languageName: node + linkType: hard + +"@esbuild/linux-riscv64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/linux-riscv64@npm:0.25.5" + conditions: os=linux & cpu=riscv64 + languageName: node + linkType: hard + +"@esbuild/linux-s390x@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/linux-s390x@npm:0.25.5" + conditions: os=linux & cpu=s390x + languageName: node + linkType: hard + +"@esbuild/linux-x64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/linux-x64@npm:0.25.5" + conditions: os=linux & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/netbsd-arm64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/netbsd-arm64@npm:0.25.5" + conditions: os=netbsd & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/netbsd-x64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/netbsd-x64@npm:0.25.5" + conditions: os=netbsd & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/openbsd-arm64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/openbsd-arm64@npm:0.25.5" + conditions: os=openbsd & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/openbsd-x64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/openbsd-x64@npm:0.25.5" + conditions: os=openbsd & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/sunos-x64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/sunos-x64@npm:0.25.5" + conditions: os=sunos & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/win32-arm64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/win32-arm64@npm:0.25.5" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/win32-ia32@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/win32-ia32@npm:0.25.5" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@esbuild/win32-x64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/win32-x64@npm:0.25.5" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + +"@ethereumjs/rlp@npm:^4.0.1": + version: 4.0.1 + resolution: "@ethereumjs/rlp@npm:4.0.1" + bin: + rlp: bin/rlp + checksum: 10c0/78379f288e9d88c584c2159c725c4a667a9742981d638bad760ed908263e0e36bdbd822c0a902003e0701195fd1cbde7adad621cd97fdfbf552c45e835ce022c + languageName: node + linkType: hard + +"@ethereumjs/rlp@npm:^5.0.2": + version: 5.0.2 + resolution: "@ethereumjs/rlp@npm:5.0.2" + bin: + rlp: bin/rlp.cjs + checksum: 10c0/56162eaee96dd429f0528a9e51b453398546d57f26057b3e188f2aa09efe8bd430502971c54238ca9cc42af41b0a3f137cf67b9e020d52bc83caca043d64911b + languageName: node + linkType: hard + +"@ethereumjs/util@npm:^9.1.0": + version: 9.1.0 + resolution: "@ethereumjs/util@npm:9.1.0" + dependencies: + "@ethereumjs/rlp": "npm:^5.0.2" + ethereum-cryptography: "npm:^2.2.1" + checksum: 10c0/7b55c79d90e55da873037b8283c37b61164f1712b194e2783bdb0a3401ff0999dc9d1404c7051589f71fb79e8aeb6952ec43ede21dd0028d7d9b1c07abcfff27 + languageName: node + linkType: hard + +"@ethersproject/abi@npm:^5.1.2": + version: 5.8.0 + resolution: "@ethersproject/abi@npm:5.8.0" + dependencies: + "@ethersproject/address": "npm:^5.8.0" + "@ethersproject/bignumber": "npm:^5.8.0" + "@ethersproject/bytes": "npm:^5.8.0" + "@ethersproject/constants": "npm:^5.8.0" + "@ethersproject/hash": "npm:^5.8.0" + "@ethersproject/keccak256": "npm:^5.8.0" + "@ethersproject/logger": "npm:^5.8.0" + "@ethersproject/properties": "npm:^5.8.0" + "@ethersproject/strings": "npm:^5.8.0" + checksum: 10c0/6b759247a2f43ecc1548647d0447d08de1e946dfc7e71bfb014fa2f749c1b76b742a1d37394660ebab02ff8565674b3593fdfa011e16a5adcfc87ca4d85af39c + languageName: node + linkType: hard + +"@ethersproject/abstract-provider@npm:^5.8.0": + version: 5.8.0 + resolution: "@ethersproject/abstract-provider@npm:5.8.0" + dependencies: + "@ethersproject/bignumber": "npm:^5.8.0" + "@ethersproject/bytes": "npm:^5.8.0" + "@ethersproject/logger": "npm:^5.8.0" + "@ethersproject/networks": "npm:^5.8.0" + "@ethersproject/properties": "npm:^5.8.0" + "@ethersproject/transactions": "npm:^5.8.0" + "@ethersproject/web": "npm:^5.8.0" + checksum: 10c0/9c183da1d037b272ff2b03002c3d801088d0534f88985f4983efc5f3ebd59b05f04bc05db97792fe29ddf87eeba3c73416e5699615f183126f85f877ea6c8637 + languageName: node + linkType: hard + +"@ethersproject/abstract-signer@npm:^5.8.0": + version: 5.8.0 + resolution: "@ethersproject/abstract-signer@npm:5.8.0" + dependencies: + "@ethersproject/abstract-provider": "npm:^5.8.0" + "@ethersproject/bignumber": "npm:^5.8.0" + "@ethersproject/bytes": "npm:^5.8.0" + "@ethersproject/logger": "npm:^5.8.0" + "@ethersproject/properties": "npm:^5.8.0" + checksum: 10c0/143f32d7cb0bc7064e45674d4a9dffdb90d6171425d20e8de9dc95765be960534bae7246ead400e6f52346624b66569d9585d790eedd34b0b6b7f481ec331cc2 + languageName: node + linkType: hard + +"@ethersproject/address@npm:^5.8.0": + version: 5.8.0 + resolution: "@ethersproject/address@npm:5.8.0" + dependencies: + "@ethersproject/bignumber": "npm:^5.8.0" + "@ethersproject/bytes": "npm:^5.8.0" + "@ethersproject/keccak256": "npm:^5.8.0" + "@ethersproject/logger": "npm:^5.8.0" + "@ethersproject/rlp": "npm:^5.8.0" + checksum: 10c0/8bac8a4b567c75c1abc00eeca08c200de1a2d5cf76d595dc04fa4d7bff9ffa5530b2cdfc5e8656cfa8f6fa046de54be47620a092fb429830a8ddde410b9d50bc + languageName: node + linkType: hard + +"@ethersproject/base64@npm:^5.8.0": + version: 5.8.0 + resolution: "@ethersproject/base64@npm:5.8.0" + dependencies: + "@ethersproject/bytes": "npm:^5.8.0" + checksum: 10c0/60ae6d1e2367d70f4090b717852efe62075442ae59aeac9bb1054fe8306a2de8ef0b0561e7fb4666ecb1f8efa1655d683dd240675c3a25d6fa867245525a63ca + languageName: node + linkType: hard + +"@ethersproject/bignumber@npm:^5.8.0": + version: 5.8.0 + resolution: "@ethersproject/bignumber@npm:5.8.0" + dependencies: + "@ethersproject/bytes": "npm:^5.8.0" + "@ethersproject/logger": "npm:^5.8.0" + bn.js: "npm:^5.2.1" + checksum: 10c0/8e87fa96999d59d0ab4c814c79e3a8354d2ba914dfa78cf9ee688f53110473cec0df0db2aaf9d447e84ab2dbbfca39979abac4f2dac69fef4d080f4cc3e29613 + languageName: node + linkType: hard + +"@ethersproject/bytes@npm:^5.8.0": + version: 5.8.0 + resolution: "@ethersproject/bytes@npm:5.8.0" + dependencies: + "@ethersproject/logger": "npm:^5.8.0" + checksum: 10c0/47ef798f3ab43b95dc74097b2c92365c919308ecabc3e34d9f8bf7f886fa4b99837ba5cf4dc8921baaaafe6899982f96b0e723b3fc49132c061f83d1ca3fed8b + languageName: node + linkType: hard + +"@ethersproject/constants@npm:^5.8.0": + version: 5.8.0 + resolution: "@ethersproject/constants@npm:5.8.0" + dependencies: + "@ethersproject/bignumber": "npm:^5.8.0" + checksum: 10c0/374b3c2c6da24f8fef62e2316eae96faa462826c0774ef588cd7313ae7ddac8eb1bb85a28dad80123148be2ba0821c217c14ecfc18e2e683c72adc734b6248c9 + languageName: node + linkType: hard + +"@ethersproject/hash@npm:^5.8.0": + version: 5.8.0 + resolution: "@ethersproject/hash@npm:5.8.0" + dependencies: + "@ethersproject/abstract-signer": "npm:^5.8.0" + "@ethersproject/address": "npm:^5.8.0" + "@ethersproject/base64": "npm:^5.8.0" + "@ethersproject/bignumber": "npm:^5.8.0" + "@ethersproject/bytes": "npm:^5.8.0" + "@ethersproject/keccak256": "npm:^5.8.0" + "@ethersproject/logger": "npm:^5.8.0" + "@ethersproject/properties": "npm:^5.8.0" + "@ethersproject/strings": "npm:^5.8.0" + checksum: 10c0/72a287d4d70fae716827587339ffb449b8c23ef8728db6f8a661f359f7cb1e5ffba5b693c55e09d4e7162bf56af4a0e98a334784e0706d98102d1a5786241537 + languageName: node + linkType: hard + +"@ethersproject/keccak256@npm:^5.8.0": + version: 5.8.0 + resolution: "@ethersproject/keccak256@npm:5.8.0" + dependencies: + "@ethersproject/bytes": "npm:^5.8.0" + js-sha3: "npm:0.8.0" + checksum: 10c0/cd93ac6a5baf842313cde7de5e6e2c41feeea800db9e82955f96e7f3462d2ac6a6a29282b1c9e93b84ce7c91eec02347043c249fd037d6051214275bfc7fe99f + languageName: node + linkType: hard + +"@ethersproject/logger@npm:^5.8.0": + version: 5.8.0 + resolution: "@ethersproject/logger@npm:5.8.0" + checksum: 10c0/7f39f33e8f254ee681d4778bb71ce3c5de248e1547666f85c43bfbc1c18996c49a31f969f056b66d23012f2420f2d39173107284bc41eb98d0482ace1d06403e + languageName: node + linkType: hard + +"@ethersproject/networks@npm:^5.8.0": + version: 5.8.0 + resolution: "@ethersproject/networks@npm:5.8.0" + dependencies: + "@ethersproject/logger": "npm:^5.8.0" + checksum: 10c0/3f23bcc4c3843cc9b7e4b9f34df0a1f230b24dc87d51cdad84552302159a84d7899cd80c8a3d2cf8007b09ac373a5b10407007adde23d4c4881a4d6ee6bc4b9c + languageName: node + linkType: hard + +"@ethersproject/properties@npm:^5.8.0": + version: 5.8.0 + resolution: "@ethersproject/properties@npm:5.8.0" + dependencies: + "@ethersproject/logger": "npm:^5.8.0" + checksum: 10c0/20256d7eed65478a38dabdea4c3980c6591b7b75f8c45089722b032ceb0e1cd3dd6dd60c436cfe259337e6909c28d99528c172d06fc74bbd61be8eb9e68be2e6 + languageName: node + linkType: hard + +"@ethersproject/rlp@npm:^5.8.0": + version: 5.8.0 + resolution: "@ethersproject/rlp@npm:5.8.0" + dependencies: + "@ethersproject/bytes": "npm:^5.8.0" + "@ethersproject/logger": "npm:^5.8.0" + checksum: 10c0/db742ec9c1566d6441242cc2c2ae34c1e5304d48e1fe62bc4e53b1791f219df211e330d2de331e0e4f74482664e205c2e4220e76138bd71f1ec07884e7f5221b + languageName: node + linkType: hard + +"@ethersproject/signing-key@npm:^5.8.0": + version: 5.8.0 + resolution: "@ethersproject/signing-key@npm:5.8.0" + dependencies: + "@ethersproject/bytes": "npm:^5.8.0" + "@ethersproject/logger": "npm:^5.8.0" + "@ethersproject/properties": "npm:^5.8.0" + bn.js: "npm:^5.2.1" + elliptic: "npm:6.6.1" + hash.js: "npm:1.1.7" + checksum: 10c0/a7ff6cd344b0609737a496b6d5b902cf5528ed5a7ce2c0db5e7b69dc491d1810d1d0cd51dddf9dc74dd562ab4961d76e982f1750359b834c53c202e85e4c8502 + languageName: node + linkType: hard + +"@ethersproject/strings@npm:^5.8.0": + version: 5.8.0 + resolution: "@ethersproject/strings@npm:5.8.0" + dependencies: + "@ethersproject/bytes": "npm:^5.8.0" + "@ethersproject/constants": "npm:^5.8.0" + "@ethersproject/logger": "npm:^5.8.0" + checksum: 10c0/6db39503c4be130110612b6d593a381c62657e41eebf4f553247ebe394fda32cdf74ff645daee7b7860d209fd02c7e909a95b1f39a2f001c662669b9dfe81d00 + languageName: node + linkType: hard + +"@ethersproject/transactions@npm:^5.8.0": + version: 5.8.0 + resolution: "@ethersproject/transactions@npm:5.8.0" + dependencies: + "@ethersproject/address": "npm:^5.8.0" + "@ethersproject/bignumber": "npm:^5.8.0" + "@ethersproject/bytes": "npm:^5.8.0" + "@ethersproject/constants": "npm:^5.8.0" + "@ethersproject/keccak256": "npm:^5.8.0" + "@ethersproject/logger": "npm:^5.8.0" + "@ethersproject/properties": "npm:^5.8.0" + "@ethersproject/rlp": "npm:^5.8.0" + "@ethersproject/signing-key": "npm:^5.8.0" + checksum: 10c0/dd32f090df5945313aafa8430ce76834479750d6655cb786c3b65ec841c94596b14d3c8c59ee93eed7b4f32f27d321a9b8b43bc6bb51f7e1c6694f82639ffe68 + languageName: node + linkType: hard + +"@ethersproject/web@npm:^5.8.0": + version: 5.8.0 + resolution: "@ethersproject/web@npm:5.8.0" + dependencies: + "@ethersproject/base64": "npm:^5.8.0" + "@ethersproject/bytes": "npm:^5.8.0" + "@ethersproject/logger": "npm:^5.8.0" + "@ethersproject/properties": "npm:^5.8.0" + "@ethersproject/strings": "npm:^5.8.0" + checksum: 10c0/e3cd547225638db6e94fcd890001c778d77adb0d4f11a7f8c447e961041678f3fbfaffe77a962c7aa3f6597504232442e7015f2335b1788508a108708a30308a + languageName: node + linkType: hard + +"@fastify/busboy@npm:^2.0.0": + version: 2.1.1 + resolution: "@fastify/busboy@npm:2.1.1" + checksum: 10c0/6f8027a8cba7f8f7b736718b013f5a38c0476eea67034c94a0d3c375e2b114366ad4419e6a6fa7ffc2ef9c6d3e0435d76dd584a7a1cbac23962fda7650b579e3 + languageName: node + linkType: hard + +"@isaacs/cliui@npm:^8.0.2": + version: 8.0.2 + resolution: "@isaacs/cliui@npm:8.0.2" + dependencies: + string-width: "npm:^5.1.2" + string-width-cjs: "npm:string-width@^4.2.0" + strip-ansi: "npm:^7.0.1" + strip-ansi-cjs: "npm:strip-ansi@^6.0.1" + wrap-ansi: "npm:^8.1.0" + wrap-ansi-cjs: "npm:wrap-ansi@^7.0.0" + checksum: 10c0/b1bf42535d49f11dc137f18d5e4e63a28c5569de438a221c369483731e9dac9fb797af554e8bf02b6192d1e5eba6e6402cf93900c3d0ac86391d00d04876789e + languageName: node + linkType: hard + +"@isaacs/fs-minipass@npm:^4.0.0": + version: 4.0.1 + resolution: "@isaacs/fs-minipass@npm:4.0.1" + dependencies: + minipass: "npm:^7.0.4" + checksum: 10c0/c25b6dc1598790d5b55c0947a9b7d111cfa92594db5296c3b907e2f533c033666f692a3939eadac17b1c7c40d362d0b0635dc874cbfe3e70db7c2b07cc97a5d2 + languageName: node + linkType: hard + +"@lido-js/ganache@npm:=7.9.2-lido": + version: 7.9.2-lido + resolution: "@lido-js/ganache@npm:7.9.2-lido" + dependencies: + "@trufflesuite/bigint-buffer": "npm:1.1.10" + "@trufflesuite/uws-js-unofficial": "npm:20.30.0-unofficial.0" + "@types/bn.js": "npm:^5.1.0" + "@types/lru-cache": "npm:5.1.1" + "@types/seedrandom": "npm:3.0.1" + abstract-level: "npm:1.0.3" + abstract-leveldown: "npm:7.2.0" + async-eventemitter: "npm:0.2.4" + bufferutil: "npm:4.0.5" + emittery: "npm:0.10.0" + keccak: "npm:3.0.2" + leveldown: "npm:6.1.0" + secp256k1: "npm:4.0.3" + utf-8-validate: "npm:5.0.7" + dependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + bin: + ganache: dist/node/cli.js + ganache-cli: dist/node/cli.js + checksum: 10c0/503800d45b4ed962cae9c6e77de26e2531c9986cb703cc89f99fbf7b05a4d00961ef2e8961c7f71cb7303c30e477fc51d9e99cbde32f3eb2f322f3c49505366a + languageName: node + linkType: hard + +"@noble/curves@npm:1.4.2, @noble/curves@npm:~1.4.0": + version: 1.4.2 + resolution: "@noble/curves@npm:1.4.2" + dependencies: + "@noble/hashes": "npm:1.4.0" + checksum: 10c0/65620c895b15d46e8087939db6657b46a1a15cd4e0e4de5cd84b97a0dfe0af85f33a431bb21ac88267e3dc508618245d4cb564213959d66a84d690fe18a63419 + languageName: node + linkType: hard + +"@noble/curves@npm:~1.8.1": + version: 1.8.2 + resolution: "@noble/curves@npm:1.8.2" + dependencies: + "@noble/hashes": "npm:1.7.2" + checksum: 10c0/e7ef119b114681d6b7530b29a21f9bbea6fa6973bc369167da2158d05054cc6e6dbfb636ba89fad7707abacc150de30188b33192f94513911b24bdb87af50bbd + languageName: node + linkType: hard + +"@noble/hashes@npm:1.2.0, @noble/hashes@npm:~1.2.0": + version: 1.2.0 + resolution: "@noble/hashes@npm:1.2.0" + checksum: 10c0/8bd3edb7bb6a9068f806a9a5a208cc2144e42940a21c049d8e9a0c23db08bef5cf1cfd844a7e35489b5ab52c6fa6299352075319e7f531e0996d459c38cfe26a + languageName: node + linkType: hard + +"@noble/hashes@npm:1.4.0, @noble/hashes@npm:~1.4.0": + version: 1.4.0 + resolution: "@noble/hashes@npm:1.4.0" + checksum: 10c0/8c3f005ee72e7b8f9cff756dfae1241485187254e3f743873e22073d63906863df5d4f13d441b7530ea614b7a093f0d889309f28b59850f33b66cb26a779a4a5 + languageName: node + linkType: hard + +"@noble/hashes@npm:1.7.2, @noble/hashes@npm:~1.7.1": + version: 1.7.2 + resolution: "@noble/hashes@npm:1.7.2" + checksum: 10c0/b1411eab3c0b6691d847e9394fe7f1fcd45eeb037547c8f97e7d03c5068a499b4aef188e8e717eee67389dca4fee17d69d7e0f58af6c092567b0b76359b114b2 + languageName: node + linkType: hard + +"@noble/secp256k1@npm:1.7.1, @noble/secp256k1@npm:~1.7.0": + version: 1.7.1 + resolution: "@noble/secp256k1@npm:1.7.1" + checksum: 10c0/48091801d39daba75520012027d0ff0b1719338d96033890cfe0d287ad75af00d82769c0194a06e7e4fbd816ae3f204f4a59c9e26f0ad16b429f7e9b5403ccd5 + languageName: node + linkType: hard + +"@nomicfoundation/edr-darwin-arm64@npm:0.11.0": + version: 0.11.0 + resolution: "@nomicfoundation/edr-darwin-arm64@npm:0.11.0" + checksum: 10c0/bf4abf4a4c84b4cbe6077dc05421e72aeadde719b4a33825c994126c8b3c5bb2a6296941ab18ad9f54945becf9dee692a8cbb77e7448be246dfcdde19ac2b967 + languageName: node + linkType: hard + +"@nomicfoundation/edr-darwin-x64@npm:0.11.0": + version: 0.11.0 + resolution: "@nomicfoundation/edr-darwin-x64@npm:0.11.0" + checksum: 10c0/aff56bb9c247f7fc435e208dc7bc17bea8f7f27e8d63797dadd2565db6641c684f16d77685375f7d5194238da648415085b9a71243e5e4e7743c37edff2e64c5 + languageName: node + linkType: hard + +"@nomicfoundation/edr-linux-arm64-gnu@npm:0.11.0": + version: 0.11.0 + resolution: "@nomicfoundation/edr-linux-arm64-gnu@npm:0.11.0" + checksum: 10c0/454fe2c7a1be6add79527b3372671483e5012949bc022a0ddf63773d79b5c8920375b25385594d05f26d553b10ca273df4c4084c30515788a2ab6aa25440aa0c + languageName: node + linkType: hard + +"@nomicfoundation/edr-linux-arm64-musl@npm:0.11.0": + version: 0.11.0 + resolution: "@nomicfoundation/edr-linux-arm64-musl@npm:0.11.0" + checksum: 10c0/8737fb029d7572ae09ca2c02ec5bd4f15d541d361e8adbacb8dd26448b1a6e1e0f2af3883aad983309217d9a0104488c15e6427563bad3d754f25427571b6077 + languageName: node + linkType: hard + +"@nomicfoundation/edr-linux-x64-gnu@npm:0.11.0": + version: 0.11.0 + resolution: "@nomicfoundation/edr-linux-x64-gnu@npm:0.11.0" + checksum: 10c0/21902281cd923bff6e0057cc79e81fde68376caf4db6b0798ccefd6eb2583899ee23f0ccd24c90a8180c6d8426fbf7876bf5d3e61546bd3dfc586a5b69f32f9c + languageName: node + linkType: hard + +"@nomicfoundation/edr-linux-x64-musl@npm:0.11.0": + version: 0.11.0 + resolution: "@nomicfoundation/edr-linux-x64-musl@npm:0.11.0" + checksum: 10c0/0cc2cb5756228946734811e9aa3abc291e96ece5357895ff2a004888aef8bc6c85d53266cf2a3b2ae0ff08e81516676a7117fe9bf4478156b0b957cea10a68f1 + languageName: node + linkType: hard + +"@nomicfoundation/edr-win32-x64-msvc@npm:0.11.0": + version: 0.11.0 + resolution: "@nomicfoundation/edr-win32-x64-msvc@npm:0.11.0" + checksum: 10c0/716cdb10470a4cfab1f3d9cfed85adea457914c18121e6b30e4c8ae3a3c1d5cd291650feffceb09e4794cf7b6f7f31897710cd836235ea9c9e4159a14405335d + languageName: node + linkType: hard + +"@nomicfoundation/edr@npm:^0.11.0": + version: 0.11.0 + resolution: "@nomicfoundation/edr@npm:0.11.0" + dependencies: + "@nomicfoundation/edr-darwin-arm64": "npm:0.11.0" + "@nomicfoundation/edr-darwin-x64": "npm:0.11.0" + "@nomicfoundation/edr-linux-arm64-gnu": "npm:0.11.0" + "@nomicfoundation/edr-linux-arm64-musl": "npm:0.11.0" + "@nomicfoundation/edr-linux-x64-gnu": "npm:0.11.0" + "@nomicfoundation/edr-linux-x64-musl": "npm:0.11.0" + "@nomicfoundation/edr-win32-x64-msvc": "npm:0.11.0" + checksum: 10c0/446203e8ebc98742d913ad9d1f89774fac4f1fb69f04c170787d7ff9fcfe06eeb1a9e1e0649980fca6d3e5c36099e784fc5a6b4380da8e59dd016cb6575adb63 + languageName: node + linkType: hard + +"@nomicfoundation/solidity-analyzer-darwin-arm64@npm:0.1.2": + version: 0.1.2 + resolution: "@nomicfoundation/solidity-analyzer-darwin-arm64@npm:0.1.2" + checksum: 10c0/ef3b13bb2133fea6621db98f991036a3a84d2b240160edec50beafa6ce821fe2f0f5cd4aa61adb9685aff60cd0425982ffd15e0b868b7c768e90e26b8135b825 + languageName: node + linkType: hard + +"@nomicfoundation/solidity-analyzer-darwin-x64@npm:0.1.2": + version: 0.1.2 + resolution: "@nomicfoundation/solidity-analyzer-darwin-x64@npm:0.1.2" + checksum: 10c0/3cb6a00cd200b94efd6f59ed626c705c6f773b92ccf8b90471285cd0e81b35f01edb30c1aa5a4633393c2adb8f20fd34e90c51990dc4e30658e8a67c026d16c9 + languageName: node + linkType: hard + +"@nomicfoundation/solidity-analyzer-linux-arm64-gnu@npm:0.1.2": + version: 0.1.2 + resolution: "@nomicfoundation/solidity-analyzer-linux-arm64-gnu@npm:0.1.2" + checksum: 10c0/cb9725e7bdc3ba9c1feaef96dbf831c1a59c700ca633a9929fd97debdcb5ce06b5d7b4e6dbc076279978707214d01e2cd126d8e3f4cabc5c16525c031a47b95c + languageName: node + linkType: hard + +"@nomicfoundation/solidity-analyzer-linux-arm64-musl@npm:0.1.2": + version: 0.1.2 + resolution: "@nomicfoundation/solidity-analyzer-linux-arm64-musl@npm:0.1.2" + checksum: 10c0/82a90b1d09ad266ddc510ece2e397f51fdaf29abf7263d2a3a85accddcba2ac24cceb670a3120800611cdcc552eed04919d071e259fdda7564818359ed541f5d + languageName: node + linkType: hard + +"@nomicfoundation/solidity-analyzer-linux-x64-gnu@npm:0.1.2": + version: 0.1.2 + resolution: "@nomicfoundation/solidity-analyzer-linux-x64-gnu@npm:0.1.2" + checksum: 10c0/d1f20d4d55683bd041ead957e5461b2e43a39e959f905e8866de1d65f8d96118e9b861e994604d9002cb7f056be0844e36c241a6bb531c336b399609977c0998 + languageName: node + linkType: hard + +"@nomicfoundation/solidity-analyzer-linux-x64-musl@npm:0.1.2": + version: 0.1.2 + resolution: "@nomicfoundation/solidity-analyzer-linux-x64-musl@npm:0.1.2" + checksum: 10c0/6c17f9af3aaf184c0a217cf723076051c502d85e731dbc97f34b838f9ae1b597577abac54a2af49b3fd986b09131c52fa21fd5393b22d05e1ec7fee96a8249c2 + languageName: node + linkType: hard + +"@nomicfoundation/solidity-analyzer-win32-x64-msvc@npm:0.1.2": + version: 0.1.2 + resolution: "@nomicfoundation/solidity-analyzer-win32-x64-msvc@npm:0.1.2" + checksum: 10c0/da198464f5ee0d19b6decdfaa65ee0df3097b8960b8483bb7080931968815a5d60f27191229d47a198955784d763d5996f0b92bfde3551612ad972c160b0b000 + languageName: node + linkType: hard + +"@nomicfoundation/solidity-analyzer@npm:^0.1.0": + version: 0.1.2 + resolution: "@nomicfoundation/solidity-analyzer@npm:0.1.2" + dependencies: + "@nomicfoundation/solidity-analyzer-darwin-arm64": "npm:0.1.2" + "@nomicfoundation/solidity-analyzer-darwin-x64": "npm:0.1.2" + "@nomicfoundation/solidity-analyzer-linux-arm64-gnu": "npm:0.1.2" + "@nomicfoundation/solidity-analyzer-linux-arm64-musl": "npm:0.1.2" + "@nomicfoundation/solidity-analyzer-linux-x64-gnu": "npm:0.1.2" + "@nomicfoundation/solidity-analyzer-linux-x64-musl": "npm:0.1.2" + "@nomicfoundation/solidity-analyzer-win32-x64-msvc": "npm:0.1.2" + dependenciesMeta: + "@nomicfoundation/solidity-analyzer-darwin-arm64": + optional: true + "@nomicfoundation/solidity-analyzer-darwin-x64": + optional: true + "@nomicfoundation/solidity-analyzer-linux-arm64-gnu": + optional: true + "@nomicfoundation/solidity-analyzer-linux-arm64-musl": + optional: true + "@nomicfoundation/solidity-analyzer-linux-x64-gnu": + optional: true + "@nomicfoundation/solidity-analyzer-linux-x64-musl": + optional: true + "@nomicfoundation/solidity-analyzer-win32-x64-msvc": + optional: true + checksum: 10c0/e4f503e9287e18967535af669ca7e26e2682203c45a34ea85da53122da1dee1278f2b8c76c20c67fadd7c1b1a98eeecffd2cbc136860665e3afa133817c0de54 + languageName: node + linkType: hard + +"@npmcli/agent@npm:^3.0.0": + version: 3.0.0 + resolution: "@npmcli/agent@npm:3.0.0" + dependencies: + agent-base: "npm:^7.1.0" + http-proxy-agent: "npm:^7.0.0" + https-proxy-agent: "npm:^7.0.1" + lru-cache: "npm:^10.0.1" + socks-proxy-agent: "npm:^8.0.3" + checksum: 10c0/efe37b982f30740ee77696a80c196912c274ecd2cb243bc6ae7053a50c733ce0f6c09fda085145f33ecf453be19654acca74b69e81eaad4c90f00ccffe2f9271 + languageName: node + linkType: hard + +"@npmcli/fs@npm:^4.0.0": + version: 4.0.0 + resolution: "@npmcli/fs@npm:4.0.0" + dependencies: + semver: "npm:^7.3.5" + checksum: 10c0/c90935d5ce670c87b6b14fab04a965a3b8137e585f8b2a6257263bd7f97756dd736cb165bb470e5156a9e718ecd99413dccc54b1138c1a46d6ec7cf325982fe5 + languageName: node + linkType: hard + +"@pkgjs/parseargs@npm:^0.11.0": + version: 0.11.0 + resolution: "@pkgjs/parseargs@npm:0.11.0" + checksum: 10c0/5bd7576bb1b38a47a7fc7b51ac9f38748e772beebc56200450c4a817d712232b8f1d3ef70532c80840243c657d491cf6a6be1e3a214cff907645819fdc34aadd + languageName: node + linkType: hard + +"@scure/base@npm:~1.1.0, @scure/base@npm:~1.1.6": + version: 1.1.9 + resolution: "@scure/base@npm:1.1.9" + checksum: 10c0/77a06b9a2db8144d22d9bf198338893d77367c51b58c72b99df990c0a11f7cadd066d4102abb15e3ca6798d1529e3765f55c4355742465e49aed7a0c01fe76e8 + languageName: node + linkType: hard + +"@scure/base@npm:~1.2.5": + version: 1.2.6 + resolution: "@scure/base@npm:1.2.6" + checksum: 10c0/49bd5293371c4e062cb6ba689c8fe3ea3981b7bb9c000400dc4eafa29f56814cdcdd27c04311c2fec34de26bc373c593a1d6ca6d754398a488d587943b7c128a + languageName: node + linkType: hard + +"@scure/bip32@npm:1.1.5": + version: 1.1.5 + resolution: "@scure/bip32@npm:1.1.5" + dependencies: + "@noble/hashes": "npm:~1.2.0" + "@noble/secp256k1": "npm:~1.7.0" + "@scure/base": "npm:~1.1.0" + checksum: 10c0/d0521f6de28278e06f2d517307b4de6c9bcb3dbdf9a5844bb57a6e4916a180e4136129ccab295c27bd1196ef77757608255afcd7cf927e03baec4479b3df74fc + languageName: node + linkType: hard + +"@scure/bip32@npm:1.4.0": + version: 1.4.0 + resolution: "@scure/bip32@npm:1.4.0" + dependencies: + "@noble/curves": "npm:~1.4.0" + "@noble/hashes": "npm:~1.4.0" + "@scure/base": "npm:~1.1.6" + checksum: 10c0/6849690d49a3bf1d0ffde9452eb16ab83478c1bc0da7b914f873e2930cd5acf972ee81320e3df1963eb247cf57e76d2d975b5f97093d37c0e3f7326581bf41bd + languageName: node + linkType: hard + +"@scure/bip39@npm:1.1.1": + version: 1.1.1 + resolution: "@scure/bip39@npm:1.1.1" + dependencies: + "@noble/hashes": "npm:~1.2.0" + "@scure/base": "npm:~1.1.0" + checksum: 10c0/821dc9d5be8362a32277390526db064860c2216a079ba51d63def9289c2b290599e93681ebbeebf0e93540799eec35784c1dfcf5167d0b280ef148e5023ce01b + languageName: node + linkType: hard + +"@scure/bip39@npm:1.3.0": + version: 1.3.0 + resolution: "@scure/bip39@npm:1.3.0" + dependencies: + "@noble/hashes": "npm:~1.4.0" + "@scure/base": "npm:~1.1.6" + checksum: 10c0/1ae1545a7384a4d9e33e12d9e9f8824f29b0279eb175b0f0657c0a782c217920054f9a1d28eb316a417dfc6c4e0b700d6fbdc6da160670107426d52fcbe017a8 + languageName: node + linkType: hard + +"@sentry/core@npm:5.30.0": + version: 5.30.0 + resolution: "@sentry/core@npm:5.30.0" + dependencies: + "@sentry/hub": "npm:5.30.0" + "@sentry/minimal": "npm:5.30.0" + "@sentry/types": "npm:5.30.0" + "@sentry/utils": "npm:5.30.0" + tslib: "npm:^1.9.3" + checksum: 10c0/6407b9c2a6a56f90c198f5714b3257df24d89d1b4ca6726bd44760d0adabc25798b69fef2c88ccea461c7e79e3c78861aaebfd51fd3cb892aee656c3f7e11801 + languageName: node + linkType: hard + +"@sentry/hub@npm:5.30.0": + version: 5.30.0 + resolution: "@sentry/hub@npm:5.30.0" + dependencies: + "@sentry/types": "npm:5.30.0" + "@sentry/utils": "npm:5.30.0" + tslib: "npm:^1.9.3" + checksum: 10c0/386c91d06aa44be0465fc11330d748a113e464d41cd562a9e1d222a682cbcb14e697a3e640953e7a0239997ad8a02b223a0df3d9e1d8816cb823fd3613be3e2f + languageName: node + linkType: hard + +"@sentry/minimal@npm:5.30.0": + version: 5.30.0 + resolution: "@sentry/minimal@npm:5.30.0" + dependencies: + "@sentry/hub": "npm:5.30.0" + "@sentry/types": "npm:5.30.0" + tslib: "npm:^1.9.3" + checksum: 10c0/34ec05503de46d01f98c94701475d5d89cc044892c86ccce30e01f62f28344eb23b718e7cf573815e46f30a4ac9da3129bed9b3d20c822938acfb40cbe72437b + languageName: node + linkType: hard + +"@sentry/node@npm:^5.18.1": + version: 5.30.0 + resolution: "@sentry/node@npm:5.30.0" + dependencies: + "@sentry/core": "npm:5.30.0" + "@sentry/hub": "npm:5.30.0" + "@sentry/tracing": "npm:5.30.0" + "@sentry/types": "npm:5.30.0" + "@sentry/utils": "npm:5.30.0" + cookie: "npm:^0.4.1" + https-proxy-agent: "npm:^5.0.0" + lru_map: "npm:^0.3.3" + tslib: "npm:^1.9.3" + checksum: 10c0/c50db7c81ace57cac17692245c2ab3c84a6149183f81d5f2dfd157eaa7b66eb4d6a727dd13a754bb129c96711389eec2944cd94126722ee1d8b11f2b627b830d + languageName: node + linkType: hard + +"@sentry/tracing@npm:5.30.0": + version: 5.30.0 + resolution: "@sentry/tracing@npm:5.30.0" + dependencies: + "@sentry/hub": "npm:5.30.0" + "@sentry/minimal": "npm:5.30.0" + "@sentry/types": "npm:5.30.0" + "@sentry/utils": "npm:5.30.0" + tslib: "npm:^1.9.3" + checksum: 10c0/46830265bc54a3203d7d9f0d8d9f2f7d9d2c6a977e07ccdae317fa3ea29c388b904b3bef28f7a0ba9c074845d67feab63c6d3c0ddce9aeb275b6c966253fb415 + languageName: node + linkType: hard + +"@sentry/types@npm:5.30.0": + version: 5.30.0 + resolution: "@sentry/types@npm:5.30.0" + checksum: 10c0/99c6e55c0a82c8ca95be2e9dbb35f581b29e4ff7af74b23bc62b690de4e35febfa15868184a2303480ef86babd4fea5273cf3b5ddf4a27685b841a72f13a0c88 + languageName: node + linkType: hard + +"@sentry/utils@npm:5.30.0": + version: 5.30.0 + resolution: "@sentry/utils@npm:5.30.0" + dependencies: + "@sentry/types": "npm:5.30.0" + tslib: "npm:^1.9.3" + checksum: 10c0/ca8eebfea7ac7db6d16f6c0b8a66ac62587df12a79ce9d0d8393f4d69880bb8d40d438f9810f7fb107a9880fe0d68bbf797b89cbafd113e89a0829eb06b205f8 + languageName: node + linkType: hard + +"@trufflesuite/bigint-buffer@npm:1.1.10": + version: 1.1.10 + resolution: "@trufflesuite/bigint-buffer@npm:1.1.10" + dependencies: + node-gyp: "npm:latest" + node-gyp-build: "npm:4.4.0" + checksum: 10c0/5761201f32d05f1513f6591c38026ce00ff87462e26a2640e458be23fb57fa83b5fddef433220253ee3f98d0010959b7720db0a094d048d1c825978fd7a96938 + languageName: node + linkType: hard + +"@trufflesuite/uws-js-unofficial@npm:20.30.0-unofficial.0": + version: 20.30.0-unofficial.0 + resolution: "@trufflesuite/uws-js-unofficial@npm:20.30.0-unofficial.0" + dependencies: + bufferutil: "npm:4.0.7" + utf-8-validate: "npm:6.0.3" + ws: "npm:8.13.0" + dependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + checksum: 10c0/92f6997409add8b27c9106d3b27ba7d62dc763bff3baa4940bf7db890c12f32bdf88ba163fdb52787c78ed2d4def2f19c912891045914ffc0913d409aaa3b144 + languageName: node + linkType: hard + +"@types/bn.js@npm:^5.1.0": + version: 5.1.5 + resolution: "@types/bn.js@npm:5.1.5" + dependencies: + "@types/node": "npm:*" + checksum: 10c0/e9f375b43d8119ed82aed2090f83d4cda8afbb63ba13223afb02fa7550258ff90acd76d65cd7186838644048f085241cd98a3a512d8d187aa497c6039c746ac8 + languageName: node + linkType: hard + +"@types/lru-cache@npm:5.1.1, @types/lru-cache@npm:^5.1.0": + version: 5.1.1 + resolution: "@types/lru-cache@npm:5.1.1" + checksum: 10c0/1f17ec9b202c01a89337cc5528198a690be6b61a6688242125fbfb7fa17770e453e00e4685021abf5ae605860ca0722209faac5c254b780d0104730bb0b9e354 + languageName: node + linkType: hard + +"@types/node@npm:*": + version: 20.11.16 + resolution: "@types/node@npm:20.11.16" + dependencies: + undici-types: "npm:~5.26.4" + checksum: 10c0/4886b90278e9c877a84efd3edd4667cd990e032d77268d2a798b99ebc1901ea336fa7dfbe9eaf4ad6ad1da9ce2ec31baf300038a3905838692362eb19904ebde + languageName: node + linkType: hard + +"@types/seedrandom@npm:3.0.1": + version: 3.0.1 + resolution: "@types/seedrandom@npm:3.0.1" + checksum: 10c0/b9be192c99b25d7d5d93928e6106f1baff86a4ced33c7b9f94609c659c5d8cb657b70683c74798f83e12caf75af072d3e4f2608ab57a01c897c512fe991f6c9a + languageName: node + linkType: hard + +"@types/ws@npm:8.5.3": + version: 8.5.3 + resolution: "@types/ws@npm:8.5.3" + dependencies: + "@types/node": "npm:*" + checksum: 10c0/af36857b804e6df615b401bacf34e9312f073ed9dbeda35be16ee3352d18a4449f27066169893166a6ec17ae51557c3adf8d232ac4a4a0226aafb3267e1f1b39 + languageName: node + linkType: hard + +"abbrev@npm:^3.0.0": + version: 3.0.1 + resolution: "abbrev@npm:3.0.1" + checksum: 10c0/21ba8f574ea57a3106d6d35623f2c4a9111d9ee3e9a5be47baed46ec2457d2eac46e07a5c4a60186f88cb98abbe3e24f2d4cca70bc2b12f1692523e2209a9ccf + languageName: node + linkType: hard + +"abitype@npm:0.7.1": + version: 0.7.1 + resolution: "abitype@npm:0.7.1" + peerDependencies: + typescript: ">=4.9.4" + zod: ^3 >=3.19.1 + peerDependenciesMeta: + zod: + optional: true + checksum: 10c0/c95386afc8438b29d09fcb6d7bc3a457958ab0a472483a363bdb9bf9f42e1b90ab5b05a16f04b653ad0bf79f4451233fe35fc6c7a04b66cb4eba9df7d8e49f12 + languageName: node + linkType: hard + +"abstract-level@npm:1.0.3": + version: 1.0.3 + resolution: "abstract-level@npm:1.0.3" + dependencies: + buffer: "npm:^6.0.3" + catering: "npm:^2.1.0" + is-buffer: "npm:^2.0.5" + level-supports: "npm:^4.0.0" + level-transcoder: "npm:^1.0.1" + module-error: "npm:^1.0.1" + queue-microtask: "npm:^1.2.3" + checksum: 10c0/ead09e2aebd45a6aa06175dbda19f08c3fbe2b3fb7637cc15f7c165969fb5ef25a04b743f7e1835fd7cb7f8757ba41a9f43f27b092ab78cab5506f250effc966 + languageName: node + linkType: hard + +"abstract-leveldown@npm:7.2.0, abstract-leveldown@npm:^7.2.0": + version: 7.2.0 + resolution: "abstract-leveldown@npm:7.2.0" + dependencies: + buffer: "npm:^6.0.3" + catering: "npm:^2.0.0" + is-buffer: "npm:^2.0.5" + level-concat-iterator: "npm:^3.0.0" + level-supports: "npm:^2.0.1" + queue-microtask: "npm:^1.2.3" + checksum: 10c0/c81765642fc2100499fadc3254470a338ba7c0ba2e597b15cd13d91f333a54619b4d5c4137765e0835817142cd23e8eb7bf01b6a217e13c492f4872c164184dc + languageName: node + linkType: hard + +"adm-zip@npm:^0.4.16": + version: 0.4.16 + resolution: "adm-zip@npm:0.4.16" + checksum: 10c0/c56c6e138fd19006155fc716acae14d54e07c267ae19d78c8a8cdca04762bf20170a71a41aa8d8bad2f13b70d4f3e9a191009bafa5280e05a440ee506f871a55 + languageName: node + linkType: hard + +"agent-base@npm:6": + version: 6.0.2 + resolution: "agent-base@npm:6.0.2" + dependencies: + debug: "npm:4" + checksum: 10c0/dc4f757e40b5f3e3d674bc9beb4f1048f4ee83af189bae39be99f57bf1f48dde166a8b0a5342a84b5944ee8e6ed1e5a9d801858f4ad44764e84957122fe46261 + languageName: node + linkType: hard + +"agent-base@npm:^7.1.0, agent-base@npm:^7.1.2": + version: 7.1.4 + resolution: "agent-base@npm:7.1.4" + checksum: 10c0/c2c9ab7599692d594b6a161559ada307b7a624fa4c7b03e3afdb5a5e31cd0e53269115b620fcab024c5ac6a6f37fa5eb2e004f076ad30f5f7e6b8b671f7b35fe + languageName: node + linkType: hard + +"aggregate-error@npm:^3.0.0": + version: 3.1.0 + resolution: "aggregate-error@npm:3.1.0" + dependencies: + clean-stack: "npm:^2.0.0" + indent-string: "npm:^4.0.0" + checksum: 10c0/a42f67faa79e3e6687a4923050e7c9807db3848a037076f791d10e092677d65c1d2d863b7848560699f40fc0502c19f40963fb1cd1fb3d338a7423df8e45e039 + languageName: node + linkType: hard + +"ansi-align@npm:^3.0.0": + version: 3.0.1 + resolution: "ansi-align@npm:3.0.1" + dependencies: + string-width: "npm:^4.1.0" + checksum: 10c0/ad8b755a253a1bc8234eb341e0cec68a857ab18bf97ba2bda529e86f6e30460416523e0ec58c32e5c21f0ca470d779503244892873a5895dbd0c39c788e82467 + languageName: node + linkType: hard + +"ansi-colors@npm:^4.1.1, ansi-colors@npm:^4.1.3": + version: 4.1.3 + resolution: "ansi-colors@npm:4.1.3" + checksum: 10c0/ec87a2f59902f74e61eada7f6e6fe20094a628dab765cfdbd03c3477599368768cffccdb5d3bb19a1b6c99126783a143b1fee31aab729b31ffe5836c7e5e28b9 + languageName: node + linkType: hard + +"ansi-escapes@npm:^4.3.0": + version: 4.3.2 + resolution: "ansi-escapes@npm:4.3.2" + dependencies: + type-fest: "npm:^0.21.3" + checksum: 10c0/da917be01871525a3dfcf925ae2977bc59e8c513d4423368645634bf5d4ceba5401574eb705c1e92b79f7292af5a656f78c5725a4b0e1cec97c4b413705c1d50 + languageName: node + linkType: hard + +"ansi-regex@npm:^5.0.1": + version: 5.0.1 + resolution: "ansi-regex@npm:5.0.1" + checksum: 10c0/9a64bb8627b434ba9327b60c027742e5d17ac69277960d041898596271d992d4d52ba7267a63ca10232e29f6107fc8a835f6ce8d719b88c5f8493f8254813737 + languageName: node + linkType: hard + +"ansi-regex@npm:^6.0.1": + version: 6.2.2 + resolution: "ansi-regex@npm:6.2.2" + checksum: 10c0/05d4acb1d2f59ab2cf4b794339c7b168890d44dda4bf0ce01152a8da0213aca207802f930442ce8cd22d7a92f44907664aac6508904e75e038fa944d2601b30f + languageName: node + linkType: hard + +"ansi-styles@npm:^4.0.0, ansi-styles@npm:^4.1.0": + version: 4.3.0 + resolution: "ansi-styles@npm:4.3.0" + dependencies: + color-convert: "npm:^2.0.1" + checksum: 10c0/895a23929da416f2bd3de7e9cb4eabd340949328ab85ddd6e484a637d8f6820d485f53933446f5291c3b760cbc488beb8e88573dd0f9c7daf83dccc8fe81b041 + languageName: node + linkType: hard + +"ansi-styles@npm:^6.1.0": + version: 6.2.3 + resolution: "ansi-styles@npm:6.2.3" + checksum: 10c0/23b8a4ce14e18fb854693b95351e286b771d23d8844057ed2e7d083cd3e708376c3323707ec6a24365f7d7eda3ca00327fe04092e29e551499ec4c8b7bfac868 + languageName: node + linkType: hard + +"anymatch@npm:~3.1.2": + version: 3.1.3 + resolution: "anymatch@npm:3.1.3" + dependencies: + normalize-path: "npm:^3.0.0" + picomatch: "npm:^2.0.4" + checksum: 10c0/57b06ae984bc32a0d22592c87384cd88fe4511b1dd7581497831c56d41939c8a001b28e7b853e1450f2bf61992dfcaa8ae2d0d161a0a90c4fb631ef07098fbac + languageName: node + linkType: hard + +"argparse@npm:^2.0.1": + version: 2.0.1 + resolution: "argparse@npm:2.0.1" + checksum: 10c0/c5640c2d89045371c7cedd6a70212a04e360fd34d6edeae32f6952c63949e3525ea77dbec0289d8213a99bbaeab5abfa860b5c12cf88a2e6cf8106e90dd27a7e + languageName: node + linkType: hard + +"async-eventemitter@npm:0.2.4": + version: 0.2.4 + resolution: "async-eventemitter@npm:0.2.4" + dependencies: + async: "npm:^2.4.0" + checksum: 10c0/ce761d1837d454efb456bd2bd5b0db0e100f600d66d9a07a9f7772e0cfd5ad3029bb07385310bd1c7d65603735b755ba457a2f8ed47fb1314a6fe275dd69a322 + languageName: node + linkType: hard + +"async@npm:^2.4.0": + version: 2.6.4 + resolution: "async@npm:2.6.4" + dependencies: + lodash: "npm:^4.17.14" + checksum: 10c0/0ebb3273ef96513389520adc88e0d3c45e523d03653cc9b66f5c46f4239444294899bfd13d2b569e7dbfde7da2235c35cf5fd3ece9524f935d41bbe4efccdad0 + languageName: node + linkType: hard + +"available-typed-arrays@npm:^1.0.7": + version: 1.0.7 + resolution: "available-typed-arrays@npm:1.0.7" + dependencies: + possible-typed-array-names: "npm:^1.0.0" + checksum: 10c0/d07226ef4f87daa01bd0fe80f8f310982e345f372926da2e5296aecc25c41cab440916bbaa4c5e1034b453af3392f67df5961124e4b586df1e99793a1374bdb2 + languageName: node + linkType: hard + +"balanced-match@npm:^1.0.0": + version: 1.0.2 + resolution: "balanced-match@npm:1.0.2" + checksum: 10c0/9308baf0a7e4838a82bbfd11e01b1cb0f0cf2893bc1676c27c2a8c0e70cbae1c59120c3268517a8ae7fb6376b4639ef81ca22582611dbee4ed28df945134aaee + languageName: node + linkType: hard + +"base64-js@npm:^1.3.1": + version: 1.5.1 + resolution: "base64-js@npm:1.5.1" + checksum: 10c0/f23823513b63173a001030fae4f2dabe283b99a9d324ade3ad3d148e218134676f1ee8568c877cd79ec1c53158dcf2d2ba527a97c606618928ba99dd930102bf + languageName: node + linkType: hard + +"bignumber.js@npm:^9.3.0": + version: 9.3.0 + resolution: "bignumber.js@npm:9.3.0" + checksum: 10c0/f54a79cd6fc98552ac0510c1cd9381650870ae443bdb20ba9b98e3548188d941506ac3c22a9f9c69b2cc60da9be5700e87d3f54d2825310a8b2ae999dfd6d99d + languageName: node + linkType: hard + +"binary-extensions@npm:^2.0.0": + version: 2.3.0 + resolution: "binary-extensions@npm:2.3.0" + checksum: 10c0/75a59cafc10fb12a11d510e77110c6c7ae3f4ca22463d52487709ca7f18f69d886aa387557cc9864fbdb10153d0bdb4caacabf11541f55e89ed6e18d12ece2b5 + languageName: node + linkType: hard + +"bn.js@npm:^4.11.9": + version: 4.12.0 + resolution: "bn.js@npm:4.12.0" + checksum: 10c0/9736aaa317421b6b3ed038ff3d4491935a01419ac2d83ddcfebc5717385295fcfcf0c57311d90fe49926d0abbd7a9dbefdd8861e6129939177f7e67ebc645b21 + languageName: node + linkType: hard + +"bn.js@npm:^5.2.1": + version: 5.2.1 + resolution: "bn.js@npm:5.2.1" + checksum: 10c0/bed3d8bd34ec89dbcf9f20f88bd7d4a49c160fda3b561c7bb227501f974d3e435a48fb9b61bc3de304acab9215a3bda0803f7017ffb4d0016a0c3a740a283caa + languageName: node + linkType: hard + +"boxen@npm:^5.1.2": + version: 5.1.2 + resolution: "boxen@npm:5.1.2" + dependencies: + ansi-align: "npm:^3.0.0" + camelcase: "npm:^6.2.0" + chalk: "npm:^4.1.0" + cli-boxes: "npm:^2.2.1" + string-width: "npm:^4.2.2" + type-fest: "npm:^0.20.2" + widest-line: "npm:^3.1.0" + wrap-ansi: "npm:^7.0.0" + checksum: 10c0/71f31c2eb3dcacd5fce524ae509e0cc90421752e0bfbd0281fd3352871d106c462a0f810c85f2fdb02f3a9fab2d7a84e9718b4999384d651b76104ebe5d2c024 + languageName: node + linkType: hard + +"brace-expansion@npm:^2.0.1": + version: 2.0.1 + resolution: "brace-expansion@npm:2.0.1" + dependencies: + balanced-match: "npm:^1.0.0" + checksum: 10c0/b358f2fe060e2d7a87aa015979ecea07f3c37d4018f8d6deb5bd4c229ad3a0384fe6029bb76cd8be63c81e516ee52d1a0673edbe2023d53a5191732ae3c3e49f + languageName: node + linkType: hard + +"braces@npm:~3.0.2": + version: 3.0.3 + resolution: "braces@npm:3.0.3" + dependencies: + fill-range: "npm:^7.1.1" + checksum: 10c0/7c6dfd30c338d2997ba77500539227b9d1f85e388a5f43220865201e407e076783d0881f2d297b9f80951b4c957fcf0b51c1d2d24227631643c3f7c284b0aa04 + languageName: node + linkType: hard + +"brorand@npm:^1.1.0": + version: 1.1.0 + resolution: "brorand@npm:1.1.0" + checksum: 10c0/6f366d7c4990f82c366e3878492ba9a372a73163c09871e80d82fb4ae0d23f9f8924cb8a662330308206e6b3b76ba1d528b4601c9ef73c2166b440b2ea3b7571 + languageName: node + linkType: hard + +"browser-stdout@npm:^1.3.1": + version: 1.3.1 + resolution: "browser-stdout@npm:1.3.1" + checksum: 10c0/c40e482fd82be872b6ea7b9f7591beafbf6f5ba522fe3dade98ba1573a1c29a11101564993e4eb44e5488be8f44510af072df9a9637c739217eb155ceb639205 + languageName: node + linkType: hard + +"buffer-from@npm:^1.0.0": + version: 1.1.2 + resolution: "buffer-from@npm:1.1.2" + checksum: 10c0/124fff9d66d691a86d3b062eff4663fe437a9d9ee4b47b1b9e97f5a5d14f6d5399345db80f796827be7c95e70a8e765dd404b7c3ff3b3324f98e9b0c8826cc34 + languageName: node + linkType: hard + +"buffer@npm:^6.0.3": + version: 6.0.3 + resolution: "buffer@npm:6.0.3" + dependencies: + base64-js: "npm:^1.3.1" + ieee754: "npm:^1.2.1" + checksum: 10c0/2a905fbbcde73cc5d8bd18d1caa23715d5f83a5935867c2329f0ac06104204ba7947be098fe1317fbd8830e26090ff8e764f08cd14fefc977bb248c3487bcbd0 + languageName: node + linkType: hard + +"bufferutil@npm:4.0.5": + version: 4.0.5 + resolution: "bufferutil@npm:4.0.5" + dependencies: + node-gyp: "npm:latest" + node-gyp-build: "npm:^4.3.0" + checksum: 10c0/307d1131dbfd01b1451585931db05bc83a5a94bb3f720f9ee2d8e1ce37d39b23251bce350b06152dba003ad4fbddc804fc94b3d5ce1f70e7871c6898ce3b4f7e + languageName: node + linkType: hard + +"bufferutil@npm:4.0.7": + version: 4.0.7 + resolution: "bufferutil@npm:4.0.7" + dependencies: + node-gyp: "npm:latest" + node-gyp-build: "npm:^4.3.0" + checksum: 10c0/48d6cf98b9c227db65f0a1062b6c80e933c43dc03e0ad5f908da0e79cc87a633c215516f4d541ca9b0e09c1fb386f1bbe1fc2de913057f0201d14798d3e0c2bb + languageName: node + linkType: hard + +"bytes@npm:3.1.2": + version: 3.1.2 + resolution: "bytes@npm:3.1.2" + checksum: 10c0/76d1c43cbd602794ad8ad2ae94095cddeb1de78c5dddaa7005c51af10b0176c69971a6d88e805a90c2b6550d76636e43c40d8427a808b8645ede885de4a0358e + languageName: node + linkType: hard + +"cacache@npm:^19.0.1": + version: 19.0.1 + resolution: "cacache@npm:19.0.1" + dependencies: + "@npmcli/fs": "npm:^4.0.0" + fs-minipass: "npm:^3.0.0" + glob: "npm:^10.2.2" + lru-cache: "npm:^10.0.1" + minipass: "npm:^7.0.3" + minipass-collect: "npm:^2.0.1" + minipass-flush: "npm:^1.0.5" + minipass-pipeline: "npm:^1.2.4" + p-map: "npm:^7.0.2" + ssri: "npm:^12.0.0" + tar: "npm:^7.4.3" + unique-filename: "npm:^4.0.0" + checksum: 10c0/01f2134e1bd7d3ab68be851df96c8d63b492b1853b67f2eecb2c37bb682d37cb70bb858a16f2f0554d3c0071be6dfe21456a1ff6fa4b7eed996570d6a25ffe9c + languageName: node + linkType: hard + +"call-bind-apply-helpers@npm:^1.0.0, call-bind-apply-helpers@npm:^1.0.1, call-bind-apply-helpers@npm:^1.0.2": + version: 1.0.2 + resolution: "call-bind-apply-helpers@npm:1.0.2" + dependencies: + es-errors: "npm:^1.3.0" + function-bind: "npm:^1.1.2" + checksum: 10c0/47bd9901d57b857590431243fea704ff18078b16890a6b3e021e12d279bbf211d039155e27d7566b374d49ee1f8189344bac9833dec7a20cdec370506361c938 + languageName: node + linkType: hard + +"call-bind@npm:^1.0.8": + version: 1.0.8 + resolution: "call-bind@npm:1.0.8" + dependencies: + call-bind-apply-helpers: "npm:^1.0.0" + es-define-property: "npm:^1.0.0" + get-intrinsic: "npm:^1.2.4" + set-function-length: "npm:^1.2.2" + checksum: 10c0/a13819be0681d915144467741b69875ae5f4eba8961eb0bf322aab63ec87f8250eb6d6b0dcbb2e1349876412a56129ca338592b3829ef4343527f5f18a0752d4 + languageName: node + linkType: hard + +"call-bound@npm:^1.0.2, call-bound@npm:^1.0.3, call-bound@npm:^1.0.4": + version: 1.0.4 + resolution: "call-bound@npm:1.0.4" + dependencies: + call-bind-apply-helpers: "npm:^1.0.2" + get-intrinsic: "npm:^1.3.0" + checksum: 10c0/f4796a6a0941e71c766aea672f63b72bc61234c4f4964dc6d7606e3664c307e7d77845328a8f3359ce39ddb377fed67318f9ee203dea1d47e46165dcf2917644 + languageName: node + linkType: hard + +"camelcase@npm:^6.0.0, camelcase@npm:^6.2.0": + version: 6.3.0 + resolution: "camelcase@npm:6.3.0" + checksum: 10c0/0d701658219bd3116d12da3eab31acddb3f9440790c0792e0d398f0a520a6a4058018e546862b6fba89d7ae990efaeb97da71e1913e9ebf5a8b5621a3d55c710 + languageName: node + linkType: hard + +"catering@npm:^2.0.0, catering@npm:^2.1.0": + version: 2.1.1 + resolution: "catering@npm:2.1.1" + checksum: 10c0/a69f946f82cba85509abcb399759ed4c39d2cc9e33ba35674f242130c1b3c56673da3c3e85804db6898dfd966c395aa128ba484b31c7b906cc2faca6a581e133 + languageName: node + linkType: hard + +"chalk@npm:^4.1.0": + version: 4.1.2 + resolution: "chalk@npm:4.1.2" + dependencies: + ansi-styles: "npm:^4.1.0" + supports-color: "npm:^7.1.0" + checksum: 10c0/4a3fef5cc34975c898ffe77141450f679721df9dde00f6c304353fa9c8b571929123b26a0e4617bde5018977eb655b31970c297b91b63ee83bb82aeb04666880 + languageName: node + linkType: hard + +"chokidar@npm:^3.5.3": + version: 3.6.0 + resolution: "chokidar@npm:3.6.0" + dependencies: + anymatch: "npm:~3.1.2" + braces: "npm:~3.0.2" + fsevents: "npm:~2.3.2" + glob-parent: "npm:~5.1.2" + is-binary-path: "npm:~2.1.0" + is-glob: "npm:~4.0.1" + normalize-path: "npm:~3.0.0" + readdirp: "npm:~3.6.0" + dependenciesMeta: + fsevents: + optional: true + checksum: 10c0/8361dcd013f2ddbe260eacb1f3cb2f2c6f2b0ad118708a343a5ed8158941a39cb8fb1d272e0f389712e74ee90ce8ba864eece9e0e62b9705cb468a2f6d917462 + languageName: node + linkType: hard + +"chokidar@npm:^4.0.0": + version: 4.0.3 + resolution: "chokidar@npm:4.0.3" + dependencies: + readdirp: "npm:^4.0.1" + checksum: 10c0/a58b9df05bb452f7d105d9e7229ac82fa873741c0c40ddcc7bb82f8a909fbe3f7814c9ebe9bc9a2bef9b737c0ec6e2d699d179048ef06ad3ec46315df0ebe6ad + languageName: node + linkType: hard + +"chownr@npm:^3.0.0": + version: 3.0.0 + resolution: "chownr@npm:3.0.0" + checksum: 10c0/43925b87700f7e3893296c8e9c56cc58f926411cce3a6e5898136daaf08f08b9a8eb76d37d3267e707d0dcc17aed2e2ebdf5848c0c3ce95cf910a919935c1b10 + languageName: node + linkType: hard + +"ci-info@npm:^2.0.0": + version: 2.0.0 + resolution: "ci-info@npm:2.0.0" + checksum: 10c0/8c5fa3830a2bcee2b53c2e5018226f0141db9ec9f7b1e27a5c57db5512332cde8a0beb769bcbaf0d8775a78afbf2bb841928feca4ea6219638a5b088f9884b46 + languageName: node + linkType: hard + +"clean-stack@npm:^2.0.0": + version: 2.2.0 + resolution: "clean-stack@npm:2.2.0" + checksum: 10c0/1f90262d5f6230a17e27d0c190b09d47ebe7efdd76a03b5a1127863f7b3c9aec4c3e6c8bb3a7bbf81d553d56a1fd35728f5a8ef4c63f867ac8d690109742a8c1 + languageName: node + linkType: hard + +"cli-boxes@npm:^2.2.1": + version: 2.2.1 + resolution: "cli-boxes@npm:2.2.1" + checksum: 10c0/6111352edbb2f62dbc7bfd58f2d534de507afed7f189f13fa894ce5a48badd94b2aa502fda28f1d7dd5f1eb456e7d4033d09a76660013ef50c7f66e7a034f050 + languageName: node + linkType: hard + +"cliui@npm:^7.0.2": + version: 7.0.4 + resolution: "cliui@npm:7.0.4" + dependencies: + string-width: "npm:^4.2.0" + strip-ansi: "npm:^6.0.0" + wrap-ansi: "npm:^7.0.0" + checksum: 10c0/6035f5daf7383470cef82b3d3db00bec70afb3423538c50394386ffbbab135e26c3689c41791f911fa71b62d13d3863c712fdd70f0fbdffd938a1e6fd09aac00 + languageName: node + linkType: hard + +"color-convert@npm:^2.0.1": + version: 2.0.1 + resolution: "color-convert@npm:2.0.1" + dependencies: + color-name: "npm:~1.1.4" + checksum: 10c0/37e1150172f2e311fe1b2df62c6293a342ee7380da7b9cfdba67ea539909afbd74da27033208d01d6d5cfc65ee7868a22e18d7e7648e004425441c0f8a15a7d7 + languageName: node + linkType: hard + +"color-name@npm:~1.1.4": + version: 1.1.4 + resolution: "color-name@npm:1.1.4" + checksum: 10c0/a1a3f914156960902f46f7f56bc62effc6c94e84b2cae157a526b1c1f74b677a47ec602bf68a61abfa2b42d15b7c5651c6dbe72a43af720bc588dff885b10f95 + languageName: node + linkType: hard + +"command-exists@npm:^1.2.8": + version: 1.2.9 + resolution: "command-exists@npm:1.2.9" + checksum: 10c0/75040240062de46cd6cd43e6b3032a8b0494525c89d3962e280dde665103f8cc304a8b313a5aa541b91da2f5a9af75c5959dc3a77893a2726407a5e9a0234c16 + languageName: node + linkType: hard + +"commander@npm:^8.1.0": + version: 8.3.0 + resolution: "commander@npm:8.3.0" + checksum: 10c0/8b043bb8322ea1c39664a1598a95e0495bfe4ca2fad0d84a92d7d1d8d213e2a155b441d2470c8e08de7c4a28cf2bc6e169211c49e1b21d9f7edc6ae4d9356060 + languageName: node + linkType: hard + +"cookie@npm:^0.4.1": + version: 0.4.2 + resolution: "cookie@npm:0.4.2" + checksum: 10c0/beab41fbd7c20175e3a2799ba948c1dcc71ef69f23fe14eeeff59fc09f50c517b0f77098db87dbb4c55da802f9d86ee86cdc1cd3efd87760341551838d53fca2 + languageName: node + linkType: hard + +"crc-32@npm:^1.2.2": + version: 1.2.2 + resolution: "crc-32@npm:1.2.2" + bin: + crc32: bin/crc32.njs + checksum: 10c0/11dcf4a2e77ee793835d49f2c028838eae58b44f50d1ff08394a610bfd817523f105d6ae4d9b5bef0aad45510f633eb23c903e9902e4409bed1ce70cb82b9bf0 + languageName: node + linkType: hard + +"cross-fetch@npm:^4.0.0": + version: 4.1.0 + resolution: "cross-fetch@npm:4.1.0" + dependencies: + node-fetch: "npm:^2.7.0" + checksum: 10c0/628b134ea27cfcada67025afe6ef1419813fffc5d63d175553efa75a2334522d450300a0f3f0719029700da80e96327930709d5551cf6deb39bb62f1d536642e + languageName: node + linkType: hard + +"cross-spawn@npm:^7.0.6": + version: 7.0.6 + resolution: "cross-spawn@npm:7.0.6" + dependencies: + path-key: "npm:^3.1.0" + shebang-command: "npm:^2.0.0" + which: "npm:^2.0.1" + checksum: 10c0/053ea8b2135caff68a9e81470e845613e374e7309a47731e81639de3eaeb90c3d01af0e0b44d2ab9d50b43467223b88567dfeb3262db942dc063b9976718ffc1 + languageName: node + linkType: hard + +"debug@npm:4, debug@npm:^4.1.1, debug@npm:^4.3.5": + version: 4.4.0 + resolution: "debug@npm:4.4.0" + dependencies: + ms: "npm:^2.1.3" + peerDependenciesMeta: + supports-color: + optional: true + checksum: 10c0/db94f1a182bf886f57b4755f85b3a74c39b5114b9377b7ab375dc2cfa3454f09490cc6c30f829df3fc8042bc8b8995f6567ce5cd96f3bc3688bd24027197d9de + languageName: node + linkType: hard + +"debug@npm:^4.3.4": + version: 4.4.3 + resolution: "debug@npm:4.4.3" + dependencies: + ms: "npm:^2.1.3" + peerDependenciesMeta: + supports-color: + optional: true + checksum: 10c0/d79136ec6c83ecbefd0f6a5593da6a9c91ec4d7ddc4b54c883d6e71ec9accb5f67a1a5e96d00a328196b5b5c86d365e98d8a3a70856aaf16b4e7b1985e67f5a6 + languageName: node + linkType: hard + +"decamelize@npm:^4.0.0": + version: 4.0.0 + resolution: "decamelize@npm:4.0.0" + checksum: 10c0/e06da03fc05333e8cd2778c1487da67ffbea5b84e03ca80449519b8fa61f888714bbc6f459ea963d5641b4aa98832130eb5cd193d90ae9f0a27eee14be8e278d + languageName: node + linkType: hard + +"define-data-property@npm:^1.1.4": + version: 1.1.4 + resolution: "define-data-property@npm:1.1.4" + dependencies: + es-define-property: "npm:^1.0.0" + es-errors: "npm:^1.3.0" + gopd: "npm:^1.0.1" + checksum: 10c0/dea0606d1483eb9db8d930d4eac62ca0fa16738b0b3e07046cddfacf7d8c868bbe13fa0cb263eb91c7d0d527960dc3f2f2471a69ed7816210307f6744fe62e37 + languageName: node + linkType: hard + +"depd@npm:2.0.0": + version: 2.0.0 + resolution: "depd@npm:2.0.0" + checksum: 10c0/58bd06ec20e19529b06f7ad07ddab60e504d9e0faca4bd23079fac2d279c3594334d736508dc350e06e510aba5e22e4594483b3a6562ce7c17dd797f4cc4ad2c + languageName: node + linkType: hard + +"diff@npm:^5.2.0": + version: 5.2.0 + resolution: "diff@npm:5.2.0" + checksum: 10c0/aed0941f206fe261ecb258dc8d0ceea8abbde3ace5827518ff8d302f0fc9cc81ce116c4d8f379151171336caf0516b79e01abdc1ed1201b6440d895a66689eb4 + languageName: node + linkType: hard + +"dunder-proto@npm:^1.0.1": + version: 1.0.1 + resolution: "dunder-proto@npm:1.0.1" + dependencies: + call-bind-apply-helpers: "npm:^1.0.1" + es-errors: "npm:^1.3.0" + gopd: "npm:^1.2.0" + checksum: 10c0/199f2a0c1c16593ca0a145dbf76a962f8033ce3129f01284d48c45ed4e14fea9bbacd7b3610b6cdc33486cef20385ac054948fefc6272fcce645c09468f93031 + languageName: node + linkType: hard + +"eastasianwidth@npm:^0.2.0": + version: 0.2.0 + resolution: "eastasianwidth@npm:0.2.0" + checksum: 10c0/26f364ebcdb6395f95124fda411f63137a4bfb5d3a06453f7f23dfe52502905bd84e0488172e0f9ec295fdc45f05c23d5d91baf16bd26f0fe9acd777a188dc39 + languageName: node + linkType: hard + +"elliptic@npm:6.6.1": + version: 6.6.1 + resolution: "elliptic@npm:6.6.1" + dependencies: + bn.js: "npm:^4.11.9" + brorand: "npm:^1.1.0" + hash.js: "npm:^1.0.0" + hmac-drbg: "npm:^1.0.1" + inherits: "npm:^2.0.4" + minimalistic-assert: "npm:^1.0.1" + minimalistic-crypto-utils: "npm:^1.0.1" + checksum: 10c0/8b24ef782eec8b472053793ea1e91ae6bee41afffdfcb78a81c0a53b191e715cbe1292aa07165958a9bbe675bd0955142560b1a007ffce7d6c765bcaf951a867 + languageName: node + linkType: hard + +"elliptic@npm:^6.5.4": + version: 6.5.4 + resolution: "elliptic@npm:6.5.4" + dependencies: + bn.js: "npm:^4.11.9" + brorand: "npm:^1.1.0" + hash.js: "npm:^1.0.0" + hmac-drbg: "npm:^1.0.1" + inherits: "npm:^2.0.4" + minimalistic-assert: "npm:^1.0.1" + minimalistic-crypto-utils: "npm:^1.0.1" + checksum: 10c0/5f361270292c3b27cf0843e84526d11dec31652f03c2763c6c2b8178548175ff5eba95341dd62baff92b2265d1af076526915d8af6cc9cb7559c44a62f8ca6e2 + languageName: node + linkType: hard + +"emittery@npm:0.10.0": + version: 0.10.0 + resolution: "emittery@npm:0.10.0" + checksum: 10c0/c2ad40e5bab53094070f7cb9d1b9a26fbbba6ab4b952cf5f33b8f64032356767c80c5aec2523aa7e44940c1cdb4f125d06a9cffd489a9be65103bb8a16ce173b + languageName: node + linkType: hard + +"emoji-regex@npm:^8.0.0": + version: 8.0.0 + resolution: "emoji-regex@npm:8.0.0" + checksum: 10c0/b6053ad39951c4cf338f9092d7bfba448cdfd46fe6a2a034700b149ac9ffbc137e361cbd3c442297f86bed2e5f7576c1b54cc0a6bf8ef5106cc62f496af35010 + languageName: node + linkType: hard + +"emoji-regex@npm:^9.2.2": + version: 9.2.2 + resolution: "emoji-regex@npm:9.2.2" + checksum: 10c0/af014e759a72064cf66e6e694a7fc6b0ed3d8db680427b021a89727689671cefe9d04151b2cad51dbaf85d5ba790d061cd167f1cf32eb7b281f6368b3c181639 + languageName: node + linkType: hard + +"encoding@npm:^0.1.13": + version: 0.1.13 + resolution: "encoding@npm:0.1.13" + dependencies: + iconv-lite: "npm:^0.6.2" + checksum: 10c0/36d938712ff00fe1f4bac88b43bcffb5930c1efa57bbcdca9d67e1d9d6c57cfb1200fb01efe0f3109b2ce99b231f90779532814a81370a1bd3274a0f58585039 + languageName: node + linkType: hard + +"enquirer@npm:^2.3.0": + version: 2.4.1 + resolution: "enquirer@npm:2.4.1" + dependencies: + ansi-colors: "npm:^4.1.1" + strip-ansi: "npm:^6.0.1" + checksum: 10c0/43850479d7a51d36a9c924b518dcdc6373b5a8ae3401097d336b7b7e258324749d0ad37a1fcaa5706f04799baa05585cd7af19ebdf7667673e7694435fcea918 + languageName: node + linkType: hard + +"env-paths@npm:^2.2.0": + version: 2.2.1 + resolution: "env-paths@npm:2.2.1" + checksum: 10c0/285325677bf00e30845e330eec32894f5105529db97496ee3f598478e50f008c5352a41a30e5e72ec9de8a542b5a570b85699cd63bd2bc646dbcb9f311d83bc4 + languageName: node + linkType: hard + +"err-code@npm:^2.0.2": + version: 2.0.3 + resolution: "err-code@npm:2.0.3" + checksum: 10c0/b642f7b4dd4a376e954947550a3065a9ece6733ab8e51ad80db727aaae0817c2e99b02a97a3d6cecc648a97848305e728289cf312d09af395403a90c9d4d8a66 + languageName: node + linkType: hard + +"es-define-property@npm:^1.0.0, es-define-property@npm:^1.0.1": + version: 1.0.1 + resolution: "es-define-property@npm:1.0.1" + checksum: 10c0/3f54eb49c16c18707949ff25a1456728c883e81259f045003499efba399c08bad00deebf65cccde8c0e07908c1a225c9d472b7107e558f2a48e28d530e34527c + languageName: node + linkType: hard + +"es-errors@npm:^1.3.0": + version: 1.3.0 + resolution: "es-errors@npm:1.3.0" + checksum: 10c0/0a61325670072f98d8ae3b914edab3559b6caa980f08054a3b872052640d91da01d38df55df797fcc916389d77fc92b8d5906cf028f4db46d7e3003abecbca85 + languageName: node + linkType: hard + +"es-object-atoms@npm:^1.0.0, es-object-atoms@npm:^1.1.1": + version: 1.1.1 + resolution: "es-object-atoms@npm:1.1.1" + dependencies: + es-errors: "npm:^1.3.0" + checksum: 10c0/65364812ca4daf48eb76e2a3b7a89b3f6a2e62a1c420766ce9f692665a29d94fe41fe88b65f24106f449859549711e4b40d9fb8002d862dfd7eb1c512d10be0c + languageName: node + linkType: hard + +"esbuild@npm:~0.25.0": + version: 0.25.5 + resolution: "esbuild@npm:0.25.5" + dependencies: + "@esbuild/aix-ppc64": "npm:0.25.5" + "@esbuild/android-arm": "npm:0.25.5" + "@esbuild/android-arm64": "npm:0.25.5" + "@esbuild/android-x64": "npm:0.25.5" + "@esbuild/darwin-arm64": "npm:0.25.5" + "@esbuild/darwin-x64": "npm:0.25.5" + "@esbuild/freebsd-arm64": "npm:0.25.5" + "@esbuild/freebsd-x64": "npm:0.25.5" + "@esbuild/linux-arm": "npm:0.25.5" + "@esbuild/linux-arm64": "npm:0.25.5" + "@esbuild/linux-ia32": "npm:0.25.5" + "@esbuild/linux-loong64": "npm:0.25.5" + "@esbuild/linux-mips64el": "npm:0.25.5" + "@esbuild/linux-ppc64": "npm:0.25.5" + "@esbuild/linux-riscv64": "npm:0.25.5" + "@esbuild/linux-s390x": "npm:0.25.5" + "@esbuild/linux-x64": "npm:0.25.5" + "@esbuild/netbsd-arm64": "npm:0.25.5" + "@esbuild/netbsd-x64": "npm:0.25.5" + "@esbuild/openbsd-arm64": "npm:0.25.5" + "@esbuild/openbsd-x64": "npm:0.25.5" + "@esbuild/sunos-x64": "npm:0.25.5" + "@esbuild/win32-arm64": "npm:0.25.5" + "@esbuild/win32-ia32": "npm:0.25.5" + "@esbuild/win32-x64": "npm:0.25.5" + dependenciesMeta: + "@esbuild/aix-ppc64": + optional: true + "@esbuild/android-arm": + optional: true + "@esbuild/android-arm64": + optional: true + "@esbuild/android-x64": + optional: true + "@esbuild/darwin-arm64": + optional: true + "@esbuild/darwin-x64": + optional: true + "@esbuild/freebsd-arm64": + optional: true + "@esbuild/freebsd-x64": + optional: true + "@esbuild/linux-arm": + optional: true + "@esbuild/linux-arm64": + optional: true + "@esbuild/linux-ia32": + optional: true + "@esbuild/linux-loong64": + optional: true + "@esbuild/linux-mips64el": + optional: true + "@esbuild/linux-ppc64": + optional: true + "@esbuild/linux-riscv64": + optional: true + "@esbuild/linux-s390x": + optional: true + "@esbuild/linux-x64": + optional: true + "@esbuild/netbsd-arm64": + optional: true + "@esbuild/netbsd-x64": + optional: true + "@esbuild/openbsd-arm64": + optional: true + "@esbuild/openbsd-x64": + optional: true + "@esbuild/sunos-x64": + optional: true + "@esbuild/win32-arm64": + optional: true + "@esbuild/win32-ia32": + optional: true + "@esbuild/win32-x64": + optional: true + bin: + esbuild: bin/esbuild + checksum: 10c0/aba8cbc11927fa77562722ed5e95541ce2853f67ad7bdc40382b558abc2e0ec57d92ffb820f082ba2047b4ef9f3bc3da068cdebe30dfd3850cfa3827a78d604e + languageName: node + linkType: hard + +"escalade@npm:^3.1.1": + version: 3.2.0 + resolution: "escalade@npm:3.2.0" + checksum: 10c0/ced4dd3a78e15897ed3be74e635110bbf3b08877b0a41be50dcb325ee0e0b5f65fc2d50e9845194d7c4633f327e2e1c6cce00a71b617c5673df0374201d67f65 + languageName: node + linkType: hard + +"escape-string-regexp@npm:^4.0.0": + version: 4.0.0 + resolution: "escape-string-regexp@npm:4.0.0" + checksum: 10c0/9497d4dd307d845bd7f75180d8188bb17ea8c151c1edbf6b6717c100e104d629dc2dfb687686181b0f4b7d732c7dfdc4d5e7a8ff72de1b0ca283a75bbb3a9cd9 + languageName: node + linkType: hard + +"ethereum-cryptography@npm:^1.0.3": + version: 1.2.0 + resolution: "ethereum-cryptography@npm:1.2.0" + dependencies: + "@noble/hashes": "npm:1.2.0" + "@noble/secp256k1": "npm:1.7.1" + "@scure/bip32": "npm:1.1.5" + "@scure/bip39": "npm:1.1.1" + checksum: 10c0/93e486a4a8b266dc2f274b69252e751345ef47551163371939b01231afb7b519133e2572b5975bb9cb4cc77ac54ccd36002c7c759a72488abeeaf216e4d55b46 + languageName: node + linkType: hard + +"ethereum-cryptography@npm:^2.0.0, ethereum-cryptography@npm:^2.2.1": + version: 2.2.1 + resolution: "ethereum-cryptography@npm:2.2.1" + dependencies: + "@noble/curves": "npm:1.4.2" + "@noble/hashes": "npm:1.4.0" + "@scure/bip32": "npm:1.4.0" + "@scure/bip39": "npm:1.3.0" + checksum: 10c0/c6c7626d393980577b57f709878b2eb91f270fe56116044b1d7afb70d5c519cddc0c072e8c05e4a335e05342eb64d9c3ab39d52f78bb75f76ad70817da9645ef + languageName: node + linkType: hard + +"eventemitter3@npm:^5.0.1": + version: 5.0.1 + resolution: "eventemitter3@npm:5.0.1" + checksum: 10c0/4ba5c00c506e6c786b4d6262cfbce90ddc14c10d4667e5c83ae993c9de88aa856033994dd2b35b83e8dc1170e224e66a319fa80adc4c32adcd2379bbc75da814 + languageName: node + linkType: hard + +"exponential-backoff@npm:^3.1.1": + version: 3.1.2 + resolution: "exponential-backoff@npm:3.1.2" + checksum: 10c0/d9d3e1eafa21b78464297df91f1776f7fbaa3d5e3f7f0995648ca5b89c069d17055033817348d9f4a43d1c20b0eab84f75af6991751e839df53e4dfd6f22e844 + languageName: node + linkType: hard + +"fdir@npm:^6.4.3": + version: 6.4.3 + resolution: "fdir@npm:6.4.3" + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + checksum: 10c0/d13c10120e9625adf21d8d80481586200759928c19405a816b77dd28eaeb80e7c59c5def3e2941508045eb06d34eb47fad865ccc8bf98e6ab988bb0ed160fb6f + languageName: node + linkType: hard + +"fdir@npm:^6.5.0": + version: 6.5.0 + resolution: "fdir@npm:6.5.0" + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + checksum: 10c0/e345083c4306b3aed6cb8ec551e26c36bab5c511e99ea4576a16750ddc8d3240e63826cc624f5ae17ad4dc82e68a253213b60d556c11bfad064b7607847ed07f + languageName: node + linkType: hard + +"fill-range@npm:^7.1.1": + version: 7.1.1 + resolution: "fill-range@npm:7.1.1" + dependencies: + to-regex-range: "npm:^5.0.1" + checksum: 10c0/b75b691bbe065472f38824f694c2f7449d7f5004aa950426a2c28f0306c60db9b880c0b0e4ed819997ffb882d1da02cfcfc819bddc94d71627f5269682edf018 + languageName: node + linkType: hard + +"find-up@npm:^5.0.0": + version: 5.0.0 + resolution: "find-up@npm:5.0.0" + dependencies: + locate-path: "npm:^6.0.0" + path-exists: "npm:^4.0.0" + checksum: 10c0/062c5a83a9c02f53cdd6d175a37ecf8f87ea5bbff1fdfb828f04bfa021441bc7583e8ebc0872a4c1baab96221fb8a8a275a19809fb93fbc40bd69ec35634069a + languageName: node + linkType: hard + +"flat@npm:^5.0.2": + version: 5.0.2 + resolution: "flat@npm:5.0.2" + bin: + flat: cli.js + checksum: 10c0/f178b13482f0cd80c7fede05f4d10585b1f2fdebf26e12edc138e32d3150c6ea6482b7f12813a1091143bad52bb6d3596bca51a162257a21163c0ff438baa5fe + languageName: node + linkType: hard + +"follow-redirects@npm:^1.12.1": + version: 1.15.9 + resolution: "follow-redirects@npm:1.15.9" + peerDependenciesMeta: + debug: + optional: true + checksum: 10c0/5829165bd112c3c0e82be6c15b1a58fa9dcfaede3b3c54697a82fe4a62dd5ae5e8222956b448d2f98e331525f05d00404aba7d696de9e761ef6e42fdc780244f + languageName: node + linkType: hard + +"for-each@npm:^0.3.5": + version: 0.3.5 + resolution: "for-each@npm:0.3.5" + dependencies: + is-callable: "npm:^1.2.7" + checksum: 10c0/0e0b50f6a843a282637d43674d1fb278dda1dd85f4f99b640024cfb10b85058aac0cc781bf689d5fe50b4b7f638e91e548560723a4e76e04fe96ae35ef039cee + languageName: node + linkType: hard + +"foreground-child@npm:^3.1.0": + version: 3.3.1 + resolution: "foreground-child@npm:3.3.1" + dependencies: + cross-spawn: "npm:^7.0.6" + signal-exit: "npm:^4.0.1" + checksum: 10c0/8986e4af2430896e65bc2788d6679067294d6aee9545daefc84923a0a4b399ad9c7a3ea7bd8c0b2b80fdf4a92de4c69df3f628233ff3224260e9c1541a9e9ed3 + languageName: node + linkType: hard + +"fp-ts@npm:1.19.3": + version: 1.19.3 + resolution: "fp-ts@npm:1.19.3" + checksum: 10c0/a016cfc98ad5e61564ab2d53a5379bbb8254642b66df13ced47e8c1d8d507abf4588d8bb43530198dfe1907211d8bae8f112cab52ba0ac6ab055da9168a6e260 + languageName: node + linkType: hard + +"fp-ts@npm:^1.0.0": + version: 1.19.5 + resolution: "fp-ts@npm:1.19.5" + checksum: 10c0/2a330fa1779561307740c26a7255fdffeb1ca2d0c7448d4dc094b477b772b0c8f7da1dfc88569b6f13f6958169b63b5df7361e514535b46b2e215bbf03a3722d + languageName: node + linkType: hard + +"fs-extra@npm:^7.0.1": + version: 7.0.1 + resolution: "fs-extra@npm:7.0.1" + dependencies: + graceful-fs: "npm:^4.1.2" + jsonfile: "npm:^4.0.0" + universalify: "npm:^0.1.0" + checksum: 10c0/1943bb2150007e3739921b8d13d4109abdc3cc481e53b97b7ea7f77eda1c3c642e27ae49eac3af074e3496ea02fde30f411ef410c760c70a38b92e656e5da784 + languageName: node + linkType: hard + +"fs-minipass@npm:^3.0.0": + version: 3.0.3 + resolution: "fs-minipass@npm:3.0.3" + dependencies: + minipass: "npm:^7.0.3" + checksum: 10c0/63e80da2ff9b621e2cb1596abcb9207f1cf82b968b116ccd7b959e3323144cce7fb141462200971c38bbf2ecca51695069db45265705bed09a7cd93ae5b89f94 + languageName: node + linkType: hard + +"fs.realpath@npm:^1.0.0": + version: 1.0.0 + resolution: "fs.realpath@npm:1.0.0" + checksum: 10c0/444cf1291d997165dfd4c0d58b69f0e4782bfd9149fd72faa4fe299e68e0e93d6db941660b37dd29153bf7186672ececa3b50b7e7249477b03fdf850f287c948 + languageName: node + linkType: hard + +"fsevents@npm:~2.3.2, fsevents@npm:~2.3.3": + version: 2.3.3 + resolution: "fsevents@npm:2.3.3" + dependencies: + node-gyp: "npm:latest" + checksum: 10c0/a1f0c44595123ed717febbc478aa952e47adfc28e2092be66b8ab1635147254ca6cfe1df792a8997f22716d4cbafc73309899ff7bfac2ac3ad8cf2e4ecc3ec60 + conditions: os=darwin + languageName: node + linkType: hard + +"fsevents@patch:fsevents@npm%3A~2.3.2#optional!builtin, fsevents@patch:fsevents@npm%3A~2.3.3#optional!builtin": + version: 2.3.3 + resolution: "fsevents@patch:fsevents@npm%3A2.3.3#optional!builtin::version=2.3.3&hash=df0bf1" + dependencies: + node-gyp: "npm:latest" + conditions: os=darwin + languageName: node + linkType: hard + +"function-bind@npm:^1.1.2": + version: 1.1.2 + resolution: "function-bind@npm:1.1.2" + checksum: 10c0/d8680ee1e5fcd4c197e4ac33b2b4dce03c71f4d91717292785703db200f5c21f977c568d28061226f9b5900cbcd2c84463646134fd5337e7925e0942bc3f46d5 + languageName: node + linkType: hard + +"get-caller-file@npm:^2.0.5": + version: 2.0.5 + resolution: "get-caller-file@npm:2.0.5" + checksum: 10c0/c6c7b60271931fa752aeb92f2b47e355eac1af3a2673f47c9589e8f8a41adc74d45551c1bc57b5e66a80609f10ffb72b6f575e4370d61cc3f7f3aaff01757cde + languageName: node + linkType: hard + +"get-intrinsic@npm:^1.2.4, get-intrinsic@npm:^1.3.0": + version: 1.3.0 + resolution: "get-intrinsic@npm:1.3.0" + dependencies: + call-bind-apply-helpers: "npm:^1.0.2" + es-define-property: "npm:^1.0.1" + es-errors: "npm:^1.3.0" + es-object-atoms: "npm:^1.1.1" + function-bind: "npm:^1.1.2" + get-proto: "npm:^1.0.1" + gopd: "npm:^1.2.0" + has-symbols: "npm:^1.1.0" + hasown: "npm:^2.0.2" + math-intrinsics: "npm:^1.1.0" + checksum: 10c0/52c81808af9a8130f581e6a6a83e1ba4a9f703359e7a438d1369a5267a25412322f03dcbd7c549edaef0b6214a0630a28511d7df0130c93cfd380f4fa0b5b66a + languageName: node + linkType: hard + +"get-proto@npm:^1.0.0, get-proto@npm:^1.0.1": + version: 1.0.1 + resolution: "get-proto@npm:1.0.1" + dependencies: + dunder-proto: "npm:^1.0.1" + es-object-atoms: "npm:^1.0.0" + checksum: 10c0/9224acb44603c5526955e83510b9da41baf6ae73f7398875fba50edc5e944223a89c4a72b070fcd78beb5f7bdda58ecb6294adc28f7acfc0da05f76a2399643c + languageName: node + linkType: hard + +"get-tsconfig@npm:^4.7.5": + version: 4.10.1 + resolution: "get-tsconfig@npm:4.10.1" + dependencies: + resolve-pkg-maps: "npm:^1.0.0" + checksum: 10c0/7f8e3dabc6a49b747920a800fb88e1952fef871cdf51b79e98db48275a5de6cdaf499c55ee67df5fa6fe7ce65f0063e26de0f2e53049b408c585aa74d39ffa21 + languageName: node + linkType: hard + +"glob-parent@npm:~5.1.2": + version: 5.1.2 + resolution: "glob-parent@npm:5.1.2" + dependencies: + is-glob: "npm:^4.0.1" + checksum: 10c0/cab87638e2112bee3f839ef5f6e0765057163d39c66be8ec1602f3823da4692297ad4e972de876ea17c44d652978638d2fd583c6713d0eb6591706825020c9ee + languageName: node + linkType: hard + +"glob@npm:^10.2.2": + version: 10.4.5 + resolution: "glob@npm:10.4.5" + dependencies: + foreground-child: "npm:^3.1.0" + jackspeak: "npm:^3.1.2" + minimatch: "npm:^9.0.4" + minipass: "npm:^7.1.2" + package-json-from-dist: "npm:^1.0.0" + path-scurry: "npm:^1.11.1" + bin: + glob: dist/esm/bin.mjs + checksum: 10c0/19a9759ea77b8e3ca0a43c2f07ecddc2ad46216b786bb8f993c445aee80d345925a21e5280c7b7c6c59e860a0154b84e4b2b60321fea92cd3c56b4a7489f160e + languageName: node + linkType: hard + +"glob@npm:^8.1.0": + version: 8.1.0 + resolution: "glob@npm:8.1.0" + dependencies: + fs.realpath: "npm:^1.0.0" + inflight: "npm:^1.0.4" + inherits: "npm:2" + minimatch: "npm:^5.0.1" + once: "npm:^1.3.0" + checksum: 10c0/cb0b5cab17a59c57299376abe5646c7070f8acb89df5595b492dba3bfb43d301a46c01e5695f01154e6553168207cb60d4eaf07d3be4bc3eb9b0457c5c561d0f + languageName: node + linkType: hard + +"gopd@npm:^1.0.1, gopd@npm:^1.2.0": + version: 1.2.0 + resolution: "gopd@npm:1.2.0" + checksum: 10c0/50fff1e04ba2b7737c097358534eacadad1e68d24cccee3272e04e007bed008e68d2614f3987788428fd192a5ae3889d08fb2331417e4fc4a9ab366b2043cead + languageName: node + linkType: hard + +"graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.6": + version: 4.2.11 + resolution: "graceful-fs@npm:4.2.11" + checksum: 10c0/386d011a553e02bc594ac2ca0bd6d9e4c22d7fa8cfbfc448a6d148c59ea881b092db9dbe3547ae4b88e55f1b01f7c4a2ecc53b310c042793e63aa44cf6c257f2 + languageName: node + linkType: hard + +"hardhat@npm:^2.24.1": + version: 2.24.1 + resolution: "hardhat@npm:2.24.1" + dependencies: + "@ethereumjs/util": "npm:^9.1.0" + "@ethersproject/abi": "npm:^5.1.2" + "@nomicfoundation/edr": "npm:^0.11.0" + "@nomicfoundation/solidity-analyzer": "npm:^0.1.0" + "@sentry/node": "npm:^5.18.1" + "@types/bn.js": "npm:^5.1.0" + "@types/lru-cache": "npm:^5.1.0" + adm-zip: "npm:^0.4.16" + aggregate-error: "npm:^3.0.0" + ansi-escapes: "npm:^4.3.0" + boxen: "npm:^5.1.2" + chokidar: "npm:^4.0.0" + ci-info: "npm:^2.0.0" + debug: "npm:^4.1.1" + enquirer: "npm:^2.3.0" + env-paths: "npm:^2.2.0" + ethereum-cryptography: "npm:^1.0.3" + find-up: "npm:^5.0.0" + fp-ts: "npm:1.19.3" + fs-extra: "npm:^7.0.1" + immutable: "npm:^4.0.0-rc.12" + io-ts: "npm:1.10.4" + json-stream-stringify: "npm:^3.1.4" + keccak: "npm:^3.0.2" + lodash: "npm:^4.17.11" + micro-eth-signer: "npm:^0.14.0" + mnemonist: "npm:^0.38.0" + mocha: "npm:^10.0.0" + p-map: "npm:^4.0.0" + picocolors: "npm:^1.1.0" + raw-body: "npm:^2.4.1" + resolve: "npm:1.17.0" + semver: "npm:^6.3.0" + solc: "npm:0.8.26" + source-map-support: "npm:^0.5.13" + stacktrace-parser: "npm:^0.1.10" + tinyglobby: "npm:^0.2.6" + tsort: "npm:0.0.1" + undici: "npm:^5.14.0" + uuid: "npm:^8.3.2" + ws: "npm:^7.4.6" + peerDependencies: + ts-node: "*" + typescript: "*" + peerDependenciesMeta: + ts-node: + optional: true + typescript: + optional: true + bin: + hardhat: internal/cli/bootstrap.js + checksum: 10c0/1dc09dbfd4566c059fea04786379a981d9a86c9d6caf3c3597aaa94a0f00ecda35f01462ce2edd5e6713366858bb9080c970c65a9e6011943fbd133961446d39 + languageName: node + linkType: hard + +"has-flag@npm:^4.0.0": + version: 4.0.0 + resolution: "has-flag@npm:4.0.0" + checksum: 10c0/2e789c61b7888d66993e14e8331449e525ef42aac53c627cc53d1c3334e768bcb6abdc4f5f0de1478a25beec6f0bd62c7549058b7ac53e924040d4f301f02fd1 + languageName: node + linkType: hard + +"has-property-descriptors@npm:^1.0.2": + version: 1.0.2 + resolution: "has-property-descriptors@npm:1.0.2" + dependencies: + es-define-property: "npm:^1.0.0" + checksum: 10c0/253c1f59e80bb476cf0dde8ff5284505d90c3bdb762983c3514d36414290475fe3fd6f574929d84de2a8eec00d35cf07cb6776205ff32efd7c50719125f00236 + languageName: node + linkType: hard + +"has-symbols@npm:^1.0.3, has-symbols@npm:^1.1.0": + version: 1.1.0 + resolution: "has-symbols@npm:1.1.0" + checksum: 10c0/dde0a734b17ae51e84b10986e651c664379018d10b91b6b0e9b293eddb32f0f069688c841fb40f19e9611546130153e0a2a48fd7f512891fb000ddfa36f5a20e + languageName: node + linkType: hard + +"has-tostringtag@npm:^1.0.2": + version: 1.0.2 + resolution: "has-tostringtag@npm:1.0.2" + dependencies: + has-symbols: "npm:^1.0.3" + checksum: 10c0/a8b166462192bafe3d9b6e420a1d581d93dd867adb61be223a17a8d6dad147aa77a8be32c961bb2f27b3ef893cae8d36f564ab651f5e9b7938ae86f74027c48c + languageName: node + linkType: hard + +"hash.js@npm:1.1.7, hash.js@npm:^1.0.0, hash.js@npm:^1.0.3": + version: 1.1.7 + resolution: "hash.js@npm:1.1.7" + dependencies: + inherits: "npm:^2.0.3" + minimalistic-assert: "npm:^1.0.1" + checksum: 10c0/41ada59494eac5332cfc1ce6b7ebdd7b88a3864a6d6b08a3ea8ef261332ed60f37f10877e0c825aaa4bddebf164fbffa618286aeeec5296675e2671cbfa746c4 + languageName: node + linkType: hard + +"hasown@npm:^2.0.2": + version: 2.0.2 + resolution: "hasown@npm:2.0.2" + dependencies: + function-bind: "npm:^1.1.2" + checksum: 10c0/3769d434703b8ac66b209a4cca0737519925bbdb61dd887f93a16372b14694c63ff4e797686d87c90f08168e81082248b9b028bad60d4da9e0d1148766f56eb9 + languageName: node + linkType: hard + +"he@npm:^1.2.0": + version: 1.2.0 + resolution: "he@npm:1.2.0" + bin: + he: bin/he + checksum: 10c0/a27d478befe3c8192f006cdd0639a66798979dfa6e2125c6ac582a19a5ebfec62ad83e8382e6036170d873f46e4536a7e795bf8b95bf7c247f4cc0825ccc8c17 + languageName: node + linkType: hard + +"hmac-drbg@npm:^1.0.1": + version: 1.0.1 + resolution: "hmac-drbg@npm:1.0.1" + dependencies: + hash.js: "npm:^1.0.3" + minimalistic-assert: "npm:^1.0.0" + minimalistic-crypto-utils: "npm:^1.0.1" + checksum: 10c0/f3d9ba31b40257a573f162176ac5930109816036c59a09f901eb2ffd7e5e705c6832bedfff507957125f2086a0ab8f853c0df225642a88bf1fcaea945f20600d + languageName: node + linkType: hard + +"http-cache-semantics@npm:^4.1.1": + version: 4.2.0 + resolution: "http-cache-semantics@npm:4.2.0" + checksum: 10c0/45b66a945cf13ec2d1f29432277201313babf4a01d9e52f44b31ca923434083afeca03f18417f599c9ab3d0e7b618ceb21257542338b57c54b710463b4a53e37 + languageName: node + linkType: hard + +"http-errors@npm:2.0.0": + version: 2.0.0 + resolution: "http-errors@npm:2.0.0" + dependencies: + depd: "npm:2.0.0" + inherits: "npm:2.0.4" + setprototypeof: "npm:1.2.0" + statuses: "npm:2.0.1" + toidentifier: "npm:1.0.1" + checksum: 10c0/fc6f2715fe188d091274b5ffc8b3657bd85c63e969daa68ccb77afb05b071a4b62841acb7a21e417b5539014dff2ebf9550f0b14a9ff126f2734a7c1387f8e19 + languageName: node + linkType: hard + +"http-proxy-agent@npm:^7.0.0": + version: 7.0.2 + resolution: "http-proxy-agent@npm:7.0.2" + dependencies: + agent-base: "npm:^7.1.0" + debug: "npm:^4.3.4" + checksum: 10c0/4207b06a4580fb85dd6dff521f0abf6db517489e70863dca1a0291daa7f2d3d2d6015a57bd702af068ea5cf9f1f6ff72314f5f5b4228d299c0904135d2aef921 + languageName: node + linkType: hard + +"https-proxy-agent@npm:^5.0.0": + version: 5.0.1 + resolution: "https-proxy-agent@npm:5.0.1" + dependencies: + agent-base: "npm:6" + debug: "npm:4" + checksum: 10c0/6dd639f03434003577c62b27cafdb864784ef19b2de430d8ae2a1d45e31c4fd60719e5637b44db1a88a046934307da7089e03d6089ec3ddacc1189d8de8897d1 + languageName: node + linkType: hard + +"https-proxy-agent@npm:^7.0.1": + version: 7.0.6 + resolution: "https-proxy-agent@npm:7.0.6" + dependencies: + agent-base: "npm:^7.1.2" + debug: "npm:4" + checksum: 10c0/f729219bc735edb621fa30e6e84e60ee5d00802b8247aac0d7b79b0bd6d4b3294737a337b93b86a0bd9e68099d031858a39260c976dc14cdbba238ba1f8779ac + languageName: node + linkType: hard + +"iconv-lite@npm:0.4.24": + version: 0.4.24 + resolution: "iconv-lite@npm:0.4.24" + dependencies: + safer-buffer: "npm:>= 2.1.2 < 3" + checksum: 10c0/c6886a24cc00f2a059767440ec1bc00d334a89f250db8e0f7feb4961c8727118457e27c495ba94d082e51d3baca378726cd110aaf7ded8b9bbfd6a44760cf1d4 + languageName: node + linkType: hard + +"iconv-lite@npm:^0.6.2": + version: 0.6.3 + resolution: "iconv-lite@npm:0.6.3" + dependencies: + safer-buffer: "npm:>= 2.1.2 < 3.0.0" + checksum: 10c0/98102bc66b33fcf5ac044099d1257ba0b7ad5e3ccd3221f34dd508ab4070edff183276221684e1e0555b145fce0850c9f7d2b60a9fcac50fbb4ea0d6e845a3b1 + languageName: node + linkType: hard + +"ieee754@npm:^1.2.1": + version: 1.2.1 + resolution: "ieee754@npm:1.2.1" + checksum: 10c0/b0782ef5e0935b9f12883a2e2aa37baa75da6e66ce6515c168697b42160807d9330de9a32ec1ed73149aea02e0d822e572bca6f1e22bdcbd2149e13b050b17bb + languageName: node + linkType: hard + +"immutable@npm:^4.0.0-rc.12": + version: 4.3.7 + resolution: "immutable@npm:4.3.7" + checksum: 10c0/9b099197081b22f6433003e34929da8ecddbbdc1474cdc8aa3b7669dee4adda349c06143de22def36016d1b6de5322b043eccd7a11db1dad2ca85dad4fff5435 + languageName: node + linkType: hard + +"imurmurhash@npm:^0.1.4": + version: 0.1.4 + resolution: "imurmurhash@npm:0.1.4" + checksum: 10c0/8b51313850dd33605c6c9d3fd9638b714f4c4c40250cff658209f30d40da60f78992fb2df5dabee4acf589a6a82bbc79ad5486550754bd9ec4e3fc0d4a57d6a6 + languageName: node + linkType: hard + +"indent-string@npm:^4.0.0": + version: 4.0.0 + resolution: "indent-string@npm:4.0.0" + checksum: 10c0/1e1904ddb0cb3d6cce7cd09e27a90184908b7a5d5c21b92e232c93579d314f0b83c246ffb035493d0504b1e9147ba2c9b21df0030f48673fba0496ecd698161f + languageName: node + linkType: hard + +"inflight@npm:^1.0.4": + version: 1.0.6 + resolution: "inflight@npm:1.0.6" + dependencies: + once: "npm:^1.3.0" + wrappy: "npm:1" + checksum: 10c0/7faca22584600a9dc5b9fca2cd5feb7135ac8c935449837b315676b4c90aa4f391ec4f42240178244b5a34e8bede1948627fda392ca3191522fc46b34e985ab2 + languageName: node + linkType: hard + +"inherits@npm:2, inherits@npm:2.0.4, inherits@npm:^2.0.3, inherits@npm:^2.0.4": + version: 2.0.4 + resolution: "inherits@npm:2.0.4" + checksum: 10c0/4e531f648b29039fb7426fb94075e6545faa1eb9fe83c29f0b6d9e7263aceb4289d2d4557db0d428188eeb449cc7c5e77b0a0b2c4e248ff2a65933a0dee49ef2 + languageName: node + linkType: hard + +"io-ts@npm:1.10.4": + version: 1.10.4 + resolution: "io-ts@npm:1.10.4" + dependencies: + fp-ts: "npm:^1.0.0" + checksum: 10c0/9370988a7e17fc23c194115808168ccd1ccf7b7ebe92c39c1cc2fd91c1dc641552a5428bb04fe28c01c826fa4f230e856eb4f7d27c774a1400af3fecf2936ab5 + languageName: node + linkType: hard + +"ip-address@npm:^10.0.1": + version: 10.0.1 + resolution: "ip-address@npm:10.0.1" + checksum: 10c0/1634d79dae18394004775cb6d699dc46b7c23df6d2083164025a2b15240c1164fccde53d0e08bd5ee4fc53913d033ab6b5e395a809ad4b956a940c446e948843 + languageName: node + linkType: hard + +"is-arguments@npm:^1.0.4": + version: 1.2.0 + resolution: "is-arguments@npm:1.2.0" + dependencies: + call-bound: "npm:^1.0.2" + has-tostringtag: "npm:^1.0.2" + checksum: 10c0/6377344b31e9fcb707c6751ee89b11f132f32338e6a782ec2eac9393b0cbd32235dad93052998cda778ee058754860738341d8114910d50ada5615912bb929fc + languageName: node + linkType: hard + +"is-binary-path@npm:~2.1.0": + version: 2.1.0 + resolution: "is-binary-path@npm:2.1.0" + dependencies: + binary-extensions: "npm:^2.0.0" + checksum: 10c0/a16eaee59ae2b315ba36fad5c5dcaf8e49c3e27318f8ab8fa3cdb8772bf559c8d1ba750a589c2ccb096113bb64497084361a25960899cb6172a6925ab6123d38 + languageName: node + linkType: hard + +"is-buffer@npm:^2.0.5": + version: 2.0.5 + resolution: "is-buffer@npm:2.0.5" + checksum: 10c0/e603f6fced83cf94c53399cff3bda1a9f08e391b872b64a73793b0928be3e5f047f2bcece230edb7632eaea2acdbfcb56c23b33d8a20c820023b230f1485679a + languageName: node + linkType: hard + +"is-callable@npm:^1.2.7": + version: 1.2.7 + resolution: "is-callable@npm:1.2.7" + checksum: 10c0/ceebaeb9d92e8adee604076971dd6000d38d6afc40bb843ea8e45c5579b57671c3f3b50d7f04869618242c6cee08d1b67806a8cb8edaaaf7c0748b3720d6066f + languageName: node + linkType: hard + +"is-extglob@npm:^2.1.1": + version: 2.1.1 + resolution: "is-extglob@npm:2.1.1" + checksum: 10c0/5487da35691fbc339700bbb2730430b07777a3c21b9ebaecb3072512dfd7b4ba78ac2381a87e8d78d20ea08affb3f1971b4af629173a6bf435ff8a4c47747912 + languageName: node + linkType: hard + +"is-fullwidth-code-point@npm:^3.0.0": + version: 3.0.0 + resolution: "is-fullwidth-code-point@npm:3.0.0" + checksum: 10c0/bb11d825e049f38e04c06373a8d72782eee0205bda9d908cc550ccb3c59b99d750ff9537982e01733c1c94a58e35400661f57042158ff5e8f3e90cf936daf0fc + languageName: node + linkType: hard + +"is-generator-function@npm:^1.0.7": + version: 1.1.0 + resolution: "is-generator-function@npm:1.1.0" + dependencies: + call-bound: "npm:^1.0.3" + get-proto: "npm:^1.0.0" + has-tostringtag: "npm:^1.0.2" + safe-regex-test: "npm:^1.1.0" + checksum: 10c0/fdfa96c8087bf36fc4cd514b474ba2ff404219a4dd4cfa6cf5426404a1eed259bdcdb98f082a71029a48d01f27733e3436ecc6690129a7ec09cb0434bee03a2a + languageName: node + linkType: hard + +"is-glob@npm:^4.0.1, is-glob@npm:~4.0.1": + version: 4.0.3 + resolution: "is-glob@npm:4.0.3" + dependencies: + is-extglob: "npm:^2.1.1" + checksum: 10c0/17fb4014e22be3bbecea9b2e3a76e9e34ff645466be702f1693e8f1ee1adac84710d0be0bd9f967d6354036fd51ab7c2741d954d6e91dae6bb69714de92c197a + languageName: node + linkType: hard + +"is-number@npm:^7.0.0": + version: 7.0.0 + resolution: "is-number@npm:7.0.0" + checksum: 10c0/b4686d0d3053146095ccd45346461bc8e53b80aeb7671cc52a4de02dbbf7dc0d1d2a986e2fe4ae206984b4d34ef37e8b795ebc4f4295c978373e6575e295d811 + languageName: node + linkType: hard + +"is-plain-obj@npm:^2.1.0": + version: 2.1.0 + resolution: "is-plain-obj@npm:2.1.0" + checksum: 10c0/e5c9814cdaa627a9ad0a0964ded0e0491bfd9ace405c49a5d63c88b30a162f1512c069d5b80997893c4d0181eadc3fed02b4ab4b81059aba5620bfcdfdeb9c53 + languageName: node + linkType: hard + +"is-regex@npm:^1.2.1": + version: 1.2.1 + resolution: "is-regex@npm:1.2.1" + dependencies: + call-bound: "npm:^1.0.2" + gopd: "npm:^1.2.0" + has-tostringtag: "npm:^1.0.2" + hasown: "npm:^2.0.2" + checksum: 10c0/1d3715d2b7889932349241680032e85d0b492cfcb045acb75ffc2c3085e8d561184f1f7e84b6f8321935b4aea39bc9c6ba74ed595b57ce4881a51dfdbc214e04 + languageName: node + linkType: hard + +"is-typed-array@npm:^1.1.3": + version: 1.1.15 + resolution: "is-typed-array@npm:1.1.15" + dependencies: + which-typed-array: "npm:^1.1.16" + checksum: 10c0/415511da3669e36e002820584e264997ffe277ff136643a3126cc949197e6ca3334d0f12d084e83b1994af2e9c8141275c741cf2b7da5a2ff62dd0cac26f76c4 + languageName: node + linkType: hard + +"is-unicode-supported@npm:^0.1.0": + version: 0.1.0 + resolution: "is-unicode-supported@npm:0.1.0" + checksum: 10c0/00cbe3455c3756be68d2542c416cab888aebd5012781d6819749fefb15162ff23e38501fe681b3d751c73e8ff561ac09a5293eba6f58fdf0178462ce6dcb3453 + languageName: node + linkType: hard + +"isexe@npm:^2.0.0": + version: 2.0.0 + resolution: "isexe@npm:2.0.0" + checksum: 10c0/228cfa503fadc2c31596ab06ed6aa82c9976eec2bfd83397e7eaf06d0ccf42cd1dfd6743bf9aeb01aebd4156d009994c5f76ea898d2832c1fe342da923ca457d + languageName: node + linkType: hard + +"isexe@npm:^3.1.1": + version: 3.1.1 + resolution: "isexe@npm:3.1.1" + checksum: 10c0/9ec257654093443eb0a528a9c8cbba9c0ca7616ccb40abd6dde7202734d96bb86e4ac0d764f0f8cd965856aacbff2f4ce23e730dc19dfb41e3b0d865ca6fdcc7 + languageName: node + linkType: hard + +"isomorphic-ws@npm:^5.0.0": + version: 5.0.0 + resolution: "isomorphic-ws@npm:5.0.0" + peerDependencies: + ws: "*" + checksum: 10c0/a058ac8b5e6efe9e46252cb0bc67fd325005d7216451d1a51238bc62d7da8486f828ef017df54ddf742e0fffcbe4b1bcc2a66cc115b027ed0180334cd18df252 + languageName: node + linkType: hard + +"jackspeak@npm:^3.1.2": + version: 3.4.3 + resolution: "jackspeak@npm:3.4.3" + dependencies: + "@isaacs/cliui": "npm:^8.0.2" + "@pkgjs/parseargs": "npm:^0.11.0" + dependenciesMeta: + "@pkgjs/parseargs": + optional: true + checksum: 10c0/6acc10d139eaefdbe04d2f679e6191b3abf073f111edf10b1de5302c97ec93fffeb2fdd8681ed17f16268aa9dd4f8c588ed9d1d3bffbbfa6e8bf897cbb3149b9 + languageName: node + linkType: hard + +"js-sha3@npm:0.8.0": + version: 0.8.0 + resolution: "js-sha3@npm:0.8.0" + checksum: 10c0/43a21dc7967c871bd2c46cb1c2ae97441a97169f324e509f382d43330d8f75cf2c96dba7c806ab08a425765a9c847efdd4bffbac2d99c3a4f3de6c0218f40533 + languageName: node + linkType: hard + +"js-yaml@npm:^4.1.0": + version: 4.1.0 + resolution: "js-yaml@npm:4.1.0" + dependencies: + argparse: "npm:^2.0.1" + bin: + js-yaml: bin/js-yaml.js + checksum: 10c0/184a24b4eaacfce40ad9074c64fd42ac83cf74d8c8cd137718d456ced75051229e5061b8633c3366b8aada17945a7a356b337828c19da92b51ae62126575018f + languageName: node + linkType: hard + +"json-stream-stringify@npm:^3.1.4": + version: 3.1.6 + resolution: "json-stream-stringify@npm:3.1.6" + checksum: 10c0/cb45e65143f4634ebb2dc0732410a942eaf86f88a7938b2f6397f4c6b96a7ba936e74d4d17db48c9221f669153996362b2ff50fe8c7fed8a7548646f98ae1f58 + languageName: node + linkType: hard + +"jsonfile@npm:^4.0.0": + version: 4.0.0 + resolution: "jsonfile@npm:4.0.0" + dependencies: + graceful-fs: "npm:^4.1.6" + dependenciesMeta: + graceful-fs: + optional: true + checksum: 10c0/7dc94b628d57a66b71fb1b79510d460d662eb975b5f876d723f81549c2e9cd316d58a2ddf742b2b93a4fa6b17b2accaf1a738a0e2ea114bdfb13a32e5377e480 + languageName: node + linkType: hard + +"keccak@npm:3.0.2": + version: 3.0.2 + resolution: "keccak@npm:3.0.2" + dependencies: + node-addon-api: "npm:^2.0.0" + node-gyp: "npm:latest" + node-gyp-build: "npm:^4.2.0" + readable-stream: "npm:^3.6.0" + checksum: 10c0/f1673e0f9bab4eb8a5bd232227916c592716d3b961e14e6ab3fabcf703c896c83fdbcd230f7b4a44f076d50fb0931ec1b093a98e4b0e74680b56be123a4a93f6 + languageName: node + linkType: hard + +"keccak@npm:^3.0.2": + version: 3.0.4 + resolution: "keccak@npm:3.0.4" + dependencies: + node-addon-api: "npm:^2.0.0" + node-gyp: "npm:latest" + node-gyp-build: "npm:^4.2.0" + readable-stream: "npm:^3.6.0" + checksum: 10c0/153525c1c1f770beadb8f8897dec2f1d2dcbee11d063fe5f61957a5b236bfd3d2a111ae2727e443aa6a848df5edb98b9ef237c78d56df49087b0ca8a232ca9cd + languageName: node + linkType: hard + +"level-concat-iterator@npm:^3.0.0": + version: 3.1.0 + resolution: "level-concat-iterator@npm:3.1.0" + dependencies: + catering: "npm:^2.1.0" + checksum: 10c0/7bb1b8e991a179de2fecfd38d2c34544a139e1228cb730f3024ef11dcbd514cc89be30b02a2a81ef4e16b0c1553f604378f67302ea23868d98f055f9fa241ae4 + languageName: node + linkType: hard + +"level-supports@npm:^2.0.1": + version: 2.1.0 + resolution: "level-supports@npm:2.1.0" + checksum: 10c0/60481dd403234c64e2c01ed2aafdc75250ddd49d770f75ebef3f92a2a5b2271bf774858bfd8c47cfae3955855f9ff9dd536683d6cffb7c085cd0e57245c4c039 + languageName: node + linkType: hard + +"level-supports@npm:^4.0.0": + version: 4.0.1 + resolution: "level-supports@npm:4.0.1" + checksum: 10c0/a94aa591786845d17c9c62ad075ae33e0fce5be714baa6e16305ed14e2d3638d09e724247fa3f63951e36de57ffd168d63e159e79d03944ee648054b8c7c1684 + languageName: node + linkType: hard + +"level-transcoder@npm:^1.0.1": + version: 1.0.1 + resolution: "level-transcoder@npm:1.0.1" + dependencies: + buffer: "npm:^6.0.3" + module-error: "npm:^1.0.1" + checksum: 10c0/25936330676325f22c5143aff5c7fe3f1db156db99f9efb07a2642045c2c6ee565fcbfccbadc0600b3abf8bbe595632cacc3dd334009214069d1857daa57987e + languageName: node + linkType: hard + +"leveldown@npm:6.1.0": + version: 6.1.0 + resolution: "leveldown@npm:6.1.0" + dependencies: + abstract-leveldown: "npm:^7.2.0" + napi-macros: "npm:~2.0.0" + node-gyp: "npm:latest" + node-gyp-build: "npm:^4.3.0" + checksum: 10c0/5af0a9596baf44187a5cce5095d78b7c085d8c5a94d652ed42e7a40c60f057135d17b52ae473f9719c674e93db3941831406206f469c4e9f62987ceed92c33e1 + languageName: node + linkType: hard + +"locate-path@npm:^6.0.0": + version: 6.0.0 + resolution: "locate-path@npm:6.0.0" + dependencies: + p-locate: "npm:^5.0.0" + checksum: 10c0/d3972ab70dfe58ce620e64265f90162d247e87159b6126b01314dd67be43d50e96a50b517bce2d9452a79409c7614054c277b5232377de50416564a77ac7aad3 + languageName: node + linkType: hard + +"lodash@npm:^4.17.11, lodash@npm:^4.17.14": + version: 4.17.21 + resolution: "lodash@npm:4.17.21" + checksum: 10c0/d8cbea072bb08655bb4c989da418994b073a608dffa608b09ac04b43a791b12aeae7cd7ad919aa4c925f33b48490b5cfe6c1f71d827956071dae2e7bb3a6b74c + languageName: node + linkType: hard + +"log-symbols@npm:^4.1.0": + version: 4.1.0 + resolution: "log-symbols@npm:4.1.0" + dependencies: + chalk: "npm:^4.1.0" + is-unicode-supported: "npm:^0.1.0" + checksum: 10c0/67f445a9ffa76db1989d0fa98586e5bc2fd5247260dafb8ad93d9f0ccd5896d53fb830b0e54dade5ad838b9de2006c826831a3c528913093af20dff8bd24aca6 + languageName: node + linkType: hard + +"lru-cache@npm:^10.0.1, lru-cache@npm:^10.2.0": + version: 10.4.3 + resolution: "lru-cache@npm:10.4.3" + checksum: 10c0/ebd04fbca961e6c1d6c0af3799adcc966a1babe798f685bb84e6599266599cd95d94630b10262f5424539bc4640107e8a33aa28585374abf561d30d16f4b39fb + languageName: node + linkType: hard + +"lru_map@npm:^0.3.3": + version: 0.3.3 + resolution: "lru_map@npm:0.3.3" + checksum: 10c0/d861f14a142a4a74ebf8d3ad57f2e768a5b820db4100ae53eed1a64eb6350912332e6ebc87cb7415ad6d0cd8f3ce6d20beab9a5e6042ccb5996ea0067a220448 + languageName: node + linkType: hard + +"make-fetch-happen@npm:^14.0.3": + version: 14.0.3 + resolution: "make-fetch-happen@npm:14.0.3" + dependencies: + "@npmcli/agent": "npm:^3.0.0" + cacache: "npm:^19.0.1" + http-cache-semantics: "npm:^4.1.1" + minipass: "npm:^7.0.2" + minipass-fetch: "npm:^4.0.0" + minipass-flush: "npm:^1.0.5" + minipass-pipeline: "npm:^1.2.4" + negotiator: "npm:^1.0.0" + proc-log: "npm:^5.0.0" + promise-retry: "npm:^2.0.1" + ssri: "npm:^12.0.0" + checksum: 10c0/c40efb5e5296e7feb8e37155bde8eb70bc57d731b1f7d90e35a092fde403d7697c56fb49334d92d330d6f1ca29a98142036d6480a12681133a0a1453164cb2f0 + languageName: node + linkType: hard + +"math-intrinsics@npm:^1.1.0": + version: 1.1.0 + resolution: "math-intrinsics@npm:1.1.0" + checksum: 10c0/7579ff94e899e2f76ab64491d76cf606274c874d8f2af4a442c016bd85688927fcfca157ba6bf74b08e9439dc010b248ce05b96cc7c126a354c3bae7fcb48b7f + languageName: node + linkType: hard + +"memorystream@npm:^0.3.1": + version: 0.3.1 + resolution: "memorystream@npm:0.3.1" + checksum: 10c0/4bd164657711d9747ff5edb0508b2944414da3464b7fe21ac5c67cf35bba975c4b446a0124bd0f9a8be54cfc18faf92e92bd77563a20328b1ccf2ff04e9f39b9 + languageName: node + linkType: hard + +"micro-eth-signer@npm:^0.14.0": + version: 0.14.0 + resolution: "micro-eth-signer@npm:0.14.0" + dependencies: + "@noble/curves": "npm:~1.8.1" + "@noble/hashes": "npm:~1.7.1" + micro-packed: "npm:~0.7.2" + checksum: 10c0/62c90d54d2b97cb4eaf713c69bc4ceb5903012d0237c26f0966076cfb89c4527de68b395e1bc29e6f237152ce08f7b551fb57b332003518a1331c2c0890fb164 + languageName: node + linkType: hard + +"micro-packed@npm:~0.7.2": + version: 0.7.3 + resolution: "micro-packed@npm:0.7.3" + dependencies: + "@scure/base": "npm:~1.2.5" + checksum: 10c0/1fde48a96d8d5606d3298ff36717bf7483d6d59e2d96f50cb88727379127a4d52881f48e7e1ce0d4906b2711b1902fb04d2128576326ce4d07e171ac022a4c2d + languageName: node + linkType: hard + +"minimalistic-assert@npm:^1.0.0, minimalistic-assert@npm:^1.0.1": + version: 1.0.1 + resolution: "minimalistic-assert@npm:1.0.1" + checksum: 10c0/96730e5601cd31457f81a296f521eb56036e6f69133c0b18c13fe941109d53ad23a4204d946a0d638d7f3099482a0cec8c9bb6d642604612ce43ee536be3dddd + languageName: node + linkType: hard + +"minimalistic-crypto-utils@npm:^1.0.1": + version: 1.0.1 + resolution: "minimalistic-crypto-utils@npm:1.0.1" + checksum: 10c0/790ecec8c5c73973a4fbf2c663d911033e8494d5fb0960a4500634766ab05d6107d20af896ca2132e7031741f19888154d44b2408ada0852446705441383e9f8 + languageName: node + linkType: hard + +"minimatch@npm:^5.0.1, minimatch@npm:^5.1.6": + version: 5.1.6 + resolution: "minimatch@npm:5.1.6" + dependencies: + brace-expansion: "npm:^2.0.1" + checksum: 10c0/3defdfd230914f22a8da203747c42ee3c405c39d4d37ffda284dac5e45b7e1f6c49aa8be606509002898e73091ff2a3bbfc59c2c6c71d4660609f63aa92f98e3 + languageName: node + linkType: hard + +"minimatch@npm:^9.0.4": + version: 9.0.5 + resolution: "minimatch@npm:9.0.5" + dependencies: + brace-expansion: "npm:^2.0.1" + checksum: 10c0/de96cf5e35bdf0eab3e2c853522f98ffbe9a36c37797778d2665231ec1f20a9447a7e567cb640901f89e4daaa95ae5d70c65a9e8aa2bb0019b6facbc3c0575ed + languageName: node + linkType: hard + +"minipass-collect@npm:^2.0.1": + version: 2.0.1 + resolution: "minipass-collect@npm:2.0.1" + dependencies: + minipass: "npm:^7.0.3" + checksum: 10c0/5167e73f62bb74cc5019594709c77e6a742051a647fe9499abf03c71dca75515b7959d67a764bdc4f8b361cf897fbf25e2d9869ee039203ed45240f48b9aa06e + languageName: node + linkType: hard + +"minipass-fetch@npm:^4.0.0": + version: 4.0.1 + resolution: "minipass-fetch@npm:4.0.1" + dependencies: + encoding: "npm:^0.1.13" + minipass: "npm:^7.0.3" + minipass-sized: "npm:^1.0.3" + minizlib: "npm:^3.0.1" + dependenciesMeta: + encoding: + optional: true + checksum: 10c0/a3147b2efe8e078c9bf9d024a0059339c5a09c5b1dded6900a219c218cc8b1b78510b62dae556b507304af226b18c3f1aeb1d48660283602d5b6586c399eed5c + languageName: node + linkType: hard + +"minipass-flush@npm:^1.0.5": + version: 1.0.5 + resolution: "minipass-flush@npm:1.0.5" + dependencies: + minipass: "npm:^3.0.0" + checksum: 10c0/2a51b63feb799d2bb34669205eee7c0eaf9dce01883261a5b77410c9408aa447e478efd191b4de6fc1101e796ff5892f8443ef20d9544385819093dbb32d36bd + languageName: node + linkType: hard + +"minipass-pipeline@npm:^1.2.4": + version: 1.2.4 + resolution: "minipass-pipeline@npm:1.2.4" + dependencies: + minipass: "npm:^3.0.0" + checksum: 10c0/cbda57cea20b140b797505dc2cac71581a70b3247b84480c1fed5ca5ba46c25ecc25f68bfc9e6dcb1a6e9017dab5c7ada5eab73ad4f0a49d84e35093e0c643f2 + languageName: node + linkType: hard + +"minipass-sized@npm:^1.0.3": + version: 1.0.3 + resolution: "minipass-sized@npm:1.0.3" + dependencies: + minipass: "npm:^3.0.0" + checksum: 10c0/298f124753efdc745cfe0f2bdfdd81ba25b9f4e753ca4a2066eb17c821f25d48acea607dfc997633ee5bf7b6dfffb4eee4f2051eb168663f0b99fad2fa4829cb + languageName: node + linkType: hard + +"minipass@npm:^3.0.0": + version: 3.3.6 + resolution: "minipass@npm:3.3.6" + dependencies: + yallist: "npm:^4.0.0" + checksum: 10c0/a114746943afa1dbbca8249e706d1d38b85ed1298b530f5808ce51f8e9e941962e2a5ad2e00eae7dd21d8a4aae6586a66d4216d1a259385e9d0358f0c1eba16c + languageName: node + linkType: hard + +"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.0.4, minipass@npm:^7.1.2": + version: 7.1.2 + resolution: "minipass@npm:7.1.2" + checksum: 10c0/b0fd20bb9fb56e5fa9a8bfac539e8915ae07430a619e4b86ff71f5fc757ef3924b23b2c4230393af1eda647ed3d75739e4e0acb250a6b1eb277cf7f8fe449557 + languageName: node + linkType: hard + +"minizlib@npm:^3.0.1": + version: 3.0.2 + resolution: "minizlib@npm:3.0.2" + dependencies: + minipass: "npm:^7.1.2" + checksum: 10c0/9f3bd35e41d40d02469cb30470c55ccc21cae0db40e08d1d0b1dff01cc8cc89a6f78e9c5d2b7c844e485ec0a8abc2238111213fdc5b2038e6d1012eacf316f78 + languageName: node + linkType: hard + +"mkdirp@npm:^3.0.1": + version: 3.0.1 + resolution: "mkdirp@npm:3.0.1" + bin: + mkdirp: dist/cjs/src/bin.js + checksum: 10c0/9f2b975e9246351f5e3a40dcfac99fcd0baa31fbfab615fe059fb11e51f10e4803c63de1f384c54d656e4db31d000e4767e9ef076a22e12a641357602e31d57d + languageName: node + linkType: hard + +"mnemonist@npm:^0.38.0": + version: 0.38.5 + resolution: "mnemonist@npm:0.38.5" + dependencies: + obliterator: "npm:^2.0.0" + checksum: 10c0/a73a2718f88cd12c3b108ecc530619a1b0f2783d479c7f98e7367375102cc3a28811bab384e17eb731553dc8d7ee9d60283d694a9f676af5f306104e75027d4f + languageName: node + linkType: hard + +"mocha@npm:^10.0.0": + version: 10.8.2 + resolution: "mocha@npm:10.8.2" + dependencies: + ansi-colors: "npm:^4.1.3" + browser-stdout: "npm:^1.3.1" + chokidar: "npm:^3.5.3" + debug: "npm:^4.3.5" + diff: "npm:^5.2.0" + escape-string-regexp: "npm:^4.0.0" + find-up: "npm:^5.0.0" + glob: "npm:^8.1.0" + he: "npm:^1.2.0" + js-yaml: "npm:^4.1.0" + log-symbols: "npm:^4.1.0" + minimatch: "npm:^5.1.6" + ms: "npm:^2.1.3" + serialize-javascript: "npm:^6.0.2" + strip-json-comments: "npm:^3.1.1" + supports-color: "npm:^8.1.1" + workerpool: "npm:^6.5.1" + yargs: "npm:^16.2.0" + yargs-parser: "npm:^20.2.9" + yargs-unparser: "npm:^2.0.0" + bin: + _mocha: bin/_mocha + mocha: bin/mocha.js + checksum: 10c0/1f786290a32a1c234f66afe2bfcc68aa50fe9c7356506bd39cca267efb0b4714a63a0cb333815578d63785ba2fba058bf576c2512db73997c0cae0d659a88beb + languageName: node + linkType: hard + +"module-error@npm:^1.0.1": + version: 1.0.2 + resolution: "module-error@npm:1.0.2" + checksum: 10c0/584a43a1bb2720c6c6c771e257a308af4f042a17c17b1472a2c855130a1ad93ba516a82ae7ac2ce2d03062e521cc53c03ec0ce153795d895312d7747fb3bb99b + languageName: node + linkType: hard + +"ms@npm:^2.1.3": + version: 2.1.3 + resolution: "ms@npm:2.1.3" + checksum: 10c0/d924b57e7312b3b63ad21fc5b3dc0af5e78d61a1fc7cfb5457edaf26326bf62be5307cc87ffb6862ef1c2b33b0233cdb5d4f01c4c958cc0d660948b65a287a48 + languageName: node + linkType: hard + +"napi-macros@npm:~2.0.0": + version: 2.0.0 + resolution: "napi-macros@npm:2.0.0" + checksum: 10c0/583ef5084b43e49a12488cdcd4c5142f11e114e249b359161579b64f06776ed523c209d96e4ee2689e2e824c92445d0f529d817cc153f7cec549210296ec4be6 + languageName: node + linkType: hard + +"negotiator@npm:^1.0.0": + version: 1.0.0 + resolution: "negotiator@npm:1.0.0" + checksum: 10c0/4c559dd52669ea48e1914f9d634227c561221dd54734070791f999c52ed0ff36e437b2e07d5c1f6e32909fc625fe46491c16e4a8f0572567d4dd15c3a4fda04b + languageName: node + linkType: hard + +"node-addon-api@npm:^2.0.0": + version: 2.0.2 + resolution: "node-addon-api@npm:2.0.2" + dependencies: + node-gyp: "npm:latest" + checksum: 10c0/ade6c097ba829fa4aee1ca340117bb7f8f29fdae7b777e343a9d5cbd548481d1f0894b7b907d23ce615c70d932e8f96154caed95c3fa935cfe8cf87546510f64 + languageName: node + linkType: hard + +"node-fetch@npm:^2.7.0": + version: 2.7.0 + resolution: "node-fetch@npm:2.7.0" + dependencies: + whatwg-url: "npm:^5.0.0" + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + checksum: 10c0/b55786b6028208e6fbe594ccccc213cab67a72899c9234eb59dba51062a299ea853210fcf526998eaa2867b0963ad72338824450905679ff0fa304b8c5093ae8 + languageName: node + linkType: hard + +"node-gyp-build@npm:4.4.0": + version: 4.4.0 + resolution: "node-gyp-build@npm:4.4.0" + bin: + node-gyp-build: bin.js + node-gyp-build-optional: optional.js + node-gyp-build-test: build-test.js + checksum: 10c0/11bbec933352004c6a754c9d2e3ac7ad02a09750cd06800fdcfdf111638bd897767ab94b7ed386ceaa155bb195ca8404037d7e79c2cbe7e9cd38ec74e5f5b5d2 + languageName: node + linkType: hard + +"node-gyp-build@npm:^4.2.0, node-gyp-build@npm:^4.3.0": + version: 4.8.0 + resolution: "node-gyp-build@npm:4.8.0" + bin: + node-gyp-build: bin.js + node-gyp-build-optional: optional.js + node-gyp-build-test: build-test.js + checksum: 10c0/85324be16f81f0235cbbc42e3eceaeb1b5ab94c8d8f5236755e1435b4908338c65a4e75f66ee343cbcb44ddf9b52a428755bec16dcd983295be4458d95c8e1ad + languageName: node + linkType: hard + +"node-gyp@npm:latest": + version: 11.4.2 + resolution: "node-gyp@npm:11.4.2" + dependencies: + env-paths: "npm:^2.2.0" + exponential-backoff: "npm:^3.1.1" + graceful-fs: "npm:^4.2.6" + make-fetch-happen: "npm:^14.0.3" + nopt: "npm:^8.0.0" + proc-log: "npm:^5.0.0" + semver: "npm:^7.3.5" + tar: "npm:^7.4.3" + tinyglobby: "npm:^0.2.12" + which: "npm:^5.0.0" + bin: + node-gyp: bin/node-gyp.js + checksum: 10c0/0bfd3e96770ed70f07798d881dd37b4267708966d868a0e585986baac487d9cf5831285579fd629a83dc4e434f53e6416ce301097f2ee464cb74d377e4d8bdbe + languageName: node + linkType: hard + +"nopt@npm:^8.0.0": + version: 8.1.0 + resolution: "nopt@npm:8.1.0" + dependencies: + abbrev: "npm:^3.0.0" + bin: + nopt: bin/nopt.js + checksum: 10c0/62e9ea70c7a3eb91d162d2c706b6606c041e4e7b547cbbb48f8b3695af457dd6479904d7ace600856bf923dd8d1ed0696f06195c8c20f02ac87c1da0e1d315ef + languageName: node + linkType: hard + +"normalize-path@npm:^3.0.0, normalize-path@npm:~3.0.0": + version: 3.0.0 + resolution: "normalize-path@npm:3.0.0" + checksum: 10c0/e008c8142bcc335b5e38cf0d63cfd39d6cf2d97480af9abdbe9a439221fd4d749763bab492a8ee708ce7a194bb00c9da6d0a115018672310850489137b3da046 + languageName: node + linkType: hard + +"obliterator@npm:^2.0.0": + version: 2.0.5 + resolution: "obliterator@npm:2.0.5" + checksum: 10c0/36e67d88271c51aa6412a7d449d6c60ae6387176f94dbc557eea67456bf6ccedbcbcecdb1e56438aa4f4694f68f531b3bf2be87b019e2f69961b144bec124e70 + languageName: node + linkType: hard + +"once@npm:^1.3.0": + version: 1.4.0 + resolution: "once@npm:1.4.0" + dependencies: + wrappy: "npm:1" + checksum: 10c0/5d48aca287dfefabd756621c5dfce5c91a549a93e9fdb7b8246bc4c4790aa2ec17b34a260530474635147aeb631a2dcc8b32c613df0675f96041cbb8244517d0 + languageName: node + linkType: hard + +"os-tmpdir@npm:~1.0.2": + version: 1.0.2 + resolution: "os-tmpdir@npm:1.0.2" + checksum: 10c0/f438450224f8e2687605a8dd318f0db694b6293c5d835ae509a69e97c8de38b6994645337e5577f5001115470414638978cc49da1cdcc25106dad8738dc69990 + languageName: node + linkType: hard + +"p-limit@npm:^3.0.2": + version: 3.1.0 + resolution: "p-limit@npm:3.1.0" + dependencies: + yocto-queue: "npm:^0.1.0" + checksum: 10c0/9db675949dbdc9c3763c89e748d0ef8bdad0afbb24d49ceaf4c46c02c77d30db4e0652ed36d0a0a7a95154335fab810d95c86153105bb73b3a90448e2bb14e1a + languageName: node + linkType: hard + +"p-locate@npm:^5.0.0": + version: 5.0.0 + resolution: "p-locate@npm:5.0.0" + dependencies: + p-limit: "npm:^3.0.2" + checksum: 10c0/2290d627ab7903b8b70d11d384fee714b797f6040d9278932754a6860845c4d3190603a0772a663c8cb5a7b21d1b16acb3a6487ebcafa9773094edc3dfe6009a + languageName: node + linkType: hard + +"p-map@npm:^4.0.0": + version: 4.0.0 + resolution: "p-map@npm:4.0.0" + dependencies: + aggregate-error: "npm:^3.0.0" + checksum: 10c0/592c05bd6262c466ce269ff172bb8de7c6975afca9b50c975135b974e9bdaafbfe80e61aaaf5be6d1200ba08b30ead04b88cfa7e25ff1e3b93ab28c9f62a2c75 + languageName: node + linkType: hard + +"p-map@npm:^7.0.2": + version: 7.0.3 + resolution: "p-map@npm:7.0.3" + checksum: 10c0/46091610da2b38ce47bcd1d8b4835a6fa4e832848a6682cf1652bc93915770f4617afc844c10a77d1b3e56d2472bb2d5622353fa3ead01a7f42b04fc8e744a5c + languageName: node + linkType: hard + +"package-json-from-dist@npm:^1.0.0": + version: 1.0.1 + resolution: "package-json-from-dist@npm:1.0.1" + checksum: 10c0/62ba2785eb655fec084a257af34dbe24292ab74516d6aecef97ef72d4897310bc6898f6c85b5cd22770eaa1ce60d55a0230e150fb6a966e3ecd6c511e23d164b + languageName: node + linkType: hard + +"path-exists@npm:^4.0.0": + version: 4.0.0 + resolution: "path-exists@npm:4.0.0" + checksum: 10c0/8c0bd3f5238188197dc78dced15207a4716c51cc4e3624c44fc97acf69558f5ebb9a2afff486fe1b4ee148e0c133e96c5e11a9aa5c48a3006e3467da070e5e1b + languageName: node + linkType: hard + +"path-key@npm:^3.1.0": + version: 3.1.1 + resolution: "path-key@npm:3.1.1" + checksum: 10c0/748c43efd5a569c039d7a00a03b58eecd1d75f3999f5a28303d75f521288df4823bc057d8784eb72358b2895a05f29a070bc9f1f17d28226cc4e62494cc58c4c + languageName: node + linkType: hard + +"path-parse@npm:^1.0.6": + version: 1.0.7 + resolution: "path-parse@npm:1.0.7" + checksum: 10c0/11ce261f9d294cc7a58d6a574b7f1b935842355ec66fba3c3fd79e0f036462eaf07d0aa95bb74ff432f9afef97ce1926c720988c6a7451d8a584930ae7de86e1 + languageName: node + linkType: hard + +"path-scurry@npm:^1.11.1": + version: 1.11.1 + resolution: "path-scurry@npm:1.11.1" + dependencies: + lru-cache: "npm:^10.2.0" + minipass: "npm:^5.0.0 || ^6.0.2 || ^7.0.0" + checksum: 10c0/32a13711a2a505616ae1cc1b5076801e453e7aae6ac40ab55b388bb91b9d0547a52f5aaceff710ea400205f18691120d4431e520afbe4266b836fadede15872d + languageName: node + linkType: hard + +"picocolors@npm:^1.1.0": + version: 1.1.1 + resolution: "picocolors@npm:1.1.1" + checksum: 10c0/e2e3e8170ab9d7c7421969adaa7e1b31434f789afb9b3f115f6b96d91945041ac3ceb02e9ec6fe6510ff036bcc0bf91e69a1772edc0b707e12b19c0f2d6bcf58 + languageName: node + linkType: hard + +"picomatch@npm:^2.0.4, picomatch@npm:^2.2.1": + version: 2.3.1 + resolution: "picomatch@npm:2.3.1" + checksum: 10c0/26c02b8d06f03206fc2ab8d16f19960f2ff9e81a658f831ecb656d8f17d9edc799e8364b1f4a7873e89d9702dff96204be0fa26fe4181f6843f040f819dac4be + languageName: node + linkType: hard + +"picomatch@npm:^4.0.2": + version: 4.0.2 + resolution: "picomatch@npm:4.0.2" + checksum: 10c0/7c51f3ad2bb42c776f49ebf964c644958158be30d0a510efd5a395e8d49cb5acfed5b82c0c5b365523ce18e6ab85013c9ebe574f60305892ec3fa8eee8304ccc + languageName: node + linkType: hard + +"picomatch@npm:^4.0.3": + version: 4.0.3 + resolution: "picomatch@npm:4.0.3" + checksum: 10c0/9582c951e95eebee5434f59e426cddd228a7b97a0161a375aed4be244bd3fe8e3a31b846808ea14ef2c8a2527a6eeab7b3946a67d5979e81694654f939473ae2 + languageName: node + linkType: hard + +"possible-typed-array-names@npm:^1.0.0": + version: 1.1.0 + resolution: "possible-typed-array-names@npm:1.1.0" + checksum: 10c0/c810983414142071da1d644662ce4caebce890203eb2bc7bf119f37f3fe5796226e117e6cca146b521921fa6531072674174a3325066ac66fce089a53e1e5196 + languageName: node + linkType: hard + +"proc-log@npm:^5.0.0": + version: 5.0.0 + resolution: "proc-log@npm:5.0.0" + checksum: 10c0/bbe5edb944b0ad63387a1d5b1911ae93e05ce8d0f60de1035b218cdcceedfe39dbd2c697853355b70f1a090f8f58fe90da487c85216bf9671f9499d1a897e9e3 + languageName: node + linkType: hard + +"promise-retry@npm:^2.0.1": + version: 2.0.1 + resolution: "promise-retry@npm:2.0.1" + dependencies: + err-code: "npm:^2.0.2" + retry: "npm:^0.12.0" + checksum: 10c0/9c7045a1a2928094b5b9b15336dcd2a7b1c052f674550df63cc3f36cd44028e5080448175b6f6ca32b642de81150f5e7b1a98b728f15cb069f2dd60ac2616b96 + languageName: node + linkType: hard + +"queue-microtask@npm:^1.2.3": + version: 1.2.3 + resolution: "queue-microtask@npm:1.2.3" + checksum: 10c0/900a93d3cdae3acd7d16f642c29a642aea32c2026446151f0778c62ac089d4b8e6c986811076e1ae180a694cedf077d453a11b58ff0a865629a4f82ab558e102 + languageName: node + linkType: hard + +"randombytes@npm:^2.1.0": + version: 2.1.0 + resolution: "randombytes@npm:2.1.0" + dependencies: + safe-buffer: "npm:^5.1.0" + checksum: 10c0/50395efda7a8c94f5dffab564f9ff89736064d32addf0cc7e8bf5e4166f09f8ded7a0849ca6c2d2a59478f7d90f78f20d8048bca3cdf8be09d8e8a10790388f3 + languageName: node + linkType: hard + +"raw-body@npm:^2.4.1": + version: 2.5.2 + resolution: "raw-body@npm:2.5.2" + dependencies: + bytes: "npm:3.1.2" + http-errors: "npm:2.0.0" + iconv-lite: "npm:0.4.24" + unpipe: "npm:1.0.0" + checksum: 10c0/b201c4b66049369a60e766318caff5cb3cc5a900efd89bdac431463822d976ad0670912c931fdbdcf5543207daf6f6833bca57aa116e1661d2ea91e12ca692c4 + languageName: node + linkType: hard + +"readable-stream@npm:^3.6.0": + version: 3.6.2 + resolution: "readable-stream@npm:3.6.2" + dependencies: + inherits: "npm:^2.0.3" + string_decoder: "npm:^1.1.1" + util-deprecate: "npm:^1.0.1" + checksum: 10c0/e37be5c79c376fdd088a45fa31ea2e423e5d48854be7a22a58869b4e84d25047b193f6acb54f1012331e1bcd667ffb569c01b99d36b0bd59658fb33f513511b7 + languageName: node + linkType: hard + +"readdirp@npm:^4.0.1": + version: 4.1.2 + resolution: "readdirp@npm:4.1.2" + checksum: 10c0/60a14f7619dec48c9c850255cd523e2717001b0e179dc7037cfa0895da7b9e9ab07532d324bfb118d73a710887d1e35f79c495fa91582784493e085d18c72c62 + languageName: node + linkType: hard + +"readdirp@npm:~3.6.0": + version: 3.6.0 + resolution: "readdirp@npm:3.6.0" + dependencies: + picomatch: "npm:^2.2.1" + checksum: 10c0/6fa848cf63d1b82ab4e985f4cf72bd55b7dcfd8e0a376905804e48c3634b7e749170940ba77b32804d5fe93b3cc521aa95a8d7e7d725f830da6d93f3669ce66b + languageName: node + linkType: hard + +"require-directory@npm:^2.1.1": + version: 2.1.1 + resolution: "require-directory@npm:2.1.1" + checksum: 10c0/83aa76a7bc1531f68d92c75a2ca2f54f1b01463cb566cf3fbc787d0de8be30c9dbc211d1d46be3497dac5785fe296f2dd11d531945ac29730643357978966e99 + languageName: node + linkType: hard + +"resolve-pkg-maps@npm:^1.0.0": + version: 1.0.0 + resolution: "resolve-pkg-maps@npm:1.0.0" + checksum: 10c0/fb8f7bbe2ca281a73b7ef423a1cbc786fb244bd7a95cbe5c3fba25b27d327150beca8ba02f622baea65919a57e061eb5005204daa5f93ed590d9b77463a567ab + languageName: node + linkType: hard + +"resolve@npm:1.17.0": + version: 1.17.0 + resolution: "resolve@npm:1.17.0" + dependencies: + path-parse: "npm:^1.0.6" + checksum: 10c0/4e6c76cc1a7b08bff637b092ce035d7901465067915605bc5a23ac0c10fe42ec205fc209d5d5f7a5f27f37ce71d687def7f656bbb003631cd46a8374f55ec73d + languageName: node + linkType: hard + +"resolve@patch:resolve@npm%3A1.17.0#optional!builtin": + version: 1.17.0 + resolution: "resolve@patch:resolve@npm%3A1.17.0#optional!builtin::version=1.17.0&hash=c3c19d" + dependencies: + path-parse: "npm:^1.0.6" + checksum: 10c0/e072e52be3c3dbfd086761115db4a5136753e7aefc0e665e66e7307ddcd9d6b740274516055c74aee44921625e95993f03570450aa310b8d73b1c9daa056c4cd + languageName: node + linkType: hard + +"retry@npm:^0.12.0": + version: 0.12.0 + resolution: "retry@npm:0.12.0" + checksum: 10c0/59933e8501727ba13ad73ef4a04d5280b3717fd650408460c987392efe9d7be2040778ed8ebe933c5cbd63da3dcc37919c141ef8af0a54a6e4fca5a2af177bfe + languageName: node + linkType: hard + +"safe-buffer@npm:^5.1.0, safe-buffer@npm:~5.2.0": + version: 5.2.1 + resolution: "safe-buffer@npm:5.2.1" + checksum: 10c0/6501914237c0a86e9675d4e51d89ca3c21ffd6a31642efeba25ad65720bce6921c9e7e974e5be91a786b25aa058b5303285d3c15dbabf983a919f5f630d349f3 + languageName: node + linkType: hard + +"safe-regex-test@npm:^1.1.0": + version: 1.1.0 + resolution: "safe-regex-test@npm:1.1.0" + dependencies: + call-bound: "npm:^1.0.2" + es-errors: "npm:^1.3.0" + is-regex: "npm:^1.2.1" + checksum: 10c0/f2c25281bbe5d39cddbbce7f86fca5ea9b3ce3354ea6cd7c81c31b006a5a9fff4286acc5450a3b9122c56c33eba69c56b9131ad751457b2b4a585825e6a10665 + languageName: node + linkType: hard + +"safer-buffer@npm:>= 2.1.2 < 3, safer-buffer@npm:>= 2.1.2 < 3.0.0": + version: 2.1.2 + resolution: "safer-buffer@npm:2.1.2" + checksum: 10c0/7e3c8b2e88a1841c9671094bbaeebd94448111dd90a81a1f606f3f67708a6ec57763b3b47f06da09fc6054193e0e6709e77325415dc8422b04497a8070fa02d4 + languageName: node + linkType: hard + +"scripts@workspace:.": + version: 0.0.0-use.local + resolution: "scripts@workspace:." + dependencies: + "@lido-js/ganache": "npm:=7.9.2-lido" + bignumber.js: "npm:^9.3.0" + hardhat: "npm:^2.24.1" + tsx: "npm:^4.19.4" + web3: "npm:^4.16.0" + languageName: unknown + linkType: soft + +"secp256k1@npm:4.0.3": + version: 4.0.3 + resolution: "secp256k1@npm:4.0.3" + dependencies: + elliptic: "npm:^6.5.4" + node-addon-api: "npm:^2.0.0" + node-gyp: "npm:latest" + node-gyp-build: "npm:^4.2.0" + checksum: 10c0/de0a0e525a6f8eb2daf199b338f0797dbfe5392874285a145bb005a72cabacb9d42c0197d0de129a1a0f6094d2cc4504d1f87acb6a8bbfb7770d4293f252c401 + languageName: node + linkType: hard + +"semver@npm:^5.5.0": + version: 5.7.2 + resolution: "semver@npm:5.7.2" + bin: + semver: bin/semver + checksum: 10c0/e4cf10f86f168db772ae95d86ba65b3fd6c5967c94d97c708ccb463b778c2ee53b914cd7167620950fc07faf5a564e6efe903836639e512a1aa15fbc9667fa25 + languageName: node + linkType: hard + +"semver@npm:^6.3.0": + version: 6.3.1 + resolution: "semver@npm:6.3.1" + bin: + semver: bin/semver.js + checksum: 10c0/e3d79b609071caa78bcb6ce2ad81c7966a46a7431d9d58b8800cfa9cb6a63699b3899a0e4bcce36167a284578212d9ae6942b6929ba4aa5015c079a67751d42d + languageName: node + linkType: hard + +"semver@npm:^7.3.5": + version: 7.7.2 + resolution: "semver@npm:7.7.2" + bin: + semver: bin/semver.js + checksum: 10c0/aca305edfbf2383c22571cb7714f48cadc7ac95371b4b52362fb8eeffdfbc0de0669368b82b2b15978f8848f01d7114da65697e56cd8c37b0dab8c58e543f9ea + languageName: node + linkType: hard + +"serialize-javascript@npm:^6.0.2": + version: 6.0.2 + resolution: "serialize-javascript@npm:6.0.2" + dependencies: + randombytes: "npm:^2.1.0" + checksum: 10c0/2dd09ef4b65a1289ba24a788b1423a035581bef60817bea1f01eda8e3bda623f86357665fe7ac1b50f6d4f583f97db9615b3f07b2a2e8cbcb75033965f771dd2 + languageName: node + linkType: hard + +"set-function-length@npm:^1.2.2": + version: 1.2.2 + resolution: "set-function-length@npm:1.2.2" + dependencies: + define-data-property: "npm:^1.1.4" + es-errors: "npm:^1.3.0" + function-bind: "npm:^1.1.2" + get-intrinsic: "npm:^1.2.4" + gopd: "npm:^1.0.1" + has-property-descriptors: "npm:^1.0.2" + checksum: 10c0/82850e62f412a258b71e123d4ed3873fa9377c216809551192bb6769329340176f109c2eeae8c22a8d386c76739855f78e8716515c818bcaef384b51110f0f3c + languageName: node + linkType: hard + +"setimmediate@npm:^1.0.5": + version: 1.0.5 + resolution: "setimmediate@npm:1.0.5" + checksum: 10c0/5bae81bfdbfbd0ce992893286d49c9693c82b1bcc00dcaaf3a09c8f428fdeacf4190c013598b81875dfac2b08a572422db7df779a99332d0fce186d15a3e4d49 + languageName: node + linkType: hard + +"setprototypeof@npm:1.2.0": + version: 1.2.0 + resolution: "setprototypeof@npm:1.2.0" + checksum: 10c0/68733173026766fa0d9ecaeb07f0483f4c2dc70ca376b3b7c40b7cda909f94b0918f6c5ad5ce27a9160bdfb475efaa9d5e705a11d8eaae18f9835d20976028bc + languageName: node + linkType: hard + +"shebang-command@npm:^2.0.0": + version: 2.0.0 + resolution: "shebang-command@npm:2.0.0" + dependencies: + shebang-regex: "npm:^3.0.0" + checksum: 10c0/a41692e7d89a553ef21d324a5cceb5f686d1f3c040759c50aab69688634688c5c327f26f3ecf7001ebfd78c01f3c7c0a11a7c8bfd0a8bc9f6240d4f40b224e4e + languageName: node + linkType: hard + +"shebang-regex@npm:^3.0.0": + version: 3.0.0 + resolution: "shebang-regex@npm:3.0.0" + checksum: 10c0/1dbed0726dd0e1152a92696c76c7f06084eb32a90f0528d11acd764043aacf76994b2fb30aa1291a21bd019d6699164d048286309a278855ee7bec06cf6fb690 + languageName: node + linkType: hard + +"signal-exit@npm:^4.0.1": + version: 4.1.0 + resolution: "signal-exit@npm:4.1.0" + checksum: 10c0/41602dce540e46d599edba9d9860193398d135f7ff72cab629db5171516cfae628d21e7bfccde1bbfdf11c48726bc2a6d1a8fb8701125852fbfda7cf19c6aa83 + languageName: node + linkType: hard + +"smart-buffer@npm:^4.2.0": + version: 4.2.0 + resolution: "smart-buffer@npm:4.2.0" + checksum: 10c0/a16775323e1404dd43fabafe7460be13a471e021637bc7889468eb45ce6a6b207261f454e4e530a19500cc962c4cc5348583520843b363f4193cee5c00e1e539 + languageName: node + linkType: hard + +"socks-proxy-agent@npm:^8.0.3": + version: 8.0.5 + resolution: "socks-proxy-agent@npm:8.0.5" + dependencies: + agent-base: "npm:^7.1.2" + debug: "npm:^4.3.4" + socks: "npm:^2.8.3" + checksum: 10c0/5d2c6cecba6821389aabf18728325730504bf9bb1d9e342e7987a5d13badd7a98838cc9a55b8ed3cb866ad37cc23e1086f09c4d72d93105ce9dfe76330e9d2a6 + languageName: node + linkType: hard + +"socks@npm:^2.8.3": + version: 2.8.7 + resolution: "socks@npm:2.8.7" + dependencies: + ip-address: "npm:^10.0.1" + smart-buffer: "npm:^4.2.0" + checksum: 10c0/2805a43a1c4bcf9ebf6e018268d87b32b32b06fbbc1f9282573583acc155860dc361500f89c73bfbb157caa1b4ac78059eac0ef15d1811eb0ca75e0bdadbc9d2 + languageName: node + linkType: hard + +"solc@npm:0.8.26": + version: 0.8.26 + resolution: "solc@npm:0.8.26" + dependencies: + command-exists: "npm:^1.2.8" + commander: "npm:^8.1.0" + follow-redirects: "npm:^1.12.1" + js-sha3: "npm:0.8.0" + memorystream: "npm:^0.3.1" + semver: "npm:^5.5.0" + tmp: "npm:0.0.33" + bin: + solcjs: solc.js + checksum: 10c0/1eea35da99c228d0dc1d831c29f7819e7921b67824c889a5e5f2e471a2ef5856a15fabc0b5de067f5ba994fa36fb5a563361963646fe98dad58a0e4fa17c8b2d + languageName: node + linkType: hard + +"source-map-support@npm:^0.5.13": + version: 0.5.21 + resolution: "source-map-support@npm:0.5.21" + dependencies: + buffer-from: "npm:^1.0.0" + source-map: "npm:^0.6.0" + checksum: 10c0/9ee09942f415e0f721d6daad3917ec1516af746a8120bba7bb56278707a37f1eb8642bde456e98454b8a885023af81a16e646869975f06afc1a711fb90484e7d + languageName: node + linkType: hard + +"source-map@npm:^0.6.0": + version: 0.6.1 + resolution: "source-map@npm:0.6.1" + checksum: 10c0/ab55398007c5e5532957cb0beee2368529618ac0ab372d789806f5718123cc4367d57de3904b4e6a4170eb5a0b0f41373066d02ca0735a0c4d75c7d328d3e011 + languageName: node + linkType: hard + +"ssri@npm:^12.0.0": + version: 12.0.0 + resolution: "ssri@npm:12.0.0" + dependencies: + minipass: "npm:^7.0.3" + checksum: 10c0/caddd5f544b2006e88fa6b0124d8d7b28208b83c72d7672d5ade44d794525d23b540f3396108c4eb9280dcb7c01f0bef50682f5b4b2c34291f7c5e211fd1417d + languageName: node + linkType: hard + +"stacktrace-parser@npm:^0.1.10": + version: 0.1.11 + resolution: "stacktrace-parser@npm:0.1.11" + dependencies: + type-fest: "npm:^0.7.1" + checksum: 10c0/4633d9afe8cd2f6c7fb2cebdee3cc8de7fd5f6f9736645fd08c0f66872a303061ce9cc0ccf46f4216dc94a7941b56e331012398dc0024dc25e46b5eb5d4ff018 + languageName: node + linkType: hard + +"statuses@npm:2.0.1": + version: 2.0.1 + resolution: "statuses@npm:2.0.1" + checksum: 10c0/34378b207a1620a24804ce8b5d230fea0c279f00b18a7209646d5d47e419d1cc23e7cbf33a25a1e51ac38973dc2ac2e1e9c647a8e481ef365f77668d72becfd0 + languageName: node + linkType: hard + +"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^4.0.0, string-width@npm:^4.1.0, string-width@npm:^4.2.0, string-width@npm:^4.2.2": + version: 4.2.3 + resolution: "string-width@npm:4.2.3" + dependencies: + emoji-regex: "npm:^8.0.0" + is-fullwidth-code-point: "npm:^3.0.0" + strip-ansi: "npm:^6.0.1" + checksum: 10c0/1e525e92e5eae0afd7454086eed9c818ee84374bb80328fc41217ae72ff5f065ef1c9d7f72da41de40c75fa8bb3dee63d92373fd492c84260a552c636392a47b + languageName: node + linkType: hard + +"string-width@npm:^5.0.1, string-width@npm:^5.1.2": + version: 5.1.2 + resolution: "string-width@npm:5.1.2" + dependencies: + eastasianwidth: "npm:^0.2.0" + emoji-regex: "npm:^9.2.2" + strip-ansi: "npm:^7.0.1" + checksum: 10c0/ab9c4264443d35b8b923cbdd513a089a60de339216d3b0ed3be3ba57d6880e1a192b70ae17225f764d7adbf5994e9bb8df253a944736c15a0240eff553c678ca + languageName: node + linkType: hard + +"string_decoder@npm:^1.1.1": + version: 1.3.0 + resolution: "string_decoder@npm:1.3.0" + dependencies: + safe-buffer: "npm:~5.2.0" + checksum: 10c0/810614ddb030e271cd591935dcd5956b2410dd079d64ff92a1844d6b7588bf992b3e1b69b0f4d34a3e06e0bd73046ac646b5264c1987b20d0601f81ef35d731d + languageName: node + linkType: hard + +"strip-ansi-cjs@npm:strip-ansi@^6.0.1, strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1": + version: 6.0.1 + resolution: "strip-ansi@npm:6.0.1" + dependencies: + ansi-regex: "npm:^5.0.1" + checksum: 10c0/1ae5f212a126fe5b167707f716942490e3933085a5ff6c008ab97ab2f272c8025d3aa218b7bd6ab25729ca20cc81cddb252102f8751e13482a5199e873680952 + languageName: node + linkType: hard + +"strip-ansi@npm:^7.0.1": + version: 7.1.2 + resolution: "strip-ansi@npm:7.1.2" + dependencies: + ansi-regex: "npm:^6.0.1" + checksum: 10c0/0d6d7a023de33368fd042aab0bf48f4f4077abdfd60e5393e73c7c411e85e1b3a83507c11af2e656188511475776215df9ca589b4da2295c9455cc399ce1858b + languageName: node + linkType: hard + +"strip-json-comments@npm:^3.1.1": + version: 3.1.1 + resolution: "strip-json-comments@npm:3.1.1" + checksum: 10c0/9681a6257b925a7fa0f285851c0e613cc934a50661fa7bb41ca9cbbff89686bb4a0ee366e6ecedc4daafd01e83eee0720111ab294366fe7c185e935475ebcecd + languageName: node + linkType: hard + +"supports-color@npm:^7.1.0": + version: 7.2.0 + resolution: "supports-color@npm:7.2.0" + dependencies: + has-flag: "npm:^4.0.0" + checksum: 10c0/afb4c88521b8b136b5f5f95160c98dee7243dc79d5432db7efc27efb219385bbc7d9427398e43dd6cc730a0f87d5085ce1652af7efbe391327bc0a7d0f7fc124 + languageName: node + linkType: hard + +"supports-color@npm:^8.1.1": + version: 8.1.1 + resolution: "supports-color@npm:8.1.1" + dependencies: + has-flag: "npm:^4.0.0" + checksum: 10c0/ea1d3c275dd604c974670f63943ed9bd83623edc102430c05adb8efc56ba492746b6e95386e7831b872ec3807fd89dd8eb43f735195f37b5ec343e4234cc7e89 + languageName: node + linkType: hard + +"tar@npm:^7.4.3": + version: 7.4.3 + resolution: "tar@npm:7.4.3" + dependencies: + "@isaacs/fs-minipass": "npm:^4.0.0" + chownr: "npm:^3.0.0" + minipass: "npm:^7.1.2" + minizlib: "npm:^3.0.1" + mkdirp: "npm:^3.0.1" + yallist: "npm:^5.0.0" + checksum: 10c0/d4679609bb2a9b48eeaf84632b6d844128d2412b95b6de07d53d8ee8baf4ca0857c9331dfa510390a0727b550fd543d4d1a10995ad86cdf078423fbb8d99831d + languageName: node + linkType: hard + +"tinyglobby@npm:^0.2.12": + version: 0.2.15 + resolution: "tinyglobby@npm:0.2.15" + dependencies: + fdir: "npm:^6.5.0" + picomatch: "npm:^4.0.3" + checksum: 10c0/869c31490d0d88eedb8305d178d4c75e7463e820df5a9b9d388291daf93e8b1eb5de1dad1c1e139767e4269fe75f3b10d5009b2cc14db96ff98986920a186844 + languageName: node + linkType: hard + +"tinyglobby@npm:^0.2.6": + version: 0.2.12 + resolution: "tinyglobby@npm:0.2.12" + dependencies: + fdir: "npm:^6.4.3" + picomatch: "npm:^4.0.2" + checksum: 10c0/7c9be4fd3625630e262dcb19015302aad3b4ba7fc620f269313e688f2161ea8724d6cb4444baab5ef2826eb6bed72647b169a33ec8eea37501832a2526ff540f + languageName: node + linkType: hard + +"tmp@npm:0.0.33": + version: 0.0.33 + resolution: "tmp@npm:0.0.33" + dependencies: + os-tmpdir: "npm:~1.0.2" + checksum: 10c0/69863947b8c29cabad43fe0ce65cec5bb4b481d15d4b4b21e036b060b3edbf3bc7a5541de1bacb437bb3f7c4538f669752627fdf9b4aaf034cebd172ba373408 + languageName: node + linkType: hard + +"to-regex-range@npm:^5.0.1": + version: 5.0.1 + resolution: "to-regex-range@npm:5.0.1" + dependencies: + is-number: "npm:^7.0.0" + checksum: 10c0/487988b0a19c654ff3e1961b87f471702e708fa8a8dd02a298ef16da7206692e8552a0250e8b3e8759270f62e9d8314616f6da274734d3b558b1fc7b7724e892 + languageName: node + linkType: hard + +"toidentifier@npm:1.0.1": + version: 1.0.1 + resolution: "toidentifier@npm:1.0.1" + checksum: 10c0/93937279934bd66cc3270016dd8d0afec14fb7c94a05c72dc57321f8bd1fa97e5bea6d1f7c89e728d077ca31ea125b78320a616a6c6cd0e6b9cb94cb864381c1 + languageName: node + linkType: hard + +"tr46@npm:~0.0.3": + version: 0.0.3 + resolution: "tr46@npm:0.0.3" + checksum: 10c0/047cb209a6b60c742f05c9d3ace8fa510bff609995c129a37ace03476a9b12db4dbf975e74600830ef0796e18882b2381fb5fb1f6b4f96b832c374de3ab91a11 + languageName: node + linkType: hard + +"tslib@npm:^1.9.3": + version: 1.14.1 + resolution: "tslib@npm:1.14.1" + checksum: 10c0/69ae09c49eea644bc5ebe1bca4fa4cc2c82b7b3e02f43b84bd891504edf66dbc6b2ec0eef31a957042de2269139e4acff911e6d186a258fb14069cd7f6febce2 + languageName: node + linkType: hard + +"tsort@npm:0.0.1": + version: 0.0.1 + resolution: "tsort@npm:0.0.1" + checksum: 10c0/ea3d034ab341dd9282c972710496e98539408d77f1cd476ad0551a9731f40586b65ab917b39745f902bf32037a3161eee3821405f6ab15bcd2ce4cc0a52d1da6 + languageName: node + linkType: hard + +"tsx@npm:^4.19.4": + version: 4.19.4 + resolution: "tsx@npm:4.19.4" + dependencies: + esbuild: "npm:~0.25.0" + fsevents: "npm:~2.3.3" + get-tsconfig: "npm:^4.7.5" + dependenciesMeta: + fsevents: + optional: true + bin: + tsx: dist/cli.mjs + checksum: 10c0/f7b8d44362343fbde1f2ecc9832d243a450e1168dd09702a545ebe5f699aa6912e45b431a54b885466db414cceda48e5067b36d182027c43b2c02a4f99d8721e + languageName: node + linkType: hard + +"type-fest@npm:^0.20.2": + version: 0.20.2 + resolution: "type-fest@npm:0.20.2" + checksum: 10c0/dea9df45ea1f0aaa4e2d3bed3f9a0bfe9e5b2592bddb92eb1bf06e50bcf98dbb78189668cd8bc31a0511d3fc25539b4cd5c704497e53e93e2d40ca764b10bfc3 + languageName: node + linkType: hard + +"type-fest@npm:^0.21.3": + version: 0.21.3 + resolution: "type-fest@npm:0.21.3" + checksum: 10c0/902bd57bfa30d51d4779b641c2bc403cdf1371fb9c91d3c058b0133694fcfdb817aef07a47f40faf79039eecbaa39ee9d3c532deff244f3a19ce68cea71a61e8 + languageName: node + linkType: hard + +"type-fest@npm:^0.7.1": + version: 0.7.1 + resolution: "type-fest@npm:0.7.1" + checksum: 10c0/ce6b5ef806a76bf08d0daa78d65e61f24d9a0380bd1f1df36ffb61f84d14a0985c3a921923cf4b97831278cb6fa9bf1b89c751df09407e0510b14e8c081e4e0f + languageName: node + linkType: hard + +"undici-types@npm:~5.26.4": + version: 5.26.5 + resolution: "undici-types@npm:5.26.5" + checksum: 10c0/bb673d7876c2d411b6eb6c560e0c571eef4a01c1c19925175d16e3a30c4c428181fb8d7ae802a261f283e4166a0ac435e2f505743aa9e45d893f9a3df017b501 + languageName: node + linkType: hard + +"undici@npm:^5.14.0": + version: 5.28.5 + resolution: "undici@npm:5.28.5" + dependencies: + "@fastify/busboy": "npm:^2.0.0" + checksum: 10c0/4dfaa13089fe4c0758f84ec0d34b257e58608e6be3aa540f493b9864b39e3fdcd0a1ace38e434fe79db55f833aa30bcfddd8d6cbe3e0982b0dcae8ec17b65e08 + languageName: node + linkType: hard + +"unique-filename@npm:^4.0.0": + version: 4.0.0 + resolution: "unique-filename@npm:4.0.0" + dependencies: + unique-slug: "npm:^5.0.0" + checksum: 10c0/38ae681cceb1408ea0587b6b01e29b00eee3c84baee1e41fd5c16b9ed443b80fba90c40e0ba69627e30855570a34ba8b06702d4a35035d4b5e198bf5a64c9ddc + languageName: node + linkType: hard + +"unique-slug@npm:^5.0.0": + version: 5.0.0 + resolution: "unique-slug@npm:5.0.0" + dependencies: + imurmurhash: "npm:^0.1.4" + checksum: 10c0/d324c5a44887bd7e105ce800fcf7533d43f29c48757ac410afd42975de82cc38ea2035c0483f4de82d186691bf3208ef35c644f73aa2b1b20b8e651be5afd293 + languageName: node + linkType: hard + +"universalify@npm:^0.1.0": + version: 0.1.2 + resolution: "universalify@npm:0.1.2" + checksum: 10c0/e70e0339f6b36f34c9816f6bf9662372bd241714dc77508d231d08386d94f2c4aa1ba1318614f92015f40d45aae1b9075cd30bd490efbe39387b60a76ca3f045 + languageName: node + linkType: hard + +"unpipe@npm:1.0.0": + version: 1.0.0 + resolution: "unpipe@npm:1.0.0" + checksum: 10c0/193400255bd48968e5c5383730344fbb4fa114cdedfab26e329e50dd2d81b134244bb8a72c6ac1b10ab0281a58b363d06405632c9d49ca9dfd5e90cbd7d0f32c + languageName: node + linkType: hard + +"utf-8-validate@npm:5.0.7": + version: 5.0.7 + resolution: "utf-8-validate@npm:5.0.7" + dependencies: + node-gyp: "npm:latest" + node-gyp-build: "npm:^4.3.0" + checksum: 10c0/1f343467b4509a37e4d8b06be527b78869a7a950fe039f24fad9bc5951208730227789c1f22665988124762e05a2080056a6cd68ba6bec5988c16ee30bfa9737 + languageName: node + linkType: hard + +"utf-8-validate@npm:6.0.3": + version: 6.0.3 + resolution: "utf-8-validate@npm:6.0.3" + dependencies: + node-gyp: "npm:latest" + node-gyp-build: "npm:^4.3.0" + checksum: 10c0/2ca08b07f4070540b33ff15f3f0632fa30baaee8a766fff993be47b4829b4fb30fd36fdf1270336324d03f65e0936c4608ee719d862230d75311751dcfe27a83 + languageName: node + linkType: hard + +"util-deprecate@npm:^1.0.1": + version: 1.0.2 + resolution: "util-deprecate@npm:1.0.2" + checksum: 10c0/41a5bdd214df2f6c3ecf8622745e4a366c4adced864bc3c833739791aeeeb1838119af7daed4ba36428114b5c67dcda034a79c882e97e43c03e66a4dd7389942 + languageName: node + linkType: hard + +"util@npm:^0.12.5": + version: 0.12.5 + resolution: "util@npm:0.12.5" + dependencies: + inherits: "npm:^2.0.3" + is-arguments: "npm:^1.0.4" + is-generator-function: "npm:^1.0.7" + is-typed-array: "npm:^1.1.3" + which-typed-array: "npm:^1.1.2" + checksum: 10c0/c27054de2cea2229a66c09522d0fa1415fb12d861d08523a8846bf2e4cbf0079d4c3f725f09dcb87493549bcbf05f5798dce1688b53c6c17201a45759e7253f3 + languageName: node + linkType: hard + +"uuid@npm:^8.3.2": + version: 8.3.2 + resolution: "uuid@npm:8.3.2" + bin: + uuid: dist/bin/uuid + checksum: 10c0/bcbb807a917d374a49f475fae2e87fdca7da5e5530820ef53f65ba1d12131bd81a92ecf259cc7ce317cbe0f289e7d79fdfebcef9bfa3087c8c8a2fa304c9be54 + languageName: node + linkType: hard + +"web3-core@npm:^4.4.0, web3-core@npm:^4.5.0, web3-core@npm:^4.6.0, web3-core@npm:^4.7.1": + version: 4.7.1 + resolution: "web3-core@npm:4.7.1" + dependencies: + web3-errors: "npm:^1.3.1" + web3-eth-accounts: "npm:^4.3.1" + web3-eth-iban: "npm:^4.0.7" + web3-providers-http: "npm:^4.2.0" + web3-providers-ipc: "npm:^4.0.7" + web3-providers-ws: "npm:^4.0.8" + web3-types: "npm:^1.10.0" + web3-utils: "npm:^4.3.3" + web3-validator: "npm:^2.0.6" + dependenciesMeta: + web3-providers-ipc: + optional: true + checksum: 10c0/803a55d46c21dc48c2ab478686ea5a264501b97b0b4f72fe27ba978d862ec61ac406fff5bfce0528044609a8e8fffb74fc0ff06277827a62667a66ef2ce750ac + languageName: node + linkType: hard + +"web3-errors@npm:^1.1.3, web3-errors@npm:^1.2.0, web3-errors@npm:^1.3.0, web3-errors@npm:^1.3.1": + version: 1.3.1 + resolution: "web3-errors@npm:1.3.1" + dependencies: + web3-types: "npm:^1.10.0" + checksum: 10c0/b763f0ae43c5c90f0fb72a0342a0d9227b68b363ab9d0b0c2948d586379129ec31b6da070c37393213022b34ed10374d3b16b86002c1280c637d3df4d29eed2a + languageName: node + linkType: hard + +"web3-eth-abi@npm:^4.4.1": + version: 4.4.1 + resolution: "web3-eth-abi@npm:4.4.1" + dependencies: + abitype: "npm:0.7.1" + web3-errors: "npm:^1.3.1" + web3-types: "npm:^1.10.0" + web3-utils: "npm:^4.3.3" + web3-validator: "npm:^2.0.6" + checksum: 10c0/fbaf2a6ef29dc8146a562a2d19823f20deb29f802abf0a82349863cb0ae884e564f756643fa76246717f89475088175e7d93fc813c24790911422e22e18e2fda + languageName: node + linkType: hard + +"web3-eth-accounts@npm:^4.3.1": + version: 4.3.1 + resolution: "web3-eth-accounts@npm:4.3.1" + dependencies: + "@ethereumjs/rlp": "npm:^4.0.1" + crc-32: "npm:^1.2.2" + ethereum-cryptography: "npm:^2.0.0" + web3-errors: "npm:^1.3.1" + web3-types: "npm:^1.10.0" + web3-utils: "npm:^4.3.3" + web3-validator: "npm:^2.0.6" + checksum: 10c0/efde89b171d75a212f05ce04e46c247001f7b747e2995df0d90c2459c703093ae6aa853356d62b2673735dad3eca5c81df44a1836fab5f0bfc80a64845652020 + languageName: node + linkType: hard + +"web3-eth-contract@npm:^4.5.0, web3-eth-contract@npm:^4.7.2": + version: 4.7.2 + resolution: "web3-eth-contract@npm:4.7.2" + dependencies: + "@ethereumjs/rlp": "npm:^5.0.2" + web3-core: "npm:^4.7.1" + web3-errors: "npm:^1.3.1" + web3-eth: "npm:^4.11.1" + web3-eth-abi: "npm:^4.4.1" + web3-types: "npm:^1.10.0" + web3-utils: "npm:^4.3.3" + web3-validator: "npm:^2.0.6" + checksum: 10c0/c119c7fb7dc32142e13816ace5775ecaeb33d0981edbba24e0648780e75e7fd24b855fd3096b618b9ade71514886eea9f919501ababb88cacc67136f51bcd0da + languageName: node + linkType: hard + +"web3-eth-ens@npm:^4.4.0": + version: 4.4.0 + resolution: "web3-eth-ens@npm:4.4.0" + dependencies: + "@adraffy/ens-normalize": "npm:^1.8.8" + web3-core: "npm:^4.5.0" + web3-errors: "npm:^1.2.0" + web3-eth: "npm:^4.8.0" + web3-eth-contract: "npm:^4.5.0" + web3-net: "npm:^4.1.0" + web3-types: "npm:^1.7.0" + web3-utils: "npm:^4.3.0" + web3-validator: "npm:^2.0.6" + checksum: 10c0/104f8d561dce462775a8bec529de6c91dde779f0ed0afe3116b33047352733f75240a46f7a02b39bdc66439f77ee9178fcb8812f9d614b7397dde4758787ae07 + languageName: node + linkType: hard + +"web3-eth-iban@npm:^4.0.7": + version: 4.0.7 + resolution: "web3-eth-iban@npm:4.0.7" + dependencies: + web3-errors: "npm:^1.1.3" + web3-types: "npm:^1.3.0" + web3-utils: "npm:^4.0.7" + web3-validator: "npm:^2.0.3" + checksum: 10c0/f1e74106afa40a662a9f2a8095a8d9fe76bbd011dfa00fdde5d759db6b99968771bb1d4afa810ff9bb38970db7b871c21869c786ae9bb4abaa2bf8298cfc0121 + languageName: node + linkType: hard + +"web3-eth-personal@npm:^4.1.0": + version: 4.1.0 + resolution: "web3-eth-personal@npm:4.1.0" + dependencies: + web3-core: "npm:^4.6.0" + web3-eth: "npm:^4.9.0" + web3-rpc-methods: "npm:^1.3.0" + web3-types: "npm:^1.8.0" + web3-utils: "npm:^4.3.1" + web3-validator: "npm:^2.0.6" + checksum: 10c0/203f59b33c7385d3e671a0645cbfc7f8ba56ab63bd6a0de9db42ec26e597cdc9ebf2e6a30586f3c0f27f9c09aa45d9cb77255c63c02d5905b180fb75c629cf80 + languageName: node + linkType: hard + +"web3-eth@npm:^4.11.1, web3-eth@npm:^4.8.0, web3-eth@npm:^4.9.0": + version: 4.11.1 + resolution: "web3-eth@npm:4.11.1" + dependencies: + setimmediate: "npm:^1.0.5" + web3-core: "npm:^4.7.1" + web3-errors: "npm:^1.3.1" + web3-eth-abi: "npm:^4.4.1" + web3-eth-accounts: "npm:^4.3.1" + web3-net: "npm:^4.1.0" + web3-providers-ws: "npm:^4.0.8" + web3-rpc-methods: "npm:^1.3.0" + web3-types: "npm:^1.10.0" + web3-utils: "npm:^4.3.3" + web3-validator: "npm:^2.0.6" + checksum: 10c0/139b7b59fdaf31884422a2cb06deb0de6e17e960d2952d7e06ff9690ff2db43f97c63109027dd529ba0103964827e2fc8aaa8c7f351ad8889429788fddbdf44f + languageName: node + linkType: hard + +"web3-net@npm:^4.1.0": + version: 4.1.0 + resolution: "web3-net@npm:4.1.0" + dependencies: + web3-core: "npm:^4.4.0" + web3-rpc-methods: "npm:^1.3.0" + web3-types: "npm:^1.6.0" + web3-utils: "npm:^4.3.0" + checksum: 10c0/17a70d941116e8d08a65109c447897121af39c74ed0e3ef61ec9833bf268b6e527507b8c0544852d0fe9e6964fe7731117640629b5a3ca562be4115b74f60acd + languageName: node + linkType: hard + +"web3-providers-http@npm:^4.2.0": + version: 4.2.0 + resolution: "web3-providers-http@npm:4.2.0" + dependencies: + cross-fetch: "npm:^4.0.0" + web3-errors: "npm:^1.3.0" + web3-types: "npm:^1.7.0" + web3-utils: "npm:^4.3.1" + checksum: 10c0/4541552fa48bc44c49a59ffd3c7d2ed5e3bf5bad0987bde95876aed4962fd74f2b8eb3b884fa6c7c43c493eb3febcb68f6f25be9867a9436aced618a9324eff5 + languageName: node + linkType: hard + +"web3-providers-ipc@npm:^4.0.7": + version: 4.0.7 + resolution: "web3-providers-ipc@npm:4.0.7" + dependencies: + web3-errors: "npm:^1.1.3" + web3-types: "npm:^1.3.0" + web3-utils: "npm:^4.0.7" + checksum: 10c0/3eb1db6514e8d9cf8d8d9e34d215deda6b68129df276bd0854ed16f01546d53a7ae2640d4788f9947ecd94ef9d2a905dd16b4d233f48712f7b9c4d1b4ffedc86 + languageName: node + linkType: hard + +"web3-providers-ws@npm:^4.0.8": + version: 4.0.8 + resolution: "web3-providers-ws@npm:4.0.8" + dependencies: + "@types/ws": "npm:8.5.3" + isomorphic-ws: "npm:^5.0.0" + web3-errors: "npm:^1.2.0" + web3-types: "npm:^1.7.0" + web3-utils: "npm:^4.3.1" + ws: "npm:^8.17.1" + checksum: 10c0/befbcab0cc2faf3376433dd8f18a080a5ce17e4b95bc1088179fb4409eeeebd01e715568aa67879161bb996944d5be2b53e6709d2d830243159b4f0144625bfa + languageName: node + linkType: hard + +"web3-rpc-methods@npm:^1.3.0": + version: 1.3.0 + resolution: "web3-rpc-methods@npm:1.3.0" + dependencies: + web3-core: "npm:^4.4.0" + web3-types: "npm:^1.6.0" + web3-validator: "npm:^2.0.6" + checksum: 10c0/28a3350de4a94c7773860cc960ea6d8afe73dc1cc368e0c455fb6a4e054178e649f3b426992612a860924b631fc015c5b8f58d583a9b3a6cd9a19d5481d8172f + languageName: node + linkType: hard + +"web3-rpc-providers@npm:^1.0.0-rc.4": + version: 1.0.0-rc.4 + resolution: "web3-rpc-providers@npm:1.0.0-rc.4" + dependencies: + web3-errors: "npm:^1.3.1" + web3-providers-http: "npm:^4.2.0" + web3-providers-ws: "npm:^4.0.8" + web3-types: "npm:^1.10.0" + web3-utils: "npm:^4.3.3" + web3-validator: "npm:^2.0.6" + checksum: 10c0/5f74e5f3c12c06348abf73180a9b9405d6148c4db22a3c34f825fb8fb48a9793a239256d539d885479897954f853b534b012abb89c10505cf4af3e40f74e8925 + languageName: node + linkType: hard + +"web3-types@npm:^1.10.0, web3-types@npm:^1.3.0, web3-types@npm:^1.6.0, web3-types@npm:^1.7.0, web3-types@npm:^1.8.0": + version: 1.10.0 + resolution: "web3-types@npm:1.10.0" + checksum: 10c0/e7238b48f62dd03a4eda2ca6d150f0ae7d02a0bede886b36316e57ee6535ccf9965ba938afc9dcbdd807696df782eff1a29658ed03a917d92f88798cf8db2bc7 + languageName: node + linkType: hard + +"web3-utils@npm:^4.0.7, web3-utils@npm:^4.3.0, web3-utils@npm:^4.3.1, web3-utils@npm:^4.3.3": + version: 4.3.3 + resolution: "web3-utils@npm:4.3.3" + dependencies: + ethereum-cryptography: "npm:^2.0.0" + eventemitter3: "npm:^5.0.1" + web3-errors: "npm:^1.3.1" + web3-types: "npm:^1.10.0" + web3-validator: "npm:^2.0.6" + checksum: 10c0/c56040d254ac168c4c3266ac00dbef3a16e81093cc7926e53d0c619d2c354818bc04f2b0475dd18cb60e6167262154b8bfd0540683c1f4c91045791ad2667963 + languageName: node + linkType: hard + +"web3-validator@npm:^2.0.3, web3-validator@npm:^2.0.6": + version: 2.0.6 + resolution: "web3-validator@npm:2.0.6" + dependencies: + ethereum-cryptography: "npm:^2.0.0" + util: "npm:^0.12.5" + web3-errors: "npm:^1.2.0" + web3-types: "npm:^1.6.0" + zod: "npm:^3.21.4" + checksum: 10c0/28728773b9abad2531f7a4145784db56ec9ecffeb25cc9f6fe67bedeb01a1833b1a5d1a2e0f431ce4a3c8c6f13b111f35202dd8fa0829c6e2fcd68c58d1d5658 + languageName: node + linkType: hard + +"web3@npm:^4.16.0": + version: 4.16.0 + resolution: "web3@npm:4.16.0" + dependencies: + web3-core: "npm:^4.7.1" + web3-errors: "npm:^1.3.1" + web3-eth: "npm:^4.11.1" + web3-eth-abi: "npm:^4.4.1" + web3-eth-accounts: "npm:^4.3.1" + web3-eth-contract: "npm:^4.7.2" + web3-eth-ens: "npm:^4.4.0" + web3-eth-iban: "npm:^4.0.7" + web3-eth-personal: "npm:^4.1.0" + web3-net: "npm:^4.1.0" + web3-providers-http: "npm:^4.2.0" + web3-providers-ws: "npm:^4.0.8" + web3-rpc-methods: "npm:^1.3.0" + web3-rpc-providers: "npm:^1.0.0-rc.4" + web3-types: "npm:^1.10.0" + web3-utils: "npm:^4.3.3" + web3-validator: "npm:^2.0.6" + checksum: 10c0/c8a80833f5ec69d69bf30fc0c77accbb7c5a74917fa66b21d40e2f889e38d4f8723ed39264170f742807c8dc418b05b34f7bd328b576af38a8b92e1308506087 + languageName: node + linkType: hard + +"webidl-conversions@npm:^3.0.0": + version: 3.0.1 + resolution: "webidl-conversions@npm:3.0.1" + checksum: 10c0/5612d5f3e54760a797052eb4927f0ddc01383550f542ccd33d5238cfd65aeed392a45ad38364970d0a0f4fea32e1f4d231b3d8dac4a3bdd385e5cf802ae097db + languageName: node + linkType: hard + +"whatwg-url@npm:^5.0.0": + version: 5.0.0 + resolution: "whatwg-url@npm:5.0.0" + dependencies: + tr46: "npm:~0.0.3" + webidl-conversions: "npm:^3.0.0" + checksum: 10c0/1588bed84d10b72d5eec1d0faa0722ba1962f1821e7539c535558fb5398d223b0c50d8acab950b8c488b4ba69043fd833cc2697056b167d8ad46fac3995a55d5 + languageName: node + linkType: hard + +"which-typed-array@npm:^1.1.16, which-typed-array@npm:^1.1.2": + version: 1.1.19 + resolution: "which-typed-array@npm:1.1.19" + dependencies: + available-typed-arrays: "npm:^1.0.7" + call-bind: "npm:^1.0.8" + call-bound: "npm:^1.0.4" + for-each: "npm:^0.3.5" + get-proto: "npm:^1.0.1" + gopd: "npm:^1.2.0" + has-tostringtag: "npm:^1.0.2" + checksum: 10c0/702b5dc878addafe6c6300c3d0af5983b175c75fcb4f2a72dfc3dd38d93cf9e89581e4b29c854b16ea37e50a7d7fca5ae42ece5c273d8060dcd603b2404bbb3f + languageName: node + linkType: hard + +"which@npm:^2.0.1": + version: 2.0.2 + resolution: "which@npm:2.0.2" + dependencies: + isexe: "npm:^2.0.0" + bin: + node-which: ./bin/node-which + checksum: 10c0/66522872a768b60c2a65a57e8ad184e5372f5b6a9ca6d5f033d4b0dc98aff63995655a7503b9c0a2598936f532120e81dd8cc155e2e92ed662a2b9377cc4374f + languageName: node + linkType: hard + +"which@npm:^5.0.0": + version: 5.0.0 + resolution: "which@npm:5.0.0" + dependencies: + isexe: "npm:^3.1.1" + bin: + node-which: bin/which.js + checksum: 10c0/e556e4cd8b7dbf5df52408c9a9dd5ac6518c8c5267c8953f5b0564073c66ed5bf9503b14d876d0e9c7844d4db9725fb0dcf45d6e911e17e26ab363dc3965ae7b + languageName: node + linkType: hard + +"widest-line@npm:^3.1.0": + version: 3.1.0 + resolution: "widest-line@npm:3.1.0" + dependencies: + string-width: "npm:^4.0.0" + checksum: 10c0/b1e623adcfb9df35350dd7fc61295d6d4a1eaa65a406ba39c4b8360045b614af95ad10e05abf704936ed022569be438c4bfa02d6d031863c4166a238c301119f + languageName: node + linkType: hard + +"workerpool@npm:^6.5.1": + version: 6.5.1 + resolution: "workerpool@npm:6.5.1" + checksum: 10c0/58e8e969782292cb3a7bfba823f1179a7615250a0cefb4841d5166234db1880a3d0fe83a31dd8d648329ec92c2d0cd1890ad9ec9e53674bb36ca43e9753cdeac + languageName: node + linkType: hard + +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0, wrap-ansi@npm:^7.0.0": + version: 7.0.0 + resolution: "wrap-ansi@npm:7.0.0" + dependencies: + ansi-styles: "npm:^4.0.0" + string-width: "npm:^4.1.0" + strip-ansi: "npm:^6.0.0" + checksum: 10c0/d15fc12c11e4cbc4044a552129ebc75ee3f57aa9c1958373a4db0292d72282f54373b536103987a4a7594db1ef6a4f10acf92978f79b98c49306a4b58c77d4da + languageName: node + linkType: hard + +"wrap-ansi@npm:^8.1.0": + version: 8.1.0 + resolution: "wrap-ansi@npm:8.1.0" + dependencies: + ansi-styles: "npm:^6.1.0" + string-width: "npm:^5.0.1" + strip-ansi: "npm:^7.0.1" + checksum: 10c0/138ff58a41d2f877eae87e3282c0630fc2789012fc1af4d6bd626eeb9a2f9a65ca92005e6e69a75c7b85a68479fe7443c7dbe1eb8fbaa681a4491364b7c55c60 + languageName: node + linkType: hard + +"wrappy@npm:1": + version: 1.0.2 + resolution: "wrappy@npm:1.0.2" + checksum: 10c0/56fece1a4018c6a6c8e28fbc88c87e0fbf4ea8fd64fc6c63b18f4acc4bd13e0ad2515189786dd2c30d3eec9663d70f4ecf699330002f8ccb547e4a18231fc9f0 + languageName: node + linkType: hard + +"ws@npm:8.13.0": + version: 8.13.0 + resolution: "ws@npm:8.13.0" + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ">=5.0.2" + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + checksum: 10c0/579817dbbab3ee46669129c220cfd81ba6cdb9ab5c3e9a105702dd045743c4ab72e33bb384573827c0c481213417cc880e41bc097e0fc541a0b79fa3eb38207d + languageName: node + linkType: hard + +"ws@npm:^7.4.6": + version: 7.5.10 + resolution: "ws@npm:7.5.10" + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + checksum: 10c0/bd7d5f4aaf04fae7960c23dcb6c6375d525e00f795dd20b9385902bd008c40a94d3db3ce97d878acc7573df852056ca546328b27b39f47609f80fb22a0a9b61d + languageName: node + linkType: hard + +"ws@npm:^8.17.1": + version: 8.18.2 + resolution: "ws@npm:8.18.2" + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ">=5.0.2" + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + checksum: 10c0/4b50f67931b8c6943c893f59c524f0e4905bbd183016cfb0f2b8653aa7f28dad4e456b9d99d285bbb67cca4fedd9ce90dfdfaa82b898a11414ebd66ee99141e4 + languageName: node + linkType: hard + +"y18n@npm:^5.0.5": + version: 5.0.8 + resolution: "y18n@npm:5.0.8" + checksum: 10c0/4df2842c36e468590c3691c894bc9cdbac41f520566e76e24f59401ba7d8b4811eb1e34524d57e54bc6d864bcb66baab7ffd9ca42bf1eda596618f9162b91249 + languageName: node + linkType: hard + +"yallist@npm:^4.0.0": + version: 4.0.0 + resolution: "yallist@npm:4.0.0" + checksum: 10c0/2286b5e8dbfe22204ab66e2ef5cc9bbb1e55dfc873bbe0d568aa943eb255d131890dfd5bf243637273d31119b870f49c18fcde2c6ffbb7a7a092b870dc90625a + languageName: node + linkType: hard + +"yallist@npm:^5.0.0": + version: 5.0.0 + resolution: "yallist@npm:5.0.0" + checksum: 10c0/a499c81ce6d4a1d260d4ea0f6d49ab4da09681e32c3f0472dee16667ed69d01dae63a3b81745a24bd78476ec4fcf856114cb4896ace738e01da34b2c42235416 + languageName: node + linkType: hard + +"yargs-parser@npm:^20.2.2, yargs-parser@npm:^20.2.9": + version: 20.2.9 + resolution: "yargs-parser@npm:20.2.9" + checksum: 10c0/0685a8e58bbfb57fab6aefe03c6da904a59769bd803a722bb098bd5b0f29d274a1357762c7258fb487512811b8063fb5d2824a3415a0a4540598335b3b086c72 + languageName: node + linkType: hard + +"yargs-unparser@npm:^2.0.0": + version: 2.0.0 + resolution: "yargs-unparser@npm:2.0.0" + dependencies: + camelcase: "npm:^6.0.0" + decamelize: "npm:^4.0.0" + flat: "npm:^5.0.2" + is-plain-obj: "npm:^2.1.0" + checksum: 10c0/a5a7d6dc157efa95122e16780c019f40ed91d4af6d2bac066db8194ed0ec5c330abb115daa5a79ff07a9b80b8ea80c925baacf354c4c12edd878c0529927ff03 + languageName: node + linkType: hard + +"yargs@npm:^16.2.0": + version: 16.2.0 + resolution: "yargs@npm:16.2.0" + dependencies: + cliui: "npm:^7.0.2" + escalade: "npm:^3.1.1" + get-caller-file: "npm:^2.0.5" + require-directory: "npm:^2.1.1" + string-width: "npm:^4.2.0" + y18n: "npm:^5.0.5" + yargs-parser: "npm:^20.2.2" + checksum: 10c0/b1dbfefa679848442454b60053a6c95d62f2d2e21dd28def92b647587f415969173c6e99a0f3bab4f1b67ee8283bf735ebe3544013f09491186ba9e8a9a2b651 + languageName: node + linkType: hard + +"yocto-queue@npm:^0.1.0": + version: 0.1.0 + resolution: "yocto-queue@npm:0.1.0" + checksum: 10c0/dceb44c28578b31641e13695d200d34ec4ab3966a5729814d5445b194933c096b7ced71494ce53a0e8820685d1d010df8b2422e5bf2cdea7e469d97ffbea306f + languageName: node + linkType: hard + +"zod@npm:^3.21.4": + version: 3.25.48 + resolution: "zod@npm:3.25.48" + checksum: 10c0/bb1a537b27b62e6e7a37f909e9ff029c6ddac89fd6bba24b8e92b2002d5e9aaa90f74b30da1186a1f6ea5f1a0e216b77fad49301a91998d32730fc1b65719dc3 + languageName: node + linkType: hard From fd2845f14bcd7193870393985187f1f3639529b3 Mon Sep 17 00:00:00 2001 From: hweawer Date: Thu, 18 Sep 2025 16:57:05 +0200 Subject: [PATCH 24/28] Rearrange validations --- scripts/vote_tw_csm2_mainnet.py | 7 +- tests/test_vote_tw_csm2_mainnet.py | 391 +++++++++++++++-------------- 2 files changed, 208 insertions(+), 190 deletions(-) diff --git a/scripts/vote_tw_csm2_mainnet.py b/scripts/vote_tw_csm2_mainnet.py index d2c1d83fd..962c74aaf 100644 --- a/scripts/vote_tw_csm2_mainnet.py +++ b/scripts/vote_tw_csm2_mainnet.py @@ -95,9 +95,9 @@ import time -from typing import TYPE_CHECKING, Any, Dict -from typing import Tuple, Optional, Sequence -from brownie import interface, web3, convert, ZERO_ADDRESS +from typing import Any, Dict +from typing import Tuple +from brownie import interface, web3, convert from brownie.convert.main import to_uint # type: ignore from utils.agent import agent_forward from utils.config import ( @@ -107,7 +107,6 @@ CS_MODULE_TREASURY_FEE_BP, CS_MODULE_MAX_DEPOSITS_PER_BLOCK, CS_MODULE_MIN_DEPOSIT_BLOCK_DISTANCE, - CS_MODULE_TARGET_SHARE_BP, CS_GATE_SEAL_ADDRESS, NODE_OPERATORS_REGISTRY_ARAGON_APP_ID, SIMPLE_DVT_ARAGON_APP_ID, diff --git a/tests/test_vote_tw_csm2_mainnet.py b/tests/test_vote_tw_csm2_mainnet.py index 802c9d268..a1d024f86 100644 --- a/tests/test_vote_tw_csm2_mainnet.py +++ b/tests/test_vote_tw_csm2_mainnet.py @@ -1,19 +1,10 @@ from typing import Optional -from brownie import chain, interface from brownie.network.transaction import TransactionReceipt from utils.test.tx_tracing_helpers import ( count_vote_items_by_events, display_dg_events, - display_voting_events, - group_voting_events_from_receipt, - group_dg_events_from_receipt, ) -from utils.evm_script import encode_call_script -from utils.voting import find_metadata_by_vote_id -from utils.ipfs import get_lido_vote_cid_from_str -from utils.dual_governance import PROPOSAL_STATUS -from utils.test.event_validators.dual_governance import validate_dual_governance_submit_event from brownie.exceptions import VirtualMachineError from brownie import interface, reverts, chain, convert, web3, ZERO_ADDRESS # type: ignore @@ -886,187 +877,12 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g # ======================================================================= # ========================= Before voting checks ======================== # ======================================================================= - # Step 1: Check Lido Locator implementation initial state - assert locator_impl_before != LIDO_LOCATOR_IMPL, "Locator implementation should be different before upgrade" - - # Step 2: Check VEBO implementation initial state - assert vebo_impl_before != VALIDATORS_EXIT_BUS_ORACLE_IMPL, "VEBO implementation should be different before upgrade" - - # Step 3: Check VEBO finalizeUpgrade_v2 state - try: # FIXME: with reverts - assert contracts.validators_exit_bus_oracle.getMaxValidatorsPerReport() != 600, "VEBO max validators per report should not be 600 before upgrade" # FIXME: magic number - except Exception: - pass # Function might not exist yet - - # Steps 4-6: Check VEBO consensus version management - initial_vebo_consensus_version = contracts.validators_exit_bus_oracle.getConsensusVersion() - assert initial_vebo_consensus_version < VEBO_CONSENSUS_VERSION, f"VEBO consensus version should be less than {VEBO_CONSENSUS_VERSION}" - # FIXME: Why no check for the role SUBMIT_REPORT_HASH_ROLE? - - # Step 7: Check TWG role for CS Ejector initial state - add_full_withdrawal_request_role = triggerable_withdrawals_gateway.ADD_FULL_WITHDRAWAL_REQUEST_ROLE() - assert not triggerable_withdrawals_gateway.hasRole(add_full_withdrawal_request_role, cs_ejector), "CS Ejector should not have ADD_FULL_WITHDRAWAL_REQUEST_ROLE before upgrade" - - # Step 8: Check TWG role for VEB initial state - assert not triggerable_withdrawals_gateway.hasRole(add_full_withdrawal_request_role, contracts.validators_exit_bus_oracle), "VEBO should not have ADD_FULL_WITHDRAWAL_REQUEST_ROLE before upgrade" - - # Step 9: Check EasyTrack VEB SUBMIT_REPORT_HASH_ROLE initial state - submit_report_hash_role = web3.keccak(text="SUBMIT_REPORT_HASH_ROLE") - assert not contracts.validators_exit_bus_oracle.hasRole(submit_report_hash_role, EASYTRACK_EVMSCRIPT_EXECUTOR), "EasyTrack executor should not have SUBMIT_REPORT_HASH_ROLE on VEBO before upgrade" - - # Step 10: Check DualGovernance tiebreaker initial state - tiebreaker_details = contracts.dual_governance.getTiebreakerDetails() - initial_tiebreakers = tiebreaker_details[3] # sealableWithdrawalBlockers - assert TRIGGERABLE_WITHDRAWALS_GATEWAY not in initial_tiebreakers, "TWG should not be in tiebreaker list before upgrade" - - # Step 9: Check Withdrawal Vault implementation initial state - assert withdrawal_vault_impl_before != WITHDRAWAL_VAULT_IMPL, "Withdrawal Vault implementation should be different before upgrade" - - # Step 10: Withdrawal Vault finalizeUpgrade_v2 check is done post-execution - assert contracts.withdrawal_vault.getContractVersion() == 1, "Withdrawal Vault version should be 1 before upgrade" - - # Step 11: Check Accounting Oracle implementation initial state - assert accounting_oracle_impl_before != ACCOUNTING_ORACLE_IMPL, "Accounting Oracle implementation should be different before upgrade" - - # Steps 12-14: Check AO consensus version management - initial_ao_consensus_version = contracts.accounting_oracle.getConsensusVersion() - assert initial_ao_consensus_version < AO_CONSENSUS_VERSION, f"AO consensus version should be less than {AO_CONSENSUS_VERSION}" - assert not contracts.accounting_oracle.hasRole(contracts.accounting_oracle.MANAGE_CONSENSUS_VERSION_ROLE(), contracts.agent), "Agent should not have MANAGE_CONSENSUS_VERSION_ROLE on AO before upgrade" - - # Step 17: Check AO version before finalizeUpgrade_v3 - assert contracts.accounting_oracle.getContractVersion() == 2, "AO contract version should be 2 before finalizeUpgrade_v3" - - # Step 15: Check Staking Router implementation initial state - assert staking_router_impl_before != STAKING_ROUTER_IMPL, "Staking Router implementation should be different before upgrade" - - # Steps 16-17: Check SR roles initial state - try: - report_validator_exiting_status_role = contracts.staking_router.REPORT_VALIDATOR_EXITING_STATUS_ROLE() - report_validator_exit_triggered_role = contracts.staking_router.REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE() - except Exception as e: - assert "Unknown typed error: 0x" in str(e), f"Unexpected error: {e}" - report_validator_exiting_status_role = ZERO_ADDRESS - report_validator_exit_triggered_role = ZERO_ADDRESS - - assert report_validator_exiting_status_role == ZERO_ADDRESS, "REPORT_VALIDATOR_EXITING_STATUS_ROLE should not exist before upgrade" - assert report_validator_exit_triggered_role == ZERO_ADDRESS, "REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE should not exist before upgrade" - - # Step 18: Check APP_MANAGER_ROLE initial state - app_manager_role = web3.keccak(text="APP_MANAGER_ROLE") - assert contracts.acl.getPermissionManager(ARAGON_KERNEL, app_manager_role) == AGENT, "AGENT should be the permission manager for APP_MANAGER_ROLE" - assert contracts.node_operators_registry.kernel() == ARAGON_KERNEL, "Node Operators Registry must use the correct kernel" - assert not contracts.acl.hasPermission(VOTING, ARAGON_KERNEL, app_manager_role), "VOTING should not have APP_MANAGER_ROLE before the upgrade" - assert not contracts.acl.hasPermission(AGENT, ARAGON_KERNEL, app_manager_role), "AGENT should not have APP_MANAGER_ROLE before the upgrade" - - # Steps 19-23: Check NOR and sDVT initial state - assert not contracts.acl.hasPermission(contracts.agent, contracts.kernel, app_manager_role), "Agent should not have APP_MANAGER_ROLE before upgrade" - assert contracts.node_operators_registry.getContractVersion() == 3, "Node Operators Registry version should be 3 before upgrade" - assert contracts.simple_dvt.getContractVersion() == 3, "Simple DVT version should be 3 before upgrade" - - # Step 24: Check CONFIG_MANAGER_ROLE initial state - config_manager_role = contracts.oracle_daemon_config.CONFIG_MANAGER_ROLE() - assert not contracts.oracle_daemon_config.hasRole(config_manager_role, contracts.agent), "Agent should not have CONFIG_MANAGER_ROLE on Oracle Daemon Config before upgrade" - - # Steps 25-27: Check Oracle Daemon Config variables to be removed - try: - contracts.oracle_daemon_config.get('NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP') - contracts.oracle_daemon_config.get('VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS') - contracts.oracle_daemon_config.get('VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS') - except Exception as e: - assert False, f"Expected variables to exist before removal: {e}" - - # Step 28: Check that EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS doesn't exist yet - try: - contracts.oracle_daemon_config.get('EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS') - assert False, "EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS should not exist before vote" - except Exception: - pass # Expected to fail - - # Step 29: Check CSM implementation initial state - assert csm_impl_before != CSM_IMPL_V2_ADDRESS, "CSM implementation should be different before vote" - - # Step 30: Check CSM finalizeUpgradeV2 initial state - with reverts(): - # The function should not exist yet - contracts.csm.getInitializedVersion() - - # CSM Step 32: Check CSAccounting implementation (pre-vote state) - assert cs_accounting_impl_before != CS_ACCOUNTING_IMPL_V2_ADDRESS, "CSAccounting implementation should be different before vote" - - # CSM Step 33: Check CSAccounting finalizeUpgradeV2 was not called (pre-vote state) - with reverts(): - # The function should not exist yet - contracts.cs_accounting.getInitializedVersion() - - # CSM Step 34: Check CSFeeOracle implementation (pre-vote state) - assert cs_fee_oracle_impl_before != CS_FEE_ORACLE_IMPL_V2_ADDRESS, "CSFeeOracle implementation should be different before vote" - - # CSM Step 35: Check CSFeeOracle finalizeUpgradeV2 was not called (pre-vote state) - assert contracts.cs_fee_oracle.getContractVersion() < CS_FEE_ORACLE_V2_VERSION, f"CSFeeOracle version should be less than {CS_FEE_ORACLE_V2_VERSION} before vote" - assert contracts.cs_fee_oracle.getConsensusVersion() < 3, "CSFeeOracle consensus version should be less than 3 before vote" - - # CSM Step 36: Check CSFeeDistributor implementation (pre-vote state) - assert cs_fee_distributor_impl_before != CS_FEE_DISTRIBUTOR_IMPL_V2_ADDRESS, "CSFeeDistributor implementation should be different before vote" - - # CSM Step 37: Check CSFeeDistributor finalizeUpgradeV2 was not called (pre-vote state) - with reverts(): - # The function should not exist yet - contracts.cs_fee_distributor.getInitializedVersion() - - # CSM Steps 38-40: CSAccounting roles (pre-vote state) - assert contracts.cs_accounting.hasRole(contracts.cs_accounting.SET_BOND_CURVE_ROLE(), contracts.csm.address), "CSM should have SET_BOND_CURVE_ROLE on CSAccounting before vote" - assert contracts.cs_accounting.hasRole(web3.keccak(text="RESET_BOND_CURVE_ROLE"), contracts.csm.address), "CSM should have RESET_BOND_CURVE_ROLE on CSAccounting before vote" - assert contracts.cs_accounting.hasRole(web3.keccak(text="RESET_BOND_CURVE_ROLE"), CSM_COMMITTEE_MS), "CSM committee should have RESET_BOND_CURVE_ROLE on CSAccounting before vote" - - # CSM Steps 41-42: CSM roles (pre-vote state) - assert not contracts.csm.hasRole(web3.keccak(text="CREATE_NODE_OPERATOR_ROLE"), cs_permissionless_gate.address), "Permissionless gate should not have CREATE_NODE_OPERATOR_ROLE on CSM before vote" - assert not contracts.csm.hasRole(web3.keccak(text="CREATE_NODE_OPERATOR_ROLE"), cs_vetted_gate.address), "Vetted gate should not have CREATE_NODE_OPERATOR_ROLE on CSM before vote" - - # CSM Step 43: CSAccounting bond curve role for vetted gate (pre-vote state) - assert not contracts.cs_accounting.hasRole(contracts.cs_accounting.SET_BOND_CURVE_ROLE(), cs_vetted_gate.address), "Vetted gate should not have SET_BOND_CURVE_ROLE on CSAccounting before vote" - - # CSM Steps 44-45: Verifier roles (pre-vote state) - assert contracts.csm.hasRole(contracts.csm.VERIFIER_ROLE(), CS_VERIFIER_ADDRESS_OLD), "Old verifier should have VERIFIER_ROLE on CSM before vote" - assert not contracts.csm.hasRole(contracts.csm.VERIFIER_ROLE(), cs_verifier_v2.address), "New verifier should not have VERIFIER_ROLE on CSM before vote" - - # CSM Steps 46-51: GateSeal roles (pre-vote state) - assert contracts.csm.hasRole(contracts.csm.PAUSE_ROLE(), CS_GATE_SEAL_ADDRESS), "Old GateSeal should have PAUSE_ROLE on CSM before vote" - assert contracts.cs_accounting.hasRole(contracts.cs_accounting.PAUSE_ROLE(), CS_GATE_SEAL_ADDRESS), "Old GateSeal should have PAUSE_ROLE on CSAccounting before vote" - assert contracts.cs_fee_oracle.hasRole(contracts.cs_fee_oracle.PAUSE_ROLE(), CS_GATE_SEAL_ADDRESS), "Old GateSeal should have PAUSE_ROLE on CSFeeOracle before vote" - - assert not contracts.csm.hasRole(contracts.csm.PAUSE_ROLE(), CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should not have PAUSE_ROLE on CSM before vote" - assert not contracts.cs_accounting.hasRole(contracts.cs_accounting.PAUSE_ROLE(), CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should not have PAUSE_ROLE on CSAccounting before vote" - assert not contracts.cs_fee_oracle.hasRole(contracts.cs_fee_oracle.PAUSE_ROLE(), CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should not have PAUSE_ROLE on CSFeeOracle before vote" - - # CSM Step 52: Staking Router CSM module state before vote (pre-vote state) - csm_module_before = contracts.staking_router.getStakingModule(CS_MODULE_ID) - csm_share_before = csm_module_before['stakeShareLimit'] - csm_priority_exit_threshold_before = csm_module_before['priorityExitShareThreshold'] - assert csm_share_before != CS_MODULE_NEW_TARGET_SHARE_BP, f"CSM share should not be {CS_MODULE_NEW_TARGET_SHARE_BP} before vote, current: {csm_share_before}" - assert csm_priority_exit_threshold_before != CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP, f"CSM priority exit threshold should not be {CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP} before vote, current: {csm_priority_exit_threshold_before}" - # CSM Step 65: EasyTrack factories before vote (pre-vote state) initial_factories = contracts.easy_track.getEVMScriptFactories() assert EASYTRACK_CS_SET_VETTED_GATE_TREE_FACTORY not in initial_factories, "EasyTrack should not have CSMSetVettedGateTree factory before vote" assert EASYTRACK_SDVT_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY not in initial_factories, "EasyTrack should not have SDVT validator exit request hashes factory before vote" assert EASYTRACK_CURATED_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY not in initial_factories, "EasyTrack should not have Curated validator exit request hashes factory before vote" - # Gate Seals: Check initial states before vote - assert contracts.withdrawal_queue.hasRole(contracts.withdrawal_queue.PAUSE_ROLE(), OLD_GATE_SEAL_ADDRESS), "Old GateSeal should have PAUSE_ROLE on WithdrawalQueue before vote" - assert contracts.validators_exit_bus_oracle.hasRole(contracts.validators_exit_bus_oracle.PAUSE_ROLE(), OLD_GATE_SEAL_ADDRESS), "Old GateSeal should have PAUSE_ROLE on VEBO before vote" - assert not contracts.withdrawal_queue.hasRole(contracts.withdrawal_queue.PAUSE_ROLE(), NEW_WQ_GATE_SEAL), "New WQ GateSeal should not have PAUSE_ROLE on WithdrawalQueue before vote" - assert not contracts.validators_exit_bus_oracle.hasRole(contracts.validators_exit_bus_oracle.PAUSE_ROLE(), NEW_TW_GATE_SEAL), "New TW GateSeal should not have PAUSE_ROLE on VEBO before vote" - assert not triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.PAUSE_ROLE(), NEW_TW_GATE_SEAL), "New TW GateSeal should not have PAUSE_ROLE on TWG before vote" - - # ResealManager: Check initial states before vote - assert not triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.PAUSE_ROLE(), RESEAL_MANAGER), "ResealManager should not have PAUSE_ROLE on TWG before vote" - assert not triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.RESUME_ROLE(), RESEAL_MANAGER), "ResealManager should not have RESUME_ROLE on TWG before vote" - # Rename Nethermind NO - nethermind_no_data_before = no_registry.getNodeOperator(NETHERMIND_NO_ID, True) - - assert nethermind_no_data_before["rewardAddress"] == NETHERMIND_NO_STAKING_REWARDS_ADDRESS_OLD - assert nethermind_no_data_before["name"] == NETHERMIND_NO_NAME_OLD - assert get_lido_vote_cid_from_str(find_metadata_by_vote_id(vote_id)) == IPFS_DESCRIPTION_HASH vote_tx: TransactionReceipt = helpers.execute_vote(vote_id=vote_id, accounts=accounts, dao_voting=voting) @@ -1140,7 +956,210 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g # ========================================================================= # ================== DG before proposal executed checks =================== # ========================================================================= - # TODO add DG before proposal executed checks + # Step 1: Check Lido Locator implementation initial state + assert locator_impl_before != LIDO_LOCATOR_IMPL, "Locator implementation should be different before upgrade" + + # Step 2: Check VEBO implementation initial state + assert vebo_impl_before != VALIDATORS_EXIT_BUS_ORACLE_IMPL, "VEBO implementation should be different before upgrade" + + # Step 3: Check VEBO finalizeUpgrade_v2 state + try: # FIXME: with reverts + assert contracts.validators_exit_bus_oracle.getMaxValidatorsPerReport() != 600, "VEBO max validators per report should not be 600 before upgrade" # FIXME: magic number + except Exception: + pass # Function might not exist yet + + # Steps 4-6: Check VEBO consensus version management + initial_vebo_consensus_version = contracts.validators_exit_bus_oracle.getConsensusVersion() + assert initial_vebo_consensus_version < VEBO_CONSENSUS_VERSION, f"VEBO consensus version should be less than {VEBO_CONSENSUS_VERSION}" + # FIXME: Why no check for the role SUBMIT_REPORT_HASH_ROLE? + + # Step 7: Check TWG role for CS Ejector initial state + add_full_withdrawal_request_role = triggerable_withdrawals_gateway.ADD_FULL_WITHDRAWAL_REQUEST_ROLE() + assert not triggerable_withdrawals_gateway.hasRole(add_full_withdrawal_request_role, + cs_ejector), "CS Ejector should not have ADD_FULL_WITHDRAWAL_REQUEST_ROLE before upgrade" + + # Step 8: Check TWG role for VEB initial state + assert not triggerable_withdrawals_gateway.hasRole(add_full_withdrawal_request_role, + contracts.validators_exit_bus_oracle), "VEBO should not have ADD_FULL_WITHDRAWAL_REQUEST_ROLE before upgrade" + + # Step 9: Check EasyTrack VEB SUBMIT_REPORT_HASH_ROLE initial state + submit_report_hash_role = web3.keccak(text="SUBMIT_REPORT_HASH_ROLE") + assert not contracts.validators_exit_bus_oracle.hasRole(submit_report_hash_role, + EASYTRACK_EVMSCRIPT_EXECUTOR), "EasyTrack executor should not have SUBMIT_REPORT_HASH_ROLE on VEBO before upgrade" + + # Step 10: Check DualGovernance tiebreaker initial state + tiebreaker_details = contracts.dual_governance.getTiebreakerDetails() + initial_tiebreakers = tiebreaker_details[3] # sealableWithdrawalBlockers + assert TRIGGERABLE_WITHDRAWALS_GATEWAY not in initial_tiebreakers, "TWG should not be in tiebreaker list before upgrade" + + # Step 9: Check Withdrawal Vault implementation initial state + assert withdrawal_vault_impl_before != WITHDRAWAL_VAULT_IMPL, "Withdrawal Vault implementation should be different before upgrade" + + # Step 10: Withdrawal Vault finalizeUpgrade_v2 check is done post-execution + assert contracts.withdrawal_vault.getContractVersion() == 1, "Withdrawal Vault version should be 1 before upgrade" + + # Step 11: Check Accounting Oracle implementation initial state + assert accounting_oracle_impl_before != ACCOUNTING_ORACLE_IMPL, "Accounting Oracle implementation should be different before upgrade" + + # Steps 12-14: Check AO consensus version management + initial_ao_consensus_version = contracts.accounting_oracle.getConsensusVersion() + assert initial_ao_consensus_version < AO_CONSENSUS_VERSION, f"AO consensus version should be less than {AO_CONSENSUS_VERSION}" + assert not contracts.accounting_oracle.hasRole(contracts.accounting_oracle.MANAGE_CONSENSUS_VERSION_ROLE(), + contracts.agent), "Agent should not have MANAGE_CONSENSUS_VERSION_ROLE on AO before upgrade" + + # Step 17: Check AO version before finalizeUpgrade_v3 + assert contracts.accounting_oracle.getContractVersion() == 2, "AO contract version should be 2 before finalizeUpgrade_v3" + + # Step 15: Check Staking Router implementation initial state + assert staking_router_impl_before != STAKING_ROUTER_IMPL, "Staking Router implementation should be different before upgrade" + + # Steps 16-17: Check SR roles initial state + try: + report_validator_exiting_status_role = contracts.staking_router.REPORT_VALIDATOR_EXITING_STATUS_ROLE() + report_validator_exit_triggered_role = contracts.staking_router.REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE() + except Exception as e: + assert "Unknown typed error: 0x" in str(e), f"Unexpected error: {e}" + report_validator_exiting_status_role = ZERO_ADDRESS + report_validator_exit_triggered_role = ZERO_ADDRESS + + assert report_validator_exiting_status_role == ZERO_ADDRESS, "REPORT_VALIDATOR_EXITING_STATUS_ROLE should not exist before upgrade" + assert report_validator_exit_triggered_role == ZERO_ADDRESS, "REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE should not exist before upgrade" + + # Step 18: Check APP_MANAGER_ROLE initial state + app_manager_role = web3.keccak(text="APP_MANAGER_ROLE") + assert contracts.acl.getPermissionManager(ARAGON_KERNEL, + app_manager_role) == AGENT, "AGENT should be the permission manager for APP_MANAGER_ROLE" + assert contracts.node_operators_registry.kernel() == ARAGON_KERNEL, "Node Operators Registry must use the correct kernel" + assert not contracts.acl.hasPermission(VOTING, ARAGON_KERNEL, + app_manager_role), "VOTING should not have APP_MANAGER_ROLE before the upgrade" + assert not contracts.acl.hasPermission(AGENT, ARAGON_KERNEL, + app_manager_role), "AGENT should not have APP_MANAGER_ROLE before the upgrade" + + # Steps 19-23: Check NOR and sDVT initial state + assert not contracts.acl.hasPermission(contracts.agent, contracts.kernel, + app_manager_role), "Agent should not have APP_MANAGER_ROLE before upgrade" + assert contracts.node_operators_registry.getContractVersion() == 3, "Node Operators Registry version should be 3 before upgrade" + assert contracts.simple_dvt.getContractVersion() == 3, "Simple DVT version should be 3 before upgrade" + + # Step 24: Check CONFIG_MANAGER_ROLE initial state + config_manager_role = contracts.oracle_daemon_config.CONFIG_MANAGER_ROLE() + assert not contracts.oracle_daemon_config.hasRole(config_manager_role, + contracts.agent), "Agent should not have CONFIG_MANAGER_ROLE on Oracle Daemon Config before upgrade" + + # Steps 25-27: Check Oracle Daemon Config variables to be removed + try: + contracts.oracle_daemon_config.get('NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP') + contracts.oracle_daemon_config.get('VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS') + contracts.oracle_daemon_config.get('VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS') + except Exception as e: + assert False, f"Expected variables to exist before removal: {e}" + + # Step 28: Check that EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS doesn't exist yet + try: + contracts.oracle_daemon_config.get('EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS') + assert False, "EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS should not exist before vote" + except Exception: + pass # Expected to fail + + # Step 29: Check CSM implementation initial state + assert csm_impl_before != CSM_IMPL_V2_ADDRESS, "CSM implementation should be different before vote" + + # Step 30: Check CSM finalizeUpgradeV2 initial state + with reverts(): + # The function should not exist yet + contracts.csm.getInitializedVersion() + + # CSM Step 32: Check CSAccounting implementation (pre-vote state) + assert cs_accounting_impl_before != CS_ACCOUNTING_IMPL_V2_ADDRESS, "CSAccounting implementation should be different before vote" + + # CSM Step 33: Check CSAccounting finalizeUpgradeV2 was not called (pre-vote state) + with reverts(): + # The function should not exist yet + contracts.cs_accounting.getInitializedVersion() + + # CSM Step 34: Check CSFeeOracle implementation (pre-vote state) + assert cs_fee_oracle_impl_before != CS_FEE_ORACLE_IMPL_V2_ADDRESS, "CSFeeOracle implementation should be different before vote" + + # CSM Step 35: Check CSFeeOracle finalizeUpgradeV2 was not called (pre-vote state) + assert contracts.cs_fee_oracle.getContractVersion() < CS_FEE_ORACLE_V2_VERSION, f"CSFeeOracle version should be less than {CS_FEE_ORACLE_V2_VERSION} before vote" + assert contracts.cs_fee_oracle.getConsensusVersion() < 3, "CSFeeOracle consensus version should be less than 3 before vote" + + # CSM Step 36: Check CSFeeDistributor implementation (pre-vote state) + assert cs_fee_distributor_impl_before != CS_FEE_DISTRIBUTOR_IMPL_V2_ADDRESS, "CSFeeDistributor implementation should be different before vote" + + # CSM Step 37: Check CSFeeDistributor finalizeUpgradeV2 was not called (pre-vote state) + with reverts(): + # The function should not exist yet + contracts.cs_fee_distributor.getInitializedVersion() + + # CSM Steps 38-40: CSAccounting roles (pre-vote state) + assert contracts.cs_accounting.hasRole(contracts.cs_accounting.SET_BOND_CURVE_ROLE(), + contracts.csm.address), "CSM should have SET_BOND_CURVE_ROLE on CSAccounting before vote" + assert contracts.cs_accounting.hasRole(web3.keccak(text="RESET_BOND_CURVE_ROLE"), + contracts.csm.address), "CSM should have RESET_BOND_CURVE_ROLE on CSAccounting before vote" + assert contracts.cs_accounting.hasRole(web3.keccak(text="RESET_BOND_CURVE_ROLE"), + CSM_COMMITTEE_MS), "CSM committee should have RESET_BOND_CURVE_ROLE on CSAccounting before vote" + + # CSM Steps 41-42: CSM roles (pre-vote state) + assert not contracts.csm.hasRole(web3.keccak(text="CREATE_NODE_OPERATOR_ROLE"), + cs_permissionless_gate.address), "Permissionless gate should not have CREATE_NODE_OPERATOR_ROLE on CSM before vote" + assert not contracts.csm.hasRole(web3.keccak(text="CREATE_NODE_OPERATOR_ROLE"), + cs_vetted_gate.address), "Vetted gate should not have CREATE_NODE_OPERATOR_ROLE on CSM before vote" + + # CSM Step 43: CSAccounting bond curve role for vetted gate (pre-vote state) + assert not contracts.cs_accounting.hasRole(contracts.cs_accounting.SET_BOND_CURVE_ROLE(), + cs_vetted_gate.address), "Vetted gate should not have SET_BOND_CURVE_ROLE on CSAccounting before vote" + + # CSM Steps 44-45: Verifier roles (pre-vote state) + assert contracts.csm.hasRole(contracts.csm.VERIFIER_ROLE(), + CS_VERIFIER_ADDRESS_OLD), "Old verifier should have VERIFIER_ROLE on CSM before vote" + assert not contracts.csm.hasRole(contracts.csm.VERIFIER_ROLE(), + cs_verifier_v2.address), "New verifier should not have VERIFIER_ROLE on CSM before vote" + + # CSM Steps 46-51: GateSeal roles (pre-vote state) + assert contracts.csm.hasRole(contracts.csm.PAUSE_ROLE(), + CS_GATE_SEAL_ADDRESS), "Old GateSeal should have PAUSE_ROLE on CSM before vote" + assert contracts.cs_accounting.hasRole(contracts.cs_accounting.PAUSE_ROLE(), + CS_GATE_SEAL_ADDRESS), "Old GateSeal should have PAUSE_ROLE on CSAccounting before vote" + assert contracts.cs_fee_oracle.hasRole(contracts.cs_fee_oracle.PAUSE_ROLE(), + CS_GATE_SEAL_ADDRESS), "Old GateSeal should have PAUSE_ROLE on CSFeeOracle before vote" + + assert not contracts.csm.hasRole(contracts.csm.PAUSE_ROLE(), + CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should not have PAUSE_ROLE on CSM before vote" + assert not contracts.cs_accounting.hasRole(contracts.cs_accounting.PAUSE_ROLE(), + CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should not have PAUSE_ROLE on CSAccounting before vote" + assert not contracts.cs_fee_oracle.hasRole(contracts.cs_fee_oracle.PAUSE_ROLE(), + CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should not have PAUSE_ROLE on CSFeeOracle before vote" + + # CSM Step 52: Staking Router CSM module state before vote (pre-vote state) + csm_module_before = contracts.staking_router.getStakingModule(CS_MODULE_ID) + csm_share_before = csm_module_before['stakeShareLimit'] + csm_priority_exit_threshold_before = csm_module_before['priorityExitShareThreshold'] + assert csm_share_before != CS_MODULE_NEW_TARGET_SHARE_BP, f"CSM share should not be {CS_MODULE_NEW_TARGET_SHARE_BP} before vote, current: {csm_share_before}" + assert csm_priority_exit_threshold_before != CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP, f"CSM priority exit threshold should not be {CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP} before vote, current: {csm_priority_exit_threshold_before}" + + # Gate Seals: Check initial states before vote + assert contracts.withdrawal_queue.hasRole(contracts.withdrawal_queue.PAUSE_ROLE(), + OLD_GATE_SEAL_ADDRESS), "Old GateSeal should have PAUSE_ROLE on WithdrawalQueue before vote" + assert contracts.validators_exit_bus_oracle.hasRole(contracts.validators_exit_bus_oracle.PAUSE_ROLE(), + OLD_GATE_SEAL_ADDRESS), "Old GateSeal should have PAUSE_ROLE on VEBO before vote" + assert not contracts.withdrawal_queue.hasRole(contracts.withdrawal_queue.PAUSE_ROLE(), + NEW_WQ_GATE_SEAL), "New WQ GateSeal should not have PAUSE_ROLE on WithdrawalQueue before vote" + assert not contracts.validators_exit_bus_oracle.hasRole(contracts.validators_exit_bus_oracle.PAUSE_ROLE(), + NEW_TW_GATE_SEAL), "New TW GateSeal should not have PAUSE_ROLE on VEBO before vote" + assert not triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.PAUSE_ROLE(), + NEW_TW_GATE_SEAL), "New TW GateSeal should not have PAUSE_ROLE on TWG before vote" + + # ResealManager: Check initial states before vote + assert not triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.PAUSE_ROLE(), + RESEAL_MANAGER), "ResealManager should not have PAUSE_ROLE on TWG before vote" + assert not triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.RESUME_ROLE(), + RESEAL_MANAGER), "ResealManager should not have RESUME_ROLE on TWG before vote" + # Rename Nethermind NO + nethermind_no_data_before = no_registry.getNodeOperator(NETHERMIND_NO_ID, True) + + assert nethermind_no_data_before["rewardAddress"] == NETHERMIND_NO_STAKING_REWARDS_ADDRESS_OLD + assert nethermind_no_data_before["name"] == NETHERMIND_NO_NAME_OLD if details["status"] == PROPOSAL_STATUS["submitted"]: chain.sleep(timelock.getAfterSubmitDelay() + 1) @@ -1149,7 +1168,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g if timelock.getProposalDetails(EXPECTED_DG_PROPOSAL_ID)["status"] == PROPOSAL_STATUS["scheduled"]: chain.sleep(timelock.getAfterScheduleDelay() + 1) dg_tx: TransactionReceipt = timelock.execute(EXPECTED_DG_PROPOSAL_ID, {"from": stranger}) - display_dg_events(dg_tx) + #display_dg_events(dg_tx) dg_events = group_dg_events_from_receipt( dg_tx, timelock=EMERGENCY_PROTECTED_TIMELOCK, From 8db95bddbccc146245f0c208973362de23f233dc Mon Sep 17 00:00:00 2001 From: vgorkavenko Date: Thu, 18 Sep 2025 16:59:01 +0200 Subject: [PATCH 25/28] feat: CSM Set Vetted Gate Tree address --- scripts/vote_tw_csm2_mainnet.py | 2 +- tests/regression/test_csm.py | 27 ++++++++++++++++++++++----- tests/test_vote_tw_csm2_mainnet.py | 2 +- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/scripts/vote_tw_csm2_mainnet.py b/scripts/vote_tw_csm2_mainnet.py index 962c74aaf..846961fd5 100644 --- a/scripts/vote_tw_csm2_mainnet.py +++ b/scripts/vote_tw_csm2_mainnet.py @@ -185,7 +185,7 @@ EASYTRACK_EVMSCRIPT_EXECUTOR = "0x79a20FD0FA36453B2F45eAbab19bfef43575Ba9E" EASYTRACK_SDVT_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY = "0xAa3D6A8B52447F272c1E8FAaA06EA06658bd95E2" EASYTRACK_CURATED_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY = "0x397206ecdbdcb1A55A75e60Fc4D054feC72E5f63" -EASYTRACK_CS_SET_VETTED_GATE_TREE_FACTORY = "0xa890fc73e1b771Ee6073e2402E631c312FF92Cd9" # TODO: replace with the real one +EASYTRACK_CS_SET_VETTED_GATE_TREE_FACTORY = "0xBc5642bDD6F2a54b01A75605aAe9143525D97308" # ============================= Description ================================== IPFS_DESCRIPTION = "Triggerable withdrawals and CSM v2 upgrade voting" diff --git a/tests/regression/test_csm.py b/tests/regression/test_csm.py index bb8ad16b2..bc0e3c869 100644 --- a/tests/regression/test_csm.py +++ b/tests/regression/test_csm.py @@ -433,10 +433,18 @@ def test_csm_remove_key(csm, parameters_registry, accounting, node_operator): def test_eject_bad_performer(csm, ejector, node_operator): eject_payment_value = get_sys_fee_to_eject() + index_to_eject = 0 tx = ejector.ejectBadPerformer( - node_operator, 0, ZERO_ADDRESS, {"value": eject_payment_value, "from": contracts.cs_strikes} + node_operator, index_to_eject, ZERO_ADDRESS, {"value": eject_payment_value, "from": contracts.cs_strikes} ) + assert "TriggeredExitFeeRecorded" in tx.events + assert tx.events["TriggeredExitFeeRecorded"]["nodeOperatorId"] == node_operator + pubkey = csm.getSigningKeys(node_operator, index_to_eject, 1) + assert tx.events["TriggeredExitFeeRecorded"]["pubkey"] == pubkey + assert tx.events["TriggeredExitFeeRecorded"]["exitType"] == 1 + assert tx.events["TriggeredExitFeeRecorded"]["withdrawalRequestPaidFee"] == eject_payment_value + assert tx.events["TriggeredExitFeeRecorded"]["withdrawalRequestRecordedFee"] == eject_payment_value @pytest.mark.usefixtures("deposits_to_csm") @@ -451,16 +459,25 @@ def test_voluntary_eject(csm, ejector, node_operator): def test_report_validator_exit_delay(csm, node_operator): - key, *_ = csm.getSigningKeys(node_operator, 0, 1) + pubkey = csm.getSigningKeys(node_operator, 0, 1) day_in_seconds = 60 * 60 * 24 - tx = csm.reportValidatorExitDelay(node_operator, 0, key, 7 * day_in_seconds, {"from": contracts.staking_router}) + tx = csm.reportValidatorExitDelay(node_operator, 0, pubkey, 7 * day_in_seconds, {"from": contracts.staking_router}) assert "ValidatorExitDelayProcessed" in tx.events + assert tx.events["ValidatorExitDelayProcessed"]["nodeOperatorId"] == node_operator + assert tx.events["ValidatorExitDelayProcessed"]["pubkey"] == pubkey + assert tx.events["ValidatorExitDelayProcessed"]["delayPenalty"] == 100000000000000000 # FIXME: should be taken from CSParametersRegistry def test_on_validator_exit_triggered(csm, node_operator): - key, *_ = csm.getSigningKeys(node_operator, 0, 1) + eject_payment_value = 1 + pubkey = csm.getSigningKeys(node_operator, 0, 1) exit_type = 3 - tx = csm.onValidatorExitTriggered(node_operator, key, 1, exit_type, {"from": contracts.staking_router}) + tx = csm.onValidatorExitTriggered(node_operator, pubkey, 1, exit_type, {"from": contracts.staking_router}) assert "TriggeredExitFeeRecorded" in tx.events + assert tx.events["TriggeredExitFeeRecorded"]["nodeOperatorId"] == node_operator + assert tx.events["TriggeredExitFeeRecorded"]["pubkey"] == pubkey + assert tx.events["TriggeredExitFeeRecorded"]["exitType"] == exit_type + assert tx.events["TriggeredExitFeeRecorded"]["withdrawalRequestPaidFee"] == eject_payment_value + assert tx.events["TriggeredExitFeeRecorded"]["withdrawalRequestRecordedFee"] == eject_payment_value diff --git a/tests/test_vote_tw_csm2_mainnet.py b/tests/test_vote_tw_csm2_mainnet.py index a1d024f86..decb30a46 100644 --- a/tests/test_vote_tw_csm2_mainnet.py +++ b/tests/test_vote_tw_csm2_mainnet.py @@ -263,7 +263,7 @@ def check_proxy_implementation(proxy_address, expected_impl): CS_FEE_ORACLE_V2_VERSION = 2 CS_FEE_DISTRIBUTOR_V2_VERSION = 2 -EASYTRACK_CS_SET_VETTED_GATE_TREE_FACTORY = "0xa890fc73e1b771Ee6073e2402E631c312FF92Cd9" +EASYTRACK_CS_SET_VETTED_GATE_TREE_FACTORY = "0xBc5642bDD6F2a54b01A75605aAe9143525D97308" EXPECTED_VOTE_ID = None EXPECTED_DG_PROPOSAL_ID = 5 From a0c1ca8e7413942d4c440765672729e440af04ae Mon Sep 17 00:00:00 2001 From: hweawer Date: Thu, 18 Sep 2025 21:18:26 +0200 Subject: [PATCH 26/28] Fix tests --- .../test_vote_update_sandbox_impl_holesky.py | 1 - scripts/vote_tw_csm2_mainnet.py | 35 +- tests/test_vote_tw_csm2_mainnet.py | 385 +++++++++--------- 3 files changed, 211 insertions(+), 210 deletions(-) diff --git a/archive/tests/test_vote_update_sandbox_impl_holesky.py b/archive/tests/test_vote_update_sandbox_impl_holesky.py index f793f50cd..2e8ba9ff3 100644 --- a/archive/tests/test_vote_update_sandbox_impl_holesky.py +++ b/archive/tests/test_vote_update_sandbox_impl_holesky.py @@ -134,4 +134,3 @@ def test_vote_update_sandbox_impl(helpers, accounts, vote_ids_from_env, stranger dg_execution_events = group_dg_events_from_receipt(dg_tx, timelock=TIMELOCK, admin_executor=DUAL_GOVERNANCE_EXECUTORS[0]) assert len(dg_execution_events) == 4, "Unexpected number of dual governance events" - diff --git a/scripts/vote_tw_csm2_mainnet.py b/scripts/vote_tw_csm2_mainnet.py index 962c74aaf..2602cd7a6 100644 --- a/scripts/vote_tw_csm2_mainnet.py +++ b/scripts/vote_tw_csm2_mainnet.py @@ -99,6 +99,7 @@ from typing import Tuple from brownie import interface, web3, convert from brownie.convert.main import to_uint # type: ignore + from utils.agent import agent_forward from utils.config import ( CSM_COMMITTEE_MS, @@ -169,6 +170,7 @@ CS_VETTED_GATE_ADDRESS = "0xB314D4A76C457c93150d308787939063F4Cc67E0" CS_VERIFIER_V2_ADDRESS = "0xdC5FE1782B6943f318E05230d688713a560063DC" +CS_VERIFIER_ADDRESS_OLD = "0xeC6Cc185f671F627fb9b6f06C8772755F587b05d" CS_CURVES = [ ([1, 2.4 * 10**18], [2, 1.3 * 10**18]), # Default Curve ([1, 1.5 * 10**18], [2, 1.3 * 10**18]), # Legacy EA Curve @@ -181,12 +183,19 @@ NEW_TW_GATE_SEAL = "0xA6BC802fAa064414AA62117B4a53D27fFfF741F1" RESEAL_MANAGER = "0x7914b5a1539b97Bd0bbd155757F25FD79A522d24" +NETHERMIND_NO_ID = 25 +NETHERMIND_NEW_REWARD_ADDRESS = "0x36201ed66DbC284132046ee8d99272F8eEeb24c8" +NETHERMIND_NEW_NO_NAME = "Twinstake" + # Add EasyTrack constants EASYTRACK_EVMSCRIPT_EXECUTOR = "0x79a20FD0FA36453B2F45eAbab19bfef43575Ba9E" EASYTRACK_SDVT_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY = "0xAa3D6A8B52447F272c1E8FAaA06EA06658bd95E2" EASYTRACK_CURATED_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY = "0x397206ecdbdcb1A55A75e60Fc4D054feC72E5f63" EASYTRACK_CS_SET_VETTED_GATE_TREE_FACTORY = "0xa890fc73e1b771Ee6073e2402E631c312FF92Cd9" # TODO: replace with the real one +OLD_KILN_ADDRESS = "0x14D5d5B71E048d2D75a39FfC5B407e3a3AB6F314" +NEW_KILN_ADDRESS = "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045" # todo: replace with the real one + # ============================= Description ================================== IPFS_DESCRIPTION = "Triggerable withdrawals and CSM v2 upgrade voting" @@ -667,7 +676,7 @@ def get_vote_items(): encode_oz_revoke_role( contract=contracts.csm, role_name="VERIFIER_ROLE", - revoke_from=contracts.cs_verifier, + revoke_from=CS_VERIFIER_ADDRESS_OLD, ) ] ), @@ -846,27 +855,27 @@ def get_vote_items(): # "67. Rename Node Operator ID 25 from Nethermind to Twinstake" agent_forward( [ - encode_set_node_operator_name(id=25, name="Twinstake", registry=contracts.node_operators_registry), + encode_set_node_operator_name(id=NETHERMIND_NO_ID, name=NETHERMIND_NEW_NO_NAME, registry=contracts.node_operators_registry), ] ), # "68. Change Node Operator ID 25 reward address from 0x237DeE529A47750bEcdFa8A59a1D766e3e7B5F91 to 0x36201ed66DbC284132046ee8d99272F8eEeb24c8" agent_forward( [ - encode_set_node_operator_reward_address(id=17, rewardAddress="0x36201ed66DbC284132046ee8d99272F8eEeb24c8", registry=contracts.node_operators_registry), + encode_set_node_operator_reward_address(id=NETHERMIND_NO_ID, rewardAddress=NETHERMIND_NEW_REWARD_ADDRESS, registry=contracts.node_operators_registry), ] ), # "69. Remove Kiln guardian" - #agent_forward( - # [ - # encode_remove_guardian(guardian_address="", quorum_size=4), - # ] - #), + agent_forward( + [ + encode_remove_guardian(dsm=contracts.deposit_security_module, guardian_address=OLD_KILN_ADDRESS, quorum_size=4), + ] + ), # "70. Add new Kiln guardian" - #agent_forward( - # [ - # encode_add_guardian(guardian_address="", quorum_size=4), - # ] - #), + agent_forward( + [ + encode_add_guardian(dsm=contracts.deposit_security_module, guardian_address=NEW_KILN_ADDRESS, quorum_size=4), + ] + ), ] dg_call_script = submit_proposals( [ diff --git a/tests/test_vote_tw_csm2_mainnet.py b/tests/test_vote_tw_csm2_mainnet.py index a1d024f86..19675f379 100644 --- a/tests/test_vote_tw_csm2_mainnet.py +++ b/tests/test_vote_tw_csm2_mainnet.py @@ -1,6 +1,7 @@ from typing import Optional from brownie.network.transaction import TransactionReceipt +from utils.dsm import encode_remove_guardian, encode_add_guardian from utils.test.tx_tracing_helpers import ( count_vote_items_by_events, display_dg_events, @@ -13,6 +14,7 @@ from utils.evm_script import encode_call_script from utils.voting import find_metadata_by_vote_id from utils.ipfs import get_lido_vote_cid_from_str +from utils.test.tx_tracing_helpers import display_voting_events from utils.dual_governance import PROPOSAL_STATUS from utils.test.event_validators.node_operators_registry import ( validate_node_operator_name_set_event, @@ -20,11 +22,9 @@ NodeOperatorNameSetItem, NodeOperatorRewardAddressSetItem, ) -from utils.test.event_validators.dual_governance import validate_dual_governance_submit_event from utils.test.tx_tracing_helpers import group_voting_events_from_receipt, group_dg_events_from_receipt from utils.test.event_validators.easy_track import validate_evmscript_factory_added_event, EVMScriptFactoryAdded from utils.test.event_validators.dual_governance import validate_dual_governance_submit_event -from utils.dual_governance import wait_for_noon_utc_to_satisfy_time_constrains from utils.config import ( CS_MODULE_ID, CS_MODULE_MODULE_FEE_BP, @@ -104,6 +104,22 @@ def validate_bond_curve_added_event(event: EventDict, curve_id: int, emitted_by: if emitted_by is not None: assert convert.to_address(event["BondCurveAdded"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" +def validate_remove_guardian_event(event: EventDict, guardian_address: str, emitted_by: Optional[str] = None): + assert "GuardianRemoved" in event, "No GuardianRemoved event found" + + assert event["GuardianRemoved"][0]["guardian"] == guardian_address, "Wrong guardian address" + + if emitted_by is not None: + assert convert.to_address(event["GuardianRemoved"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + +def validate_add_guardian_event(event: EventDict, guardian_address: str, emitted_by: Optional[str] = None): + assert "GuardianAdded" in event, "No GuardianAdded event found" + + assert event["GuardianAdded"][0]["guardian"] == guardian_address, "Wrong guardian address" + + if emitted_by is not None: + assert convert.to_address(event["GuardianAdded"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" + def validate_staking_module_update_event( event: EventDict, @@ -166,7 +182,8 @@ def check_proxy_implementation(proxy_address, expected_impl): # ============================================================================ # ============================== Import vote ================================= # ============================================================================ -from scripts.vote_tw_csm2_mainnet import start_vote, get_vote_items, encode_wv_proxy_upgrade_to +from scripts.vote_tw_csm2_mainnet import start_vote, get_vote_items, encode_wv_proxy_upgrade_to, \ + NETHERMIND_NEW_REWARD_ADDRESS # ============================================================================ # ============================== Constants =================================== @@ -177,6 +194,7 @@ def check_proxy_implementation(proxy_address, expected_impl): DUAL_GOVERNANCE_ADMIN_EXECUTOR = "0x23E0B465633FF5178808F4A75186E2F2F9537021" AGENT = "0x3e40D73EB977Dc6a537aF587D48316feE66E9C8c" ARAGON_KERNEL = "0xb8FFC3Cd6e7Cf5a098A1c92F48009765B24088Dc" +STETH = "0xAE7ab96520DE3A18E5e111B5EaAb095312D7fE84" # New core contracts implementations LIDO_LOCATOR_IMPL = "0x2C298963FB763f74765829722a1ebe0784f4F5Cf" @@ -268,7 +286,8 @@ def check_proxy_implementation(proxy_address, expected_impl): EXPECTED_VOTE_ID = None EXPECTED_DG_PROPOSAL_ID = 5 EXPECTED_VOTE_EVENTS_COUNT = 4 -EXPECTED_DG_EVENTS_COUNT = 66 +EXPECTED_DG_EVENTS_FROM_AGENT = 69 +EXPECTED_DG_EVENTS_COUNT = 70 IPFS_DESCRIPTION_HASH = "bafkreih5app23xbevhswk56r6d2cjdqui5tckki6szo7loi7xe25bfgol4" NETHERMIND_NO_ID = 25 @@ -281,6 +300,8 @@ def check_proxy_implementation(proxy_address, expected_impl): NODE_OPERATORS_REGISTRY_ARAGON_APP_ID = "0x7071f283424072341f856ac9e947e7ec0eb68719f757a7e785979b6b8717579d" SIMPLE_DVT_ARAGON_APP_ID = "0xe1635b63b5f7b5e545f2a637558a4029dea7905361a2f0fc28c66e9136cf86a4" +OLD_KILN_ADDRESS = "0x14D5d5B71E048d2D75a39FfC5B407e3a3AB6F314" +NEW_KILN_ADDRESS = "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045" # todo: replace with the real one MAX_VALIDATORS_PER_REPORT = 600 MAX_EXIT_REQUESTS_LIMIT = 11200 EXITS_PER_FRAME = 1 @@ -305,6 +326,7 @@ def encode_oracle_upgrade_consensus(oracle_contract, new_version): return (oracle_contract.address, oracle_contract.setConsensusVersion.encode_input(new_version)) # Cast contracts to OssifiableProxy interface to access proxy methods + _ = interface.StETH(STETH) # Loading ABI to parse DG events lido_locator_proxy = interface.OssifiableProxy(contracts.lido_locator.address) vebo_proxy = interface.OssifiableProxy(contracts.validators_exit_bus_oracle.address) withdrawal_vault_proxy = interface.OssifiableProxy(contracts.withdrawal_vault.address) @@ -636,7 +658,7 @@ def encode_oracle_upgrade_consensus(oracle_contract, new_version): encode_oz_revoke_role( contract=contracts.csm, role_name="VERIFIER_ROLE", - revoke_from=contracts.cs_verifier + revoke_from=CS_VERIFIER_ADDRESS_OLD ) ]), @@ -811,9 +833,17 @@ def encode_oracle_upgrade_consensus(oracle_contract, new_version): [encode_set_node_operator_name(id=25, name="Twinstake", registry=contracts.node_operators_registry)]), # 68. Change Node Operator ID 17 reward address - agent_forward([encode_set_node_operator_reward_address(id=17, + agent_forward([encode_set_node_operator_reward_address(id=25, rewardAddress="0x36201ed66DbC284132046ee8d99272F8eEeb24c8", - registry=contracts.node_operators_registry)]) + registry=contracts.node_operators_registry)]), + # "69. Remove Kiln guardian" + agent_forward([ + encode_remove_guardian(dsm=contracts.deposit_security_module, guardian_address=OLD_KILN_ADDRESS, quorum_size=4), + ]), + # "70. Add new Kiln guardian" + agent_forward([ + encode_add_guardian(dsm=contracts.deposit_security_module, guardian_address=NEW_KILN_ADDRESS, quorum_size=4), + ]), ] # Convert each dg_item to the expected format @@ -886,7 +916,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g assert get_lido_vote_cid_from_str(find_metadata_by_vote_id(vote_id)) == IPFS_DESCRIPTION_HASH vote_tx: TransactionReceipt = helpers.execute_vote(vote_id=vote_id, accounts=accounts, dao_voting=voting) - # display_voting_events(vote_tx) + #display_voting_events(vote_tx) vote_events = group_voting_events_from_receipt(vote_tx) # ======================================================================= @@ -907,7 +937,6 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g assert len(vote_events) == EXPECTED_VOTE_EVENTS_COUNT, "Unexpected number of dual governance events" assert count_vote_items_by_events(vote_tx, voting.address) == EXPECTED_VOTE_EVENTS_COUNT - print(f'TIMELOCK PROP COUNT: {timelock.getProposalsCount()}') if EXPECTED_DG_PROPOSAL_ID is not None: assert EXPECTED_DG_PROPOSAL_ID == timelock.getProposalsCount() @@ -971,7 +1000,6 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g # Steps 4-6: Check VEBO consensus version management initial_vebo_consensus_version = contracts.validators_exit_bus_oracle.getConsensusVersion() assert initial_vebo_consensus_version < VEBO_CONSENSUS_VERSION, f"VEBO consensus version should be less than {VEBO_CONSENSUS_VERSION}" - # FIXME: Why no check for the role SUBMIT_REPORT_HASH_ROLE? # Step 7: Check TWG role for CS Ejector initial state add_full_withdrawal_request_role = triggerable_withdrawals_gateway.ADD_FULL_WITHDRAWAL_REQUEST_ROLE() @@ -1093,43 +1121,29 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g contracts.cs_fee_distributor.getInitializedVersion() # CSM Steps 38-40: CSAccounting roles (pre-vote state) - assert contracts.cs_accounting.hasRole(contracts.cs_accounting.SET_BOND_CURVE_ROLE(), - contracts.csm.address), "CSM should have SET_BOND_CURVE_ROLE on CSAccounting before vote" - assert contracts.cs_accounting.hasRole(web3.keccak(text="RESET_BOND_CURVE_ROLE"), - contracts.csm.address), "CSM should have RESET_BOND_CURVE_ROLE on CSAccounting before vote" - assert contracts.cs_accounting.hasRole(web3.keccak(text="RESET_BOND_CURVE_ROLE"), - CSM_COMMITTEE_MS), "CSM committee should have RESET_BOND_CURVE_ROLE on CSAccounting before vote" + assert contracts.cs_accounting.hasRole(contracts.cs_accounting.SET_BOND_CURVE_ROLE(), contracts.csm.address), "CSM should have SET_BOND_CURVE_ROLE on CSAccounting before vote" + assert contracts.cs_accounting.hasRole(web3.keccak(text="RESET_BOND_CURVE_ROLE"), contracts.csm.address), "CSM should have RESET_BOND_CURVE_ROLE on CSAccounting before vote" + assert contracts.cs_accounting.hasRole(web3.keccak(text="RESET_BOND_CURVE_ROLE"), CSM_COMMITTEE_MS), "CSM committee should have RESET_BOND_CURVE_ROLE on CSAccounting before vote" # CSM Steps 41-42: CSM roles (pre-vote state) - assert not contracts.csm.hasRole(web3.keccak(text="CREATE_NODE_OPERATOR_ROLE"), - cs_permissionless_gate.address), "Permissionless gate should not have CREATE_NODE_OPERATOR_ROLE on CSM before vote" - assert not contracts.csm.hasRole(web3.keccak(text="CREATE_NODE_OPERATOR_ROLE"), - cs_vetted_gate.address), "Vetted gate should not have CREATE_NODE_OPERATOR_ROLE on CSM before vote" + assert not contracts.csm.hasRole(web3.keccak(text="CREATE_NODE_OPERATOR_ROLE"), cs_permissionless_gate.address), "Permissionless gate should not have CREATE_NODE_OPERATOR_ROLE on CSM before vote" + assert not contracts.csm.hasRole(web3.keccak(text="CREATE_NODE_OPERATOR_ROLE"), cs_vetted_gate.address), "Vetted gate should not have CREATE_NODE_OPERATOR_ROLE on CSM before vote" # CSM Step 43: CSAccounting bond curve role for vetted gate (pre-vote state) - assert not contracts.cs_accounting.hasRole(contracts.cs_accounting.SET_BOND_CURVE_ROLE(), - cs_vetted_gate.address), "Vetted gate should not have SET_BOND_CURVE_ROLE on CSAccounting before vote" + assert not contracts.cs_accounting.hasRole(contracts.cs_accounting.SET_BOND_CURVE_ROLE(), cs_vetted_gate.address), "Vetted gate should not have SET_BOND_CURVE_ROLE on CSAccounting before vote" # CSM Steps 44-45: Verifier roles (pre-vote state) - assert contracts.csm.hasRole(contracts.csm.VERIFIER_ROLE(), - CS_VERIFIER_ADDRESS_OLD), "Old verifier should have VERIFIER_ROLE on CSM before vote" - assert not contracts.csm.hasRole(contracts.csm.VERIFIER_ROLE(), - cs_verifier_v2.address), "New verifier should not have VERIFIER_ROLE on CSM before vote" + assert contracts.csm.hasRole(contracts.csm.VERIFIER_ROLE(), CS_VERIFIER_ADDRESS_OLD), "Old verifier should have VERIFIER_ROLE on CSM before vote" + assert not contracts.csm.hasRole(contracts.csm.VERIFIER_ROLE(), cs_verifier_v2.address), "New verifier should not have VERIFIER_ROLE on CSM before vote" # CSM Steps 46-51: GateSeal roles (pre-vote state) - assert contracts.csm.hasRole(contracts.csm.PAUSE_ROLE(), - CS_GATE_SEAL_ADDRESS), "Old GateSeal should have PAUSE_ROLE on CSM before vote" - assert contracts.cs_accounting.hasRole(contracts.cs_accounting.PAUSE_ROLE(), - CS_GATE_SEAL_ADDRESS), "Old GateSeal should have PAUSE_ROLE on CSAccounting before vote" - assert contracts.cs_fee_oracle.hasRole(contracts.cs_fee_oracle.PAUSE_ROLE(), - CS_GATE_SEAL_ADDRESS), "Old GateSeal should have PAUSE_ROLE on CSFeeOracle before vote" - - assert not contracts.csm.hasRole(contracts.csm.PAUSE_ROLE(), - CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should not have PAUSE_ROLE on CSM before vote" - assert not contracts.cs_accounting.hasRole(contracts.cs_accounting.PAUSE_ROLE(), - CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should not have PAUSE_ROLE on CSAccounting before vote" - assert not contracts.cs_fee_oracle.hasRole(contracts.cs_fee_oracle.PAUSE_ROLE(), - CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should not have PAUSE_ROLE on CSFeeOracle before vote" + assert contracts.csm.hasRole(contracts.csm.PAUSE_ROLE(), CS_GATE_SEAL_ADDRESS), "Old GateSeal should have PAUSE_ROLE on CSM before vote" + assert contracts.cs_accounting.hasRole(contracts.cs_accounting.PAUSE_ROLE(), CS_GATE_SEAL_ADDRESS), "Old GateSeal should have PAUSE_ROLE on CSAccounting before vote" + assert contracts.cs_fee_oracle.hasRole(contracts.cs_fee_oracle.PAUSE_ROLE(), CS_GATE_SEAL_ADDRESS), "Old GateSeal should have PAUSE_ROLE on CSFeeOracle before vote" + + assert not contracts.csm.hasRole(contracts.csm.PAUSE_ROLE(), CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should not have PAUSE_ROLE on CSM before vote" + assert not contracts.cs_accounting.hasRole(contracts.cs_accounting.PAUSE_ROLE(), CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should not have PAUSE_ROLE on CSAccounting before vote" + assert not contracts.cs_fee_oracle.hasRole(contracts.cs_fee_oracle.PAUSE_ROLE(), CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should not have PAUSE_ROLE on CSFeeOracle before vote" # CSM Step 52: Staking Router CSM module state before vote (pre-vote state) csm_module_before = contracts.staking_router.getStakingModule(CS_MODULE_ID) @@ -1139,22 +1153,15 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g assert csm_priority_exit_threshold_before != CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP, f"CSM priority exit threshold should not be {CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP} before vote, current: {csm_priority_exit_threshold_before}" # Gate Seals: Check initial states before vote - assert contracts.withdrawal_queue.hasRole(contracts.withdrawal_queue.PAUSE_ROLE(), - OLD_GATE_SEAL_ADDRESS), "Old GateSeal should have PAUSE_ROLE on WithdrawalQueue before vote" - assert contracts.validators_exit_bus_oracle.hasRole(contracts.validators_exit_bus_oracle.PAUSE_ROLE(), - OLD_GATE_SEAL_ADDRESS), "Old GateSeal should have PAUSE_ROLE on VEBO before vote" - assert not contracts.withdrawal_queue.hasRole(contracts.withdrawal_queue.PAUSE_ROLE(), - NEW_WQ_GATE_SEAL), "New WQ GateSeal should not have PAUSE_ROLE on WithdrawalQueue before vote" - assert not contracts.validators_exit_bus_oracle.hasRole(contracts.validators_exit_bus_oracle.PAUSE_ROLE(), - NEW_TW_GATE_SEAL), "New TW GateSeal should not have PAUSE_ROLE on VEBO before vote" - assert not triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.PAUSE_ROLE(), - NEW_TW_GATE_SEAL), "New TW GateSeal should not have PAUSE_ROLE on TWG before vote" + assert contracts.withdrawal_queue.hasRole(contracts.withdrawal_queue.PAUSE_ROLE(), OLD_GATE_SEAL_ADDRESS), "Old GateSeal should have PAUSE_ROLE on WithdrawalQueue before vote" + assert contracts.validators_exit_bus_oracle.hasRole(contracts.validators_exit_bus_oracle.PAUSE_ROLE(), OLD_GATE_SEAL_ADDRESS), "Old GateSeal should have PAUSE_ROLE on VEBO before vote" + assert not contracts.withdrawal_queue.hasRole(contracts.withdrawal_queue.PAUSE_ROLE(), NEW_WQ_GATE_SEAL), "New WQ GateSeal should not have PAUSE_ROLE on WithdrawalQueue before vote" + assert not contracts.validators_exit_bus_oracle.hasRole(contracts.validators_exit_bus_oracle.PAUSE_ROLE(), NEW_TW_GATE_SEAL), "New TW GateSeal should not have PAUSE_ROLE on VEBO before vote" + assert not triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.PAUSE_ROLE(), NEW_TW_GATE_SEAL), "New TW GateSeal should not have PAUSE_ROLE on TWG before vote" # ResealManager: Check initial states before vote - assert not triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.PAUSE_ROLE(), - RESEAL_MANAGER), "ResealManager should not have PAUSE_ROLE on TWG before vote" - assert not triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.RESUME_ROLE(), - RESEAL_MANAGER), "ResealManager should not have RESUME_ROLE on TWG before vote" + assert not triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.PAUSE_ROLE(), RESEAL_MANAGER), "ResealManager should not have PAUSE_ROLE on TWG before vote" + assert not triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.RESUME_ROLE(), RESEAL_MANAGER), "ResealManager should not have RESUME_ROLE on TWG before vote" # Rename Nethermind NO nethermind_no_data_before = no_registry.getNodeOperator(NETHERMIND_NO_ID, True) @@ -1168,37 +1175,32 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g if timelock.getProposalDetails(EXPECTED_DG_PROPOSAL_ID)["status"] == PROPOSAL_STATUS["scheduled"]: chain.sleep(timelock.getAfterScheduleDelay() + 1) dg_tx: TransactionReceipt = timelock.execute(EXPECTED_DG_PROPOSAL_ID, {"from": stranger}) - #display_dg_events(dg_tx) + display_dg_events(dg_tx) dg_events = group_dg_events_from_receipt( dg_tx, timelock=EMERGENCY_PROTECTED_TIMELOCK, admin_executor=DUAL_GOVERNANCE_ADMIN_EXECUTOR, ) - assert count_vote_items_by_events(dg_tx, AGENT) == EXPECTED_DG_EVENTS_COUNT + assert count_vote_items_by_events(dg_tx, AGENT) == EXPECTED_DG_EVENTS_FROM_AGENT assert len(dg_events) == EXPECTED_DG_EVENTS_COUNT # === DG EXECUTION EVENTS VALIDATION === # 0. Lido Locator upgrade events - validate_proxy_upgrade_event(dg_execution_events[0], LIDO_LOCATOR_IMPL, - emitted_by=contracts.lido_locator) + validate_proxy_upgrade_event(dg_events[0], LIDO_LOCATOR_IMPL, emitted_by=contracts.lido_locator) # 1. VEBO upgrade events - validate_proxy_upgrade_event(dg_execution_events[1], VALIDATORS_EXIT_BUS_ORACLE_IMPL, - emitted_by=contracts.validators_exit_bus_oracle) + validate_proxy_upgrade_event(dg_events[1], VALIDATORS_EXIT_BUS_ORACLE_IMPL, emitted_by=contracts.validators_exit_bus_oracle) # 2. VEBO finalize upgrade events - validate_contract_version_set_event(dg_execution_events[2], version=2, - emitted_by=contracts.validators_exit_bus_oracle) - assert 'ExitRequestsLimitSet' in dg_execution_events[2], "ExitRequestsLimitSet event not found" - assert dg_execution_events[2]['ExitRequestsLimitSet'][0][ - 'maxExitRequestsLimit'] == 11200, "Wrong maxExitRequestsLimit" - assert dg_execution_events[2]['ExitRequestsLimitSet'][0]['exitsPerFrame'] == 1, "Wrong exitsPerFrame" - assert dg_execution_events[2]['ExitRequestsLimitSet'][0][ - 'frameDurationInSec'] == 48, "Wrong frameDurationInSec" + validate_contract_version_set_event(dg_events[2], version=2, emitted_by=contracts.validators_exit_bus_oracle) + assert 'ExitRequestsLimitSet' in dg_events[2], "ExitRequestsLimitSet event not found" + assert dg_events[2]['ExitRequestsLimitSet'][0]['maxExitRequestsLimit'] == MAX_EXIT_REQUESTS_LIMIT, "Wrong maxExitRequestsLimit" + assert dg_events[2]['ExitRequestsLimitSet'][0]['exitsPerFrame'] == EXITS_PER_FRAME, "Wrong exitsPerFrame" + assert dg_events[2]['ExitRequestsLimitSet'][0]['frameDurationInSec'] == FRAME_DURATION_IN_SEC, "Wrong frameDurationInSec" # 3. Grant VEBO MANAGE_CONSENSUS_VERSION_ROLE to Agent validate_role_grant_event( - dg_execution_events[3], + dg_events[3], role_hash=web3.keccak(text="MANAGE_CONSENSUS_VERSION_ROLE").hex(), account=contracts.agent.address, emitted_by=contracts.validators_exit_bus_oracle @@ -1206,7 +1208,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g # 4. Set VEBO consensus version to 4 validate_consensus_version_set_event( - dg_execution_events[4], + dg_events[4], new_version=4, prev_version=3, emitted_by=contracts.validators_exit_bus_oracle @@ -1214,7 +1216,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g # 5. Revoke VEBO MANAGE_CONSENSUS_VERSION_ROLE from Agent validate_role_revoke_event( - dg_execution_events[5], + dg_events[5], role_hash=web3.keccak(text="MANAGE_CONSENSUS_VERSION_ROLE").hex(), account=contracts.agent.address, emitted_by=contracts.validators_exit_bus_oracle @@ -1222,7 +1224,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g # 6. Grant VEBO SUBMIT_REPORT_HASH_ROLE to EasyTrack executor validate_role_grant_event( - dg_execution_events[6], + dg_events[6], role_hash=web3.keccak(text="SUBMIT_REPORT_HASH_ROLE").hex(), account=EASYTRACK_EVMSCRIPT_EXECUTOR, emitted_by=contracts.validators_exit_bus_oracle @@ -1230,7 +1232,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g # 7. Grant TWG ADD_FULL_WITHDRAWAL_REQUEST_ROLE to CS Ejector validate_role_grant_event( - dg_execution_events[7], + dg_events[7], role_hash=web3.keccak(text="ADD_FULL_WITHDRAWAL_REQUEST_ROLE").hex(), account=CS_EJECTOR_ADDRESS, emitted_by=triggerable_withdrawals_gateway @@ -1238,33 +1240,29 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g # 8. Grant TWG ADD_FULL_WITHDRAWAL_REQUEST_ROLE to VEBO validate_role_grant_event( - dg_execution_events[8], + dg_events[8], role_hash=web3.keccak(text="ADD_FULL_WITHDRAWAL_REQUEST_ROLE").hex(), account=contracts.validators_exit_bus_oracle.address, emitted_by=triggerable_withdrawals_gateway ) # 9. Connect TWG to Dual Governance tiebreaker - assert 'SealableWithdrawalBlockerAdded' in dg_execution_events[ + assert 'SealableWithdrawalBlockerAdded' in dg_events[ 9], "SealableWithdrawalBlockerAdded event not found" - assert dg_execution_events[9]['SealableWithdrawalBlockerAdded'][0][ - 'sealable'] == TRIGGERABLE_WITHDRAWALS_GATEWAY, "Wrong sealableWithdrawalBlocker" + assert dg_events[9]['SealableWithdrawalBlockerAdded'][0]['sealable'] == TRIGGERABLE_WITHDRAWALS_GATEWAY, "Wrong sealableWithdrawalBlocker" # 10. Update WithdrawalVault implementation - validate_proxy_upgrade_event(dg_execution_events[10], WITHDRAWAL_VAULT_IMPL, - emitted_by=contracts.withdrawal_vault) + validate_proxy_upgrade_event(dg_events[10], WITHDRAWAL_VAULT_IMPL, emitted_by=contracts.withdrawal_vault) # 11. Call finalizeUpgrade_v2 on WithdrawalVault - validate_contract_version_set_event(dg_execution_events[11], version=2, - emitted_by=contracts.withdrawal_vault) + validate_contract_version_set_event(dg_events[11], version=2, emitted_by=contracts.withdrawal_vault) # 12. Update AO implementation - validate_proxy_upgrade_event(dg_execution_events[12], ACCOUNTING_ORACLE_IMPL, - emitted_by=contracts.accounting_oracle) + validate_proxy_upgrade_event(dg_events[12], ACCOUNTING_ORACLE_IMPL, emitted_by=contracts.accounting_oracle) # 13. Grant AO MANAGE_CONSENSUS_VERSION_ROLE to the AGENT validate_role_grant_event( - dg_execution_events[13], + dg_events[13], role_hash=web3.keccak(text="MANAGE_CONSENSUS_VERSION_ROLE").hex(), account=contracts.agent.address, emitted_by=contracts.accounting_oracle @@ -1272,7 +1270,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g # 14. Bump AO consensus version to 4 validate_consensus_version_set_event( - dg_execution_events[14], + dg_events[14], new_version=4, prev_version=3, emitted_by=contracts.accounting_oracle @@ -1280,27 +1278,24 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g # 15. Revoke AO MANAGE_CONSENSUS_VERSION_ROLE from the AGENT validate_role_revoke_event( - dg_execution_events[15], + dg_events[15], role_hash=web3.keccak(text="MANAGE_CONSENSUS_VERSION_ROLE").hex(), account=contracts.agent.address, emitted_by=contracts.accounting_oracle ) # 16. Call finalizeUpgrade_v3() on AO - validate_contract_version_set_event(dg_execution_events[16], version=3, - emitted_by=contracts.accounting_oracle) + validate_contract_version_set_event(dg_events[16], version=3, emitted_by=contracts.accounting_oracle) # 17. Update SR implementation - validate_proxy_upgrade_event(dg_execution_events[17], STAKING_ROUTER_IMPL, - emitted_by=contracts.staking_router) + validate_proxy_upgrade_event(dg_events[17], STAKING_ROUTER_IMPL, emitted_by=contracts.staking_router) # 18. Call finalizeUpgrade_v3() on SR - validate_contract_version_set_event(dg_execution_events[18], version=3, - emitted_by=contracts.staking_router) + validate_contract_version_set_event(dg_events[18], version=3, emitted_by=contracts.staking_router) # 19. Grant SR REPORT_VALIDATOR_EXITING_STATUS_ROLE to ValidatorExitVerifier validate_role_grant_event( - dg_execution_events[19], + dg_events[19], role_hash=web3.keccak(text="REPORT_VALIDATOR_EXITING_STATUS_ROLE").hex(), account=VALIDATOR_EXIT_VERIFIER, emitted_by=contracts.staking_router @@ -1308,113 +1303,104 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g # 20. Grant SR REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE to TWG validate_role_grant_event( - dg_execution_events[20], + dg_events[20], role_hash=web3.keccak(text="REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE").hex(), account=triggerable_withdrawals_gateway.address, emitted_by=contracts.staking_router ) # 21. Grant APP_MANAGER_ROLE on Kernel to Voting - assert 'SetPermission' in dg_execution_events[21] - assert dg_execution_events[21]['SetPermission'][0]['allowed'] is True + assert 'SetPermission' in dg_events[21] + assert dg_events[21]['SetPermission'][0]['allowed'] is True # 22. Set new implementation for NOR - assert 'SetApp' in dg_execution_events[22] + assert 'SetApp' in dg_events[22] # 23. Finalize upgrade for NOR - validate_contract_version_set_event(dg_execution_events[23], version=4, - emitted_by=contracts.node_operators_registry) - assert 'ExitDeadlineThresholdChanged' in dg_execution_events[23] - assert dg_execution_events[23]['ExitDeadlineThresholdChanged'][0][ - 'threshold'] == NOR_EXIT_DEADLINE_IN_SEC + validate_contract_version_set_event(dg_events[23], version=4, emitted_by=contracts.node_operators_registry) + assert 'ExitDeadlineThresholdChanged' in dg_events[23] + assert dg_events[23]['ExitDeadlineThresholdChanged'][0]['threshold'] == NOR_EXIT_DEADLINE_IN_SEC # 24. Set new implementation for sDVT - assert 'SetApp' in dg_execution_events[24] + assert 'SetApp' in dg_events[24] # 25. Finalize upgrade for sDVT - validate_contract_version_set_event(dg_execution_events[25], version=4, emitted_by=contracts.simple_dvt) - assert 'ExitDeadlineThresholdChanged' in dg_execution_events[25] - assert dg_execution_events[25]['ExitDeadlineThresholdChanged'][0][ - 'threshold'] == NOR_EXIT_DEADLINE_IN_SEC + validate_contract_version_set_event(dg_events[25], version=4, emitted_by=contracts.simple_dvt) + assert 'ExitDeadlineThresholdChanged' in dg_events[25] + assert dg_events[25]['ExitDeadlineThresholdChanged'][0]['threshold'] == NOR_EXIT_DEADLINE_IN_SEC # 26. Revoke APP_MANAGER_ROLE on Kernel from Voting - assert 'SetPermission' in dg_execution_events[26] - assert dg_execution_events[26]['SetPermission'][0]['allowed'] is False + assert 'SetPermission' in dg_events[26] + assert dg_events[26]['SetPermission'][0]['allowed'] is False # 27. Grant CONFIG_MANAGER_ROLE on OracleDaemonConfig to Agent validate_role_grant_event( - dg_execution_events[27], + dg_events[27], role_hash=contracts.oracle_daemon_config.CONFIG_MANAGER_ROLE().hex(), account=contracts.agent.address, emitted_by=contracts.oracle_daemon_config ) # 28. Unset NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP - assert 'ConfigValueUnset' in dg_execution_events[28] + assert 'ConfigValueUnset' in dg_events[28] assert 'NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP' in \ - dg_execution_events[28]['ConfigValueUnset'][0]['key'] + dg_events[28]['ConfigValueUnset'][0]['key'] # 29. Unset VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS - assert 'ConfigValueUnset' in dg_execution_events[29] - assert 'VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS' in dg_execution_events[29]['ConfigValueUnset'][0]['key'] + assert 'ConfigValueUnset' in dg_events[29] + assert 'VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS' in dg_events[29]['ConfigValueUnset'][0]['key'] # 30. Unset VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS - assert 'ConfigValueUnset' in dg_execution_events[30] - assert 'VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS' in dg_execution_events[30]['ConfigValueUnset'][0]['key'] + assert 'ConfigValueUnset' in dg_events[30] + assert 'VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS' in dg_events[30]['ConfigValueUnset'][0]['key'] # 31. Set EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS - assert 'ConfigValueSet' in dg_execution_events[31] - assert 'EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS' in dg_execution_events[31]['ConfigValueSet'][0]['key'] - assert convert.to_int( - dg_execution_events[31]['ConfigValueSet'][0]['value']) == EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS + assert 'ConfigValueSet' in dg_events[31] + assert 'EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS' in dg_events[31]['ConfigValueSet'][0]['key'] + assert convert.to_int(dg_events[31]['ConfigValueSet'][0]['value']) == EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS # 32. Revoke CONFIG_MANAGER_ROLE from the AGENT validate_role_revoke_event( - dg_execution_events[32], + dg_events[32], role_hash=contracts.oracle_daemon_config.CONFIG_MANAGER_ROLE().hex(), account=contracts.agent.address, emitted_by=contracts.oracle_daemon_config ) # 33. CSM implementation upgrade - validate_proxy_upgrade_event(dg_execution_events[33], CSM_IMPL_V2_ADDRESS, emitted_by=contracts.csm) + validate_proxy_upgrade_event(dg_events[33], CSM_IMPL_V2_ADDRESS, emitted_by=contracts.csm) # 34. CSM finalize upgrade validation - assert 'Initialized' in dg_execution_events[34] - assert dg_execution_events[34]['Initialized'][0]['version'] == CSM_V2_VERSION + assert 'Initialized' in dg_events[34] + assert dg_events[34]['Initialized'][0]['version'] == CSM_V2_VERSION # 35. CSAccounting implementation upgrade - validate_proxy_upgrade_event(dg_execution_events[35], CS_ACCOUNTING_IMPL_V2_ADDRESS, - emitted_by=contracts.cs_accounting) + validate_proxy_upgrade_event(dg_events[35], CS_ACCOUNTING_IMPL_V2_ADDRESS, emitted_by=contracts.cs_accounting) # 36. CSAccounting finalize upgrade with bond curves - assert 'BondCurveAdded' in dg_execution_events[36] - assert len(dg_execution_events[36]['BondCurveAdded']) == len(CS_CURVES) - assert 'Initialized' in dg_execution_events[36] - assert dg_execution_events[36]['Initialized'][0]['version'] == CS_ACCOUNTING_V2_VERSION + assert 'BondCurveAdded' in dg_events[36] + assert len(dg_events[36]['BondCurveAdded']) == len(CS_CURVES) + assert 'Initialized' in dg_events[36] + assert dg_events[36]['Initialized'][0]['version'] == CS_ACCOUNTING_V2_VERSION # 37. CSFeeOracle implementation upgrade - validate_proxy_upgrade_event(dg_execution_events[37], CS_FEE_ORACLE_IMPL_V2_ADDRESS, - emitted_by=contracts.cs_fee_oracle) + validate_proxy_upgrade_event(dg_events[37], CS_FEE_ORACLE_IMPL_V2_ADDRESS, emitted_by=contracts.cs_fee_oracle) # 38. CSFeeOracle finalize upgrade with consensus version - validate_consensus_version_set_event(dg_execution_events[38], new_version=3, prev_version=2, - emitted_by=contracts.cs_fee_oracle) - validate_contract_version_set_event(dg_execution_events[38], version=CS_FEE_ORACLE_V2_VERSION, - emitted_by=contracts.cs_fee_oracle) + validate_consensus_version_set_event(dg_events[38], new_version=3, prev_version=2, emitted_by=contracts.cs_fee_oracle) + validate_contract_version_set_event(dg_events[38], version=CS_FEE_ORACLE_V2_VERSION, emitted_by=contracts.cs_fee_oracle) # 39. CSFeeDistributor implementation upgrade - validate_proxy_upgrade_event(dg_execution_events[39], CS_FEE_DISTRIBUTOR_IMPL_V2_ADDRESS, - emitted_by=contracts.cs_fee_distributor) + validate_proxy_upgrade_event(dg_events[39], CS_FEE_DISTRIBUTOR_IMPL_V2_ADDRESS, emitted_by=contracts.cs_fee_distributor) # 40. CSFeeDistributor finalize upgrade - assert 'RebateRecipientSet' in dg_execution_events[40] - assert 'Initialized' in dg_execution_events[40] - assert dg_execution_events[40]['Initialized'][0]['version'] == CS_FEE_DISTRIBUTOR_V2_VERSION + assert 'RebateRecipientSet' in dg_events[40] + assert 'Initialized' in dg_events[40] + assert dg_events[40]['Initialized'][0]['version'] == CS_FEE_DISTRIBUTOR_V2_VERSION # 41. Revoke SET_BOND_CURVE_ROLE from CSM on CSAccounting validate_role_revoke_event( - dg_execution_events[41], + dg_events[41], role_hash=contracts.cs_accounting.SET_BOND_CURVE_ROLE().hex(), account=contracts.csm.address, emitted_by=contracts.cs_accounting @@ -1422,7 +1408,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g # 42. Revoke RESET_BOND_CURVE_ROLE from CSM on CSAccounting validate_role_revoke_event( - dg_execution_events[42], + dg_events[42], role_hash=web3.keccak(text="RESET_BOND_CURVE_ROLE").hex(), account=contracts.csm.address, emitted_by=contracts.cs_accounting @@ -1430,7 +1416,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g # 43. Revoke RESET_BOND_CURVE_ROLE from CSM committee on CSAccounting validate_role_revoke_event( - dg_execution_events[43], + dg_events[43], role_hash=web3.keccak(text="RESET_BOND_CURVE_ROLE").hex(), account=CSM_COMMITTEE_MS, emitted_by=contracts.cs_accounting @@ -1438,7 +1424,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g # 44. Grant CREATE_NODE_OPERATOR_ROLE to permissionless gate on CSM validate_role_grant_event( - dg_execution_events[44], + dg_events[44], role_hash=contracts.csm.CREATE_NODE_OPERATOR_ROLE().hex(), account=CS_PERMISSIONLESS_GATE_ADDRESS, emitted_by=contracts.csm @@ -1446,7 +1432,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g # 45. Grant CREATE_NODE_OPERATOR_ROLE to vetted gate on CSM validate_role_grant_event( - dg_execution_events[45], + dg_events[45], role_hash=contracts.csm.CREATE_NODE_OPERATOR_ROLE().hex(), account=CS_VETTED_GATE_ADDRESS, emitted_by=contracts.csm @@ -1454,7 +1440,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g # 46. Grant SET_BOND_CURVE_ROLE to vetted gate on CSAccounting validate_role_grant_event( - dg_execution_events[46], + dg_events[46], role_hash=contracts.cs_accounting.SET_BOND_CURVE_ROLE().hex(), account=CS_VETTED_GATE_ADDRESS, emitted_by=contracts.cs_accounting @@ -1462,15 +1448,15 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g # 47. Revoke VERIFIER_ROLE from old verifier on CSM validate_role_revoke_event( - dg_execution_events[47], + dg_events[47], role_hash=contracts.csm.VERIFIER_ROLE().hex(), - account=contracts.cs_verifier.address, + account=CS_VERIFIER_ADDRESS_OLD, emitted_by=contracts.csm ) # 48. Grant VERIFIER_ROLE to new verifier on CSM validate_role_grant_event( - dg_execution_events[48], + dg_events[48], role_hash=contracts.csm.VERIFIER_ROLE().hex(), account=CS_VERIFIER_V2_ADDRESS, emitted_by=contracts.csm @@ -1478,7 +1464,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g # 49. Revoke PAUSE_ROLE from old GateSeal on CSM validate_role_revoke_event( - dg_execution_events[49], + dg_events[49], role_hash=contracts.csm.PAUSE_ROLE().hex(), account=CS_GATE_SEAL_ADDRESS, emitted_by=contracts.csm @@ -1486,7 +1472,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g # 50. Revoke PAUSE_ROLE from old GateSeal on CSAccounting validate_role_revoke_event( - dg_execution_events[50], + dg_events[50], role_hash=contracts.cs_accounting.PAUSE_ROLE().hex(), account=CS_GATE_SEAL_ADDRESS, emitted_by=contracts.cs_accounting @@ -1494,7 +1480,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g # 51. Revoke PAUSE_ROLE from old GateSeal on CSFeeOracle validate_role_revoke_event( - dg_execution_events[51], + dg_events[51], role_hash=contracts.cs_fee_oracle.PAUSE_ROLE().hex(), account=CS_GATE_SEAL_ADDRESS, emitted_by=contracts.cs_fee_oracle @@ -1502,7 +1488,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g # 52. Grant PAUSE_ROLE to new GateSeal on CSM validate_role_grant_event( - dg_execution_events[52], + dg_events[52], role_hash=contracts.csm.PAUSE_ROLE().hex(), account=CS_GATE_SEAL_V2_ADDRESS, emitted_by=contracts.csm @@ -1510,7 +1496,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g # 53. Grant PAUSE_ROLE to new GateSeal on CSAccounting validate_role_grant_event( - dg_execution_events[53], + dg_events[53], role_hash=contracts.cs_accounting.PAUSE_ROLE().hex(), account=CS_GATE_SEAL_V2_ADDRESS, emitted_by=contracts.cs_accounting @@ -1518,7 +1504,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g # 54. Grant PAUSE_ROLE to new GateSeal on CSFeeOracle validate_role_grant_event( - dg_execution_events[54], + dg_events[54], role_hash=contracts.cs_fee_oracle.PAUSE_ROLE().hex(), account=CS_GATE_SEAL_V2_ADDRESS, emitted_by=contracts.cs_fee_oracle @@ -1526,7 +1512,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g # 55. Grant MANAGE_BOND_CURVES_ROLE to agent on CSAccounting validate_role_grant_event( - dg_execution_events[55], + dg_events[55], role_hash=contracts.cs_accounting.MANAGE_BOND_CURVES_ROLE().hex(), account=contracts.agent.address, emitted_by=contracts.cs_accounting @@ -1534,12 +1520,11 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g # 56. Add ICS bond curve ics_curve_id = len(CS_CURVES) - validate_bond_curve_added_event(dg_execution_events[56], curve_id=ics_curve_id, - emitted_by=contracts.cs_accounting) + validate_bond_curve_added_event(dg_events[56], curve_id=ics_curve_id, emitted_by=contracts.cs_accounting) # 57. Revoke MANAGE_BOND_CURVES_ROLE from agent on CSAccounting validate_role_revoke_event( - dg_execution_events[57], + dg_events[57], role_hash=contracts.cs_accounting.MANAGE_BOND_CURVES_ROLE().hex(), account=contracts.agent.address, emitted_by=contracts.cs_accounting @@ -1547,7 +1532,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g # 58. Increase CSM share in Staking Router validate_staking_module_update_event( - dg_execution_events[58], + dg_events[58], module_id=CS_MODULE_ID, share_limit=CS_MODULE_NEW_TARGET_SHARE_BP, priority_share_threshold=CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP, @@ -1561,7 +1546,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g # 59-65. Gate Seals and ResealManager role updates # 59. Revoke PAUSE_ROLE on WithdrawalQueue from the old GateSeal validate_role_revoke_event( - dg_execution_events[59], + dg_events[59], role_hash=contracts.withdrawal_queue.PAUSE_ROLE().hex(), account=OLD_GATE_SEAL_ADDRESS, emitted_by=contracts.withdrawal_queue @@ -1569,7 +1554,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g # 60. Revoke PAUSE_ROLE on ValidatorsExitBusOracle from the old GateSeal validate_role_revoke_event( - dg_execution_events[60], + dg_events[60], role_hash=contracts.validators_exit_bus_oracle.PAUSE_ROLE().hex(), account=OLD_GATE_SEAL_ADDRESS, emitted_by=contracts.validators_exit_bus_oracle @@ -1577,7 +1562,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g # 61. Grant PAUSE_ROLE on WithdrawalQueue to the new WithdrawalQueue GateSeal validate_role_grant_event( - dg_execution_events[61], + dg_events[61], role_hash=contracts.withdrawal_queue.PAUSE_ROLE().hex(), account=NEW_WQ_GATE_SEAL, emitted_by=contracts.withdrawal_queue @@ -1585,7 +1570,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g # 62. Grant PAUSE_ROLE on ValidatorsExitBusOracle to the new Triggerable Withdrawals GateSeal validate_role_grant_event( - dg_execution_events[62], + dg_events[62], role_hash=contracts.validators_exit_bus_oracle.PAUSE_ROLE().hex(), account=NEW_TW_GATE_SEAL, emitted_by=contracts.validators_exit_bus_oracle @@ -1593,7 +1578,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g # 63. Grant PAUSE_ROLE on TriggerableWithdrawalsGateway to the new Triggerable Withdrawals GateSeal validate_role_grant_event( - dg_execution_events[63], + dg_events[63], role_hash=triggerable_withdrawals_gateway.PAUSE_ROLE().hex(), account=NEW_TW_GATE_SEAL, emitted_by=triggerable_withdrawals_gateway @@ -1601,7 +1586,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g # 64. Grant PAUSE_ROLE on TriggerableWithdrawalsGateway to ResealManager validate_role_grant_event( - dg_execution_events[64], + dg_events[64], role_hash=triggerable_withdrawals_gateway.PAUSE_ROLE().hex(), account=RESEAL_MANAGER, emitted_by=triggerable_withdrawals_gateway @@ -1609,7 +1594,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g # 65. Grant RESUME_ROLE on TriggerableWithdrawalsGateway to ResealManager validate_role_grant_event( - dg_execution_events[65], + dg_events[65], role_hash=triggerable_withdrawals_gateway.RESUME_ROLE().hex(), account=RESEAL_MANAGER, emitted_by=triggerable_withdrawals_gateway @@ -1632,6 +1617,18 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g emitted_by=no_registry, is_dg_event=True, ) + # Guardian remove event + validate_remove_guardian_event( + dg_events[68], + OLD_KILN_ADDRESS, + emitted_by=contracts.deposit_security_module.address, + ) + # Guardian add event + validate_add_guardian_event( + dg_events[69], + NEW_KILN_ADDRESS, + emitted_by=contracts.deposit_security_module.address, + ) # Step 1: Validate Lido Locator implementation was updated assert get_ossifiable_proxy_impl( contracts.lido_locator) == LIDO_LOCATOR_IMPL, "Locator implementation should be updated to the new value" @@ -1642,11 +1639,10 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g assert contracts.validators_exit_bus_oracle.getMaxValidatorsPerReport() == 600, "VEBO max validators per report should be set to 600" # Validate exit request limit parameters from finalizeUpgrade_v2 call - # FIXME: Magic numbers. exit_request_limits = contracts.validators_exit_bus_oracle.getExitRequestLimitFullInfo() - assert exit_request_limits[0] == 11200, "maxExitRequestsLimit should be 11200" - assert exit_request_limits[1] == 1, "exitsPerFrame should be 1" - assert exit_request_limits[2] == 48, "frameDurationInSec should be 48 hours in seconds" + assert exit_request_limits[0] == MAX_EXIT_REQUESTS_LIMIT, "maxExitRequestsLimit should be 11200" + assert exit_request_limits[1] == EXITS_PER_FRAME, "exitsPerFrame should be 1" + assert exit_request_limits[2] == FRAME_DURATION_IN_SEC, "frameDurationInSec should be 48 in seconds" # Steps 4-6: Validate VEBO consensus version management assert not contracts.validators_exit_bus_oracle.hasRole( @@ -1655,14 +1651,11 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g assert contracts.validators_exit_bus_oracle.getConsensusVersion() == VEBO_CONSENSUS_VERSION, f"VEBO consensus version should be set to {VEBO_CONSENSUS_VERSION}" # Step 7: Validate EasyTrack VEB SUBMIT_REPORT_HASH_ROLE - assert contracts.validators_exit_bus_oracle.hasRole(submit_report_hash_role, - EASYTRACK_EVMSCRIPT_EXECUTOR), "EasyTrack executor should have SUBMIT_REPORT_HASH_ROLE on VEBO" + assert contracts.validators_exit_bus_oracle.hasRole(submit_report_hash_role, EASYTRACK_EVMSCRIPT_EXECUTOR), "EasyTrack executor should have SUBMIT_REPORT_HASH_ROLE on VEBO" # Steps 8-9: Validate TWG roles - assert triggerable_withdrawals_gateway.hasRole(add_full_withdrawal_request_role, - cs_ejector), "CS Ejector should have ADD_FULL_WITHDRAWAL_REQUEST_ROLE on TWG" - assert triggerable_withdrawals_gateway.hasRole(add_full_withdrawal_request_role, - contracts.validators_exit_bus_oracle), "VEBO should have ADD_FULL_WITHDRAWAL_REQUEST_ROLE on TWG" + assert triggerable_withdrawals_gateway.hasRole(add_full_withdrawal_request_role, cs_ejector), "CS Ejector should have ADD_FULL_WITHDRAWAL_REQUEST_ROLE on TWG" + assert triggerable_withdrawals_gateway.hasRole(add_full_withdrawal_request_role, contracts.validators_exit_bus_oracle), "VEBO should have ADD_FULL_WITHDRAWAL_REQUEST_ROLE on TWG" # Step 10: Validate DualGovernance tiebreaker connection final_tiebreaker_details = contracts.dual_governance.getTiebreakerDetails() @@ -1670,42 +1663,33 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g assert TRIGGERABLE_WITHDRAWALS_GATEWAY in final_tiebreakers, "TWG should be in tiebreaker list after upgrade" # Steps 11-12: Validate Withdrawal Vault upgrade - assert get_wv_contract_proxy_impl( - contracts.withdrawal_vault) == WITHDRAWAL_VAULT_IMPL, "Withdrawal Vault implementation should be updated" + assert get_wv_contract_proxy_impl(contracts.withdrawal_vault) == WITHDRAWAL_VAULT_IMPL, "Withdrawal Vault implementation should be updated" assert contracts.withdrawal_vault.getContractVersion() == 2, "Withdrawal Vault version should be 2 after finalizeUpgrade_v2" # Steps 13-16: Validate Accounting Oracle upgrade assert get_ossifiable_proxy_impl( contracts.accounting_oracle) == ACCOUNTING_ORACLE_IMPL, "Accounting Oracle implementation should be updated" - assert not contracts.accounting_oracle.hasRole(contracts.accounting_oracle.MANAGE_CONSENSUS_VERSION_ROLE(), - contracts.agent), "Agent should not have MANAGE_CONSENSUS_VERSION_ROLE on AO" + assert not contracts.accounting_oracle.hasRole(contracts.accounting_oracle.MANAGE_CONSENSUS_VERSION_ROLE(), contracts.agent), "Agent should not have MANAGE_CONSENSUS_VERSION_ROLE on AO" assert contracts.accounting_oracle.getConsensusVersion() == AO_CONSENSUS_VERSION, f"AO consensus version should be set to {AO_CONSENSUS_VERSION}" # Step 17: Validate AO finalizeUpgrade_v3 assert contracts.accounting_oracle.getContractVersion() == 3, "AO contract version should be 3 after finalizeUpgrade_v3" # Steps 18-21: Validate Staking Router upgrade - assert get_ossifiable_proxy_impl( - contracts.staking_router) == STAKING_ROUTER_IMPL, "Staking Router implementation should be updated" + assert get_ossifiable_proxy_impl(contracts.staking_router) == STAKING_ROUTER_IMPL, "Staking Router implementation should be updated" assert contracts.staking_router.getContractVersion() == 3, "Staking Router version should be 3 after finalizeUpgrade_v3" - assert contracts.staking_router.hasRole(contracts.staking_router.REPORT_VALIDATOR_EXITING_STATUS_ROLE(), - VALIDATOR_EXIT_VERIFIER), "ValidatorExitVerifier should have REPORT_VALIDATOR_EXITING_STATUS_ROLE on SR" - assert contracts.staking_router.hasRole(contracts.staking_router.REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE(), - triggerable_withdrawals_gateway), "TWG should have REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE on SR" + assert contracts.staking_router.hasRole(contracts.staking_router.REPORT_VALIDATOR_EXITING_STATUS_ROLE(), VALIDATOR_EXIT_VERIFIER), "ValidatorExitVerifier should have REPORT_VALIDATOR_EXITING_STATUS_ROLE on SR" + assert contracts.staking_router.hasRole(contracts.staking_router.REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE(), triggerable_withdrawals_gateway), "TWG should have REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE on SR" # Steps 22-27: Validate NOR and sDVT updates - assert not contracts.acl.hasPermission(contracts.agent, contracts.kernel, - app_manager_role), "Agent should not have APP_MANAGER_ROLE after vote" + assert not contracts.acl.hasPermission(contracts.agent, contracts.kernel,app_manager_role), "Agent should not have APP_MANAGER_ROLE after vote" assert contracts.node_operators_registry.getContractVersion() == 4, "Node Operators Registry version should be updated to 4" assert contracts.simple_dvt.getContractVersion() == 4, "Simple DVT version should be updated to 4" - assert contracts.node_operators_registry.exitDeadlineThreshold( - 0) == NOR_EXIT_DEADLINE_IN_SEC, "NOR exit deadline threshold should be set correctly after finalizeUpgrade_v4" - assert contracts.simple_dvt.exitDeadlineThreshold( - 0) == NOR_EXIT_DEADLINE_IN_SEC, "sDVT exit deadline threshold should be set correctly after finalizeUpgrade_v4" + assert contracts.node_operators_registry.exitDeadlineThreshold(0) == NOR_EXIT_DEADLINE_IN_SEC, "NOR exit deadline threshold should be set correctly after finalizeUpgrade_v4" + assert contracts.simple_dvt.exitDeadlineThreshold(0) == NOR_EXIT_DEADLINE_IN_SEC, "sDVT exit deadline threshold should be set correctly after finalizeUpgrade_v4" # Steps 28-33: Validate Oracle Daemon Config changes - assert not contracts.oracle_daemon_config.hasRole(config_manager_role, - contracts.agent), "Agent should not have CONFIG_MANAGER_ROLE on Oracle Daemon Config" + assert not contracts.oracle_daemon_config.hasRole(config_manager_role, contracts.agent), "Agent should not have CONFIG_MANAGER_ROLE on Oracle Daemon Config" for var_name in ['NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP', 'VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS', 'VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS']: try: @@ -1770,7 +1754,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g # Step 48: Validate VERIFIER_ROLE was revoked from old verifier on CSM assert not contracts.csm.hasRole(contracts.csm.VERIFIER_ROLE(), - contracts.cs_verifier.address), "Old verifier should not have VERIFIER_ROLE on CSM after vote" + CS_VERIFIER_ADDRESS_OLD), "Old verifier should not have VERIFIER_ROLE on CSM after vote" # Step 49: Validate VERIFIER_ROLE was granted to new verifier on CSM assert contracts.csm.hasRole(contracts.csm.VERIFIER_ROLE(), @@ -1832,3 +1816,12 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g RESEAL_MANAGER), "ResealManager should have PAUSE_ROLE on TWG after vote" assert triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.RESUME_ROLE(), RESEAL_MANAGER), "ResealManager should have RESUME_ROLE on TWG after vote" + + # 67-68. Rename Node Operator ID 25 from Nethermind to Twinstake + no = contracts.node_operators_registry.getNodeOperator(NETHERMIND_NO_ID, True) + + assert no[1] == NETHERMIND_NO_NAME_NEW + assert no[2] == NETHERMIND_NEW_REWARD_ADDRESS + + assert contracts.deposit_security_module.isGuardian(OLD_KILN_ADDRESS) is False, "Old Kiln address should be removed from guardians" + assert contracts.deposit_security_module.isGuardian(NEW_KILN_ADDRESS) is True, "New Kiln address should be added to guardians" From 13867024281f04db18da925894c9c357b0c2afaa Mon Sep 17 00:00:00 2001 From: hweawer Date: Fri, 19 Sep 2025 07:51:26 +0200 Subject: [PATCH 27/28] Update Kiln address --- scripts/vote_tw_csm2_mainnet.py | 17 ++++++++++------- tests/test_vote_tw_csm2_mainnet.py | 2 +- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/scripts/vote_tw_csm2_mainnet.py b/scripts/vote_tw_csm2_mainnet.py index cc2dc18a4..5b575dc43 100644 --- a/scripts/vote_tw_csm2_mainnet.py +++ b/scripts/vote_tw_csm2_mainnet.py @@ -194,7 +194,7 @@ EASYTRACK_CS_SET_VETTED_GATE_TREE_FACTORY = "0xBc5642bDD6F2a54b01A75605aAe9143525D97308" OLD_KILN_ADDRESS = "0x14D5d5B71E048d2D75a39FfC5B407e3a3AB6F314" -NEW_KILN_ADDRESS = "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045" # todo: replace with the real one +NEW_KILN_ADDRESS = "0x6d22aE126eB2c37F67a1391B37FF4f2863e61389" # ============================= Description ================================== IPFS_DESCRIPTION = "Triggerable withdrawals and CSM v2 upgrade voting" @@ -970,28 +970,31 @@ def get_vote_items(): --- Node Operators Registry rename and reward address change --- 67. Rename Node Operator ID 25 from Nethermind to Twinstake 68. Change Node Operator ID 25 reward address from 0x237DeE529A47750bEcdFa8A59a1D766e3e7B5F91 to 0x36201ed66DbC284132046ee8d99272F8eEeb24c8 +--- Kiln DSM rotation --- +69. Remove Kiln guardian +70. Add new Kiln guardian --- EasyTrack --- -69. Add CSSetVettedGateTree factory to EasyTrack with permissions -70. Add `SubmitValidatorsExitRequestHashes` (SDVT) EVM script factory to Easy Track -71. Add `SubmitValidatorsExitRequestHashes` (Curated Module) EVM script factory to Easy Track""", +71. Add CSSetVettedGateTree factory to EasyTrack with permissions +72. Add `SubmitValidatorsExitRequestHashes` (SDVT) EVM script factory to Easy Track +73. Add `SubmitValidatorsExitRequestHashes` (Curated Module) EVM script factory to Easy Track""", dg_call_script[0], ), ( - "69. Add CSSetVettedGateTree factory to EasyTrack with permissions", + "71. Add CSSetVettedGateTree factory to EasyTrack with permissions", add_evmscript_factory( factory=EASYTRACK_CS_SET_VETTED_GATE_TREE_FACTORY, permissions=(create_permissions(interface.CSVettedGate(CS_VETTED_GATE_ADDRESS), "setTreeParams")), ), ), ( - "70. Add `SubmitValidatorsExitRequestHashes` (SDVT) EVM script factory to Easy Track", + "72. Add `SubmitValidatorsExitRequestHashes` (SDVT) EVM script factory to Easy Track", add_evmscript_factory( factory=EASYTRACK_SDVT_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY, permissions=(create_permissions(contracts.validators_exit_bus_oracle, "submitExitRequestsHash")), ), ), ( - "71. Add `SubmitValidatorsExitRequestHashes` (Curated Module) EVM script factory to Easy Track", + "73. Add `SubmitValidatorsExitRequestHashes` (Curated Module) EVM script factory to Easy Track", add_evmscript_factory( factory=EASYTRACK_CURATED_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY, permissions=(create_permissions(contracts.validators_exit_bus_oracle, "submitExitRequestsHash")), diff --git a/tests/test_vote_tw_csm2_mainnet.py b/tests/test_vote_tw_csm2_mainnet.py index 66c8b3383..ba2dd136a 100644 --- a/tests/test_vote_tw_csm2_mainnet.py +++ b/tests/test_vote_tw_csm2_mainnet.py @@ -301,7 +301,7 @@ def check_proxy_implementation(proxy_address, expected_impl): SIMPLE_DVT_ARAGON_APP_ID = "0xe1635b63b5f7b5e545f2a637558a4029dea7905361a2f0fc28c66e9136cf86a4" OLD_KILN_ADDRESS = "0x14D5d5B71E048d2D75a39FfC5B407e3a3AB6F314" -NEW_KILN_ADDRESS = "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045" # todo: replace with the real one +NEW_KILN_ADDRESS = "0x6d22aE126eB2c37F67a1391B37FF4f2863e61389" MAX_VALIDATORS_PER_REPORT = 600 MAX_EXIT_REQUESTS_LIMIT = 11200 EXITS_PER_FRAME = 1 From de537fc1d14ae87aac4870ed6975531bac81b622 Mon Sep 17 00:00:00 2001 From: F4ever Date: Fri, 19 Sep 2025 14:13:48 +0200 Subject: [PATCH 28/28] Revert "Merge branch 'feat/next-vote' of github.com:lidofinance/scripts into revert-458-revert-455-feat/tw-and-csmv2" This reverts commit dd1f817436224337d6534e4a80b94206eefd68d5, reversing changes made to 90aee1c118d80fbc842ba4967fa17a653edd8e56. --- .yarn/install-state.gz | Bin 334018 -> 0 bytes .yarnrc.yml | 1 - .../test_vote_dg_easy_track_tw_holesky.py | 3 +- archive/tests/test_vote_tw_csm2_hoodi.py | 2 +- .../test_vote_update_sandbox_impl_holesky.py | 1 + configs/config_holesky.py | 15 +- configs/config_hoodi.py | 34 +- configs/config_mainnet.py | 11 +- interfaces/CSExitPenalties.json | 2 +- interfaces/CSModule.json | 2 +- interfaces/CSParametersRegistry.json | 1 - interfaces/CSVerifierV2.json | 2 +- package.json | 2 +- scripts/ci/prepare_environment.py | 2 +- scripts/vote_tw_csm2_mainnet.py | 1039 --- tests/acceptance/test_csm.py | 137 +- tests/regression/test_csm.py | 220 +- tests/test_vote_tw_csm2_mainnet.py | 1827 ----- utils/config.py | 17 +- utils/dsm.py | 13 - utils/test/csm_helpers.py | 216 +- .../test/event_validators/dual_governance.py | 8 +- utils/test/extra_data.py | 10 +- utils/test/oracle_report_helpers.py | 3 - utils/test/staking_router_helpers.py | 8 +- yarn.lock | 6603 +++++++---------- 26 files changed, 2785 insertions(+), 7394 deletions(-) delete mode 100644 .yarn/install-state.gz delete mode 100644 .yarnrc.yml delete mode 100644 interfaces/CSParametersRegistry.json delete mode 100644 scripts/vote_tw_csm2_mainnet.py delete mode 100644 tests/test_vote_tw_csm2_mainnet.py diff --git a/.yarn/install-state.gz b/.yarn/install-state.gz deleted file mode 100644 index 8d9d80bcdb330e08a6ce82300f0eeef5cc0dd4f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 334018 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�Ft~Ik@qxQz8!&=~m;M=H5w31mFI0u9fB6 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

@Z|P$at+H4~M#I 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 Tuple[Callable, Callable] | None: f"'start_vote' and/or 'get_vote_items' not found in {script_path}." ) except Exception as e: - raise RuntimeError(f"An unexpected error occurred while importing from {script_path}: {e}") + raise RuntimeError(f"An unexpected error occurred while importing from {script_path}: {e}") \ No newline at end of file diff --git a/scripts/vote_tw_csm2_mainnet.py b/scripts/vote_tw_csm2_mainnet.py deleted file mode 100644 index 5b575dc43..000000000 --- a/scripts/vote_tw_csm2_mainnet.py +++ /dev/null @@ -1,1039 +0,0 @@ -""" -Vote 2025__
[MAINNET] - ---- Locator -1. Update locator implementation ---- VEB -2. Update VEBO implementation -3. Call finalizeUpgrade_v2(maxValidatorsPerReport, maxExitRequestsLimit, exitsPerFrame, frameDurationInSec) on VEBO -4. Grant VEBO role MANAGE_CONSENSUS_VERSION_ROLE to the AGENT -5. Bump VEBO consensus version to `4` -6. Revoke VEBO role MANAGE_CONSENSUS_VERSION_ROLE from the AGENT -7. Grant SUBMIT_REPORT_HASH_ROLE on Validator Exit Bus Oracle to the EasyTrack EVM Script Executor ---- Triggerable Withdrawals Gateway (TWG) -8. Grant TWG role ADD_FULL_WITHDRAWAL_REQUEST_ROLE to the CS Ejector -9. Grant TWG role ADD_FULL_WITHDRAWAL_REQUEST_ROLE to the VEB -10. Connect TRIGGERABLE_WITHDRAWALS_GATEWAY to Dual Governance tiebreaker ---- WV -11. Update WithdrawalVault implementation -12. Call finalizeUpgrade_v2() on WithdrawalVault ---- AO -13. Update Accounting Oracle implementation -14. Grant AO MANAGE_CONSENSUS_VERSION_ROLE to the AGENT -15. Bump AO consensus version to `4` -16. Revoke AO MANAGE_CONSENSUS_VERSION_ROLE from the AGENT -17. Call finalizeUpgrade_v3() on AO ---- SR -18. Update SR implementation -19. Call finalizeUpgrade_v3() on SR -20. Grant SR role REPORT_VALIDATOR_EXITING_STATUS_ROLE to ValidatorExitVerifier -21. Grant SR role REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE to TWG ---- Curated Staking Module -22. Grant APP_MANAGER_ROLE role to the AGENT on Kernel -23. Update `NodeOperatorsRegistry` implementation -24. Call finalizeUpgrade_v4 on Curated Staking Module ---- sDVT -25. Update `SimpleDVT` implementation -26. Call finalizeUpgrade_v4 on sDVT -27. Revoke APP_MANAGER_ROLE role from the AGENT on Kernel ---- Oracle configs --- -28. Grant CONFIG_MANAGER_ROLE role to the AGENT -29. Remove NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP variable from OracleDaemonConfig -30. Remove VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS variable from OracleDaemonConfig -31. Remove VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS variable from OracleDaemonConfig -32. Add EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS variable to OracleDaemonConfig -33. Revoke CONFIG_MANAGER_ROLE role from the AGENT ---- CSM --- -34. Upgrade CSM implementation on proxy -35. Call `finalizeUpgradeV2()` on CSM contract -36. Upgrade CSAccounting implementation on proxy -37. Call `finalizeUpgradeV2(bondCurves)` on CSAccounting contract -38. Upgrade CSFeeOracle implementation on proxy -39. Call `finalizeUpgradeV2(consensusVersion)` on CSFeeOracle contract -40. Upgrade CSFeeDistributor implementation on proxy -41. Call `finalizeUpgradeV2(admin)` on CSFeeDistributor contract -42. Revoke CSAccounting role SET_BOND_CURVE_ROLE from the CSM contract -43. Revoke CSAccounting role RESET_BOND_CURVE_ROLE from the CSM contract -44. Revoke CSAccounting role RESET_BOND_CURVE_ROLE from the CSM committee -45. Grant CSM role CREATE_NODE_OPERATOR_ROLE for the permissionless gate -46. Grant CSM role CREATE_NODE_OPERATOR_ROLE for the vetted gate -47. Grant CSAccounting role SET_BOND_CURVE_ROLE for the vetted gate -48. Revoke role VERIFIER_ROLE from the previous instance of the Verifier contract -49. Grant role VERIFIER_ROLE to the new instance of the Verifier contract -50. Revoke CSM role PAUSE_ROLE from the previous GateSeal instance -51. Revoke CSAccounting role PAUSE_ROLE from the previous GateSeal instance -52. Revoke CSFeeOracle role PAUSE_ROLE from the previous GateSeal instance -53. Grant CSM role PAUSE_ROLE for the new GateSeal instance -54. Grant CSAccounting role PAUSE_ROLE for the new GateSeal instance -55. Grant CSFeeOracle role PAUSE_ROLE for the new GateSeal instance -56. Grant MANAGE_BOND_CURVES_ROLE to the AGENT -57. Add Identified Community Stakers Gate Bond Curve -58. Revoke MANAGE_BOND_CURVES_ROLE from the AGENT -59. Increase CSM share in Staking Router from 15% to 16% ---- Gate Seals --- -60. Revoke PAUSE_ROLE on WithdrawalQueue from the old GateSeal -61. Revoke PAUSE_ROLE on ValidatorsExitBusOracle from the old GateSeal -62. Grant PAUSE_ROLE on WithdrawalQueue to the new WithdrawalQueue GateSeal -63. Grant PAUSE_ROLE on ValidatorsExitBusOracle to the new Triggerable Withdrawals GateSeal -64. Grant PAUSE_ROLE on TriggerableWithdrawalsGateway to the new Triggerable Withdrawals GateSeal ---- ResealManager --- -65. Grant PAUSE_ROLE on TriggerableWithdrawalsGateway to ResealManager -66. Grant RESUME_ROLE on TriggerableWithdrawalsGateway to ResealManager ---- Node Operators Registry rename and reward address change --- -67. Rename Node Operator ID 25 from Nethermind to Twinstake -68. Change Node Operator ID 25 reward address from 0x237DeE529A47750bEcdFa8A59a1D766e3e7B5F91 to 0x36201ed66DbC284132046ee8d99272F8eEeb24c8 --- DSM rotate guardian --- -69. Remove old Kiln guardian -70. Add new Kiln guardian ---- EasyTrack --- -71. Add CSSetVettedGateTree factory to EasyTrack with permissions -72. Add `SubmitValidatorsExitRequestHashes` (SDVT) EVM script factory to Easy Track -73. Add `SubmitValidatorsExitRequestHashes` (Curated Module) EVM script factory to Easy Track - -# TODO (after vote) Vote #{vote number} passed & executed on ${date+time}, block ${blockNumber}. -""" - -import time - -from typing import Any, Dict -from typing import Tuple -from brownie import interface, web3, convert -from brownie.convert.main import to_uint # type: ignore - -from utils.agent import agent_forward -from utils.config import ( - CSM_COMMITTEE_MS, - CS_MODULE_ID, - CS_MODULE_MODULE_FEE_BP, - CS_MODULE_TREASURY_FEE_BP, - CS_MODULE_MAX_DEPOSITS_PER_BLOCK, - CS_MODULE_MIN_DEPOSIT_BLOCK_DISTANCE, - CS_GATE_SEAL_ADDRESS, - NODE_OPERATORS_REGISTRY_ARAGON_APP_ID, - SIMPLE_DVT_ARAGON_APP_ID, - ARAGON_KERNEL, - AGENT, - contracts, -) -from utils.dsm import encode_remove_guardian, encode_add_guardian -from utils.ipfs import upload_vote_ipfs_description, calculate_vote_ipfs_description -from utils.permissions import encode_oz_grant_role, encode_oz_revoke_role -from utils.easy_track import ( - add_evmscript_factory, - create_permissions, -) -from utils.voting import bake_vote_items, confirm_vote_script, create_vote -from utils.dual_governance import submit_proposals -from utils.mainnet_fork import pass_and_exec_dao_vote -from utils.config import get_deployer_account, get_priority_fee, get_is_live -from utils.node_operators import encode_set_node_operator_name, encode_set_node_operator_reward_address - -# ============================== Addresses =================================== -# New core contracts implementations -LIDO_LOCATOR_IMPL = "0x2C298963FB763f74765829722a1ebe0784f4F5Cf" -ACCOUNTING_ORACLE_IMPL = "0xE9906E543274cebcd335d2C560094089e9547e8d" -VALIDATORS_EXIT_BUS_ORACLE_IMPL = "0x905A211eD6830Cfc95643f0bE2ff64E7f3bf9b94" -WITHDRAWAL_VAULT_IMPL = "0x7D2BAa6094E1C4B60Da4cbAF4A77C3f4694fD53D" -STAKING_ROUTER_IMPL = "0x226f9265CBC37231882b7409658C18bB7738173A" -NODE_OPERATORS_REGISTRY_IMPL = "0x6828b023e737f96B168aCd0b5c6351971a4F81aE" - -TRIGGERABLE_WITHDRAWALS_GATEWAY = "0xDC00116a0D3E064427dA2600449cfD2566B3037B" -VALIDATOR_EXIT_VERIFIER = "0xbDb567672c867DB533119C2dcD4FB9d8b44EC82f" - -# Oracle consensus versions -AO_CONSENSUS_VERSION = 4 -VEBO_CONSENSUS_VERSION = 4 -CSM_CONSENSUS_VERSION = 3 - -# Fixed constants from Holesky version -EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS = 14 * 7200 # 14 days in slots (assuming 12 seconds per slot) -NOR_EXIT_DEADLINE_IN_SEC = 172800 # 172800 - -# VEB parameters from Holesky -MAX_VALIDATORS_PER_REPORT = 600 -MAX_EXIT_REQUESTS_LIMIT = 11200 -EXITS_PER_FRAME = 1 -FRAME_DURATION_IN_SEC = 48 - -# CSM -CS_MODULE_NEW_TARGET_SHARE_BP = 3500 # 3.5% -CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP = 3750 # 3.75% - -CS_ACCOUNTING_IMPL_V2_ADDRESS = "0x6f09d2426c7405C5546413e6059F884D2D03f449" -CS_FEE_DISTRIBUTOR_IMPL_V2_ADDRESS = "0x5DCF7cF7c6645E9E822a379dF046a8b0390251A1" -CS_FEE_ORACLE_IMPL_V2_ADDRESS = "0xe0B234f99E413E27D9Bc31aBba9A49A3e570Da97" -CSM_IMPL_V2_ADDRESS = "0x1eB6d4da13ca9566c17F526aE0715325d7a07665" - -CS_GATE_SEAL_V2_ADDRESS = "0xE1686C2E90eb41a48356c1cC7FaA17629af3ADB3" -CS_EJECTOR_ADDRESS = "0xc72b58aa02E0e98cF8A4a0E9Dce75e763800802C" -CS_PERMISSIONLESS_GATE_ADDRESS = "0xcF33a38111d0B1246A3F38a838fb41D626B454f0" -CS_VETTED_GATE_ADDRESS = "0xB314D4A76C457c93150d308787939063F4Cc67E0" -CS_VERIFIER_V2_ADDRESS = "0xdC5FE1782B6943f318E05230d688713a560063DC" - -CS_VERIFIER_ADDRESS_OLD = "0xeC6Cc185f671F627fb9b6f06C8772755F587b05d" -CS_CURVES = [ - ([1, 2.4 * 10**18], [2, 1.3 * 10**18]), # Default Curve - ([1, 1.5 * 10**18], [2, 1.3 * 10**18]), # Legacy EA Curve -] -CS_ICS_GATE_BOND_CURVE = ([1, 1.5 * 10**18], [2, 1.3 * 10**18]) # Identified Community Stakers Gate Bond Curve - -# Add missing constants -OLD_GATE_SEAL_ADDRESS = "0xf9C9fDB4A5D2AA1D836D5370AB9b28BC1847e178" -NEW_WQ_GATE_SEAL = "0x8A854C4E750CDf24f138f34A9061b2f556066912" -NEW_TW_GATE_SEAL = "0xA6BC802fAa064414AA62117B4a53D27fFfF741F1" -RESEAL_MANAGER = "0x7914b5a1539b97Bd0bbd155757F25FD79A522d24" - -NETHERMIND_NO_ID = 25 -NETHERMIND_NEW_REWARD_ADDRESS = "0x36201ed66DbC284132046ee8d99272F8eEeb24c8" -NETHERMIND_NEW_NO_NAME = "Twinstake" - -# Add EasyTrack constants -EASYTRACK_EVMSCRIPT_EXECUTOR = "0x79a20FD0FA36453B2F45eAbab19bfef43575Ba9E" -EASYTRACK_SDVT_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY = "0xAa3D6A8B52447F272c1E8FAaA06EA06658bd95E2" -EASYTRACK_CURATED_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY = "0x397206ecdbdcb1A55A75e60Fc4D054feC72E5f63" -EASYTRACK_CS_SET_VETTED_GATE_TREE_FACTORY = "0xBc5642bDD6F2a54b01A75605aAe9143525D97308" - -OLD_KILN_ADDRESS = "0x14D5d5B71E048d2D75a39FfC5B407e3a3AB6F314" -NEW_KILN_ADDRESS = "0x6d22aE126eB2c37F67a1391B37FF4f2863e61389" - -# ============================= Description ================================== -IPFS_DESCRIPTION = "Triggerable withdrawals and CSM v2 upgrade voting" - - -def encode_staking_router_proxy_update(implementation: str) -> Tuple[str, str]: - proxy = interface.OssifiableProxy(contracts.staking_router) - return proxy.address, proxy.proxy__upgradeTo.encode_input(implementation) - - -def encode_proxy_upgrade_to(proxy: Any, implementation: str) -> Tuple[str, str]: - proxy = interface.OssifiableProxy(proxy) - return proxy.address, proxy.proxy__upgradeTo.encode_input(implementation) - - -def encode_wv_proxy_upgrade_to(proxy: Any, implementation: str) -> Tuple[str, str]: - proxy = interface.WithdrawalContractProxy(proxy) - - return proxy.address, proxy.proxy_upgradeTo.encode_input(implementation, b"") - - -def encode_oracle_upgrade_consensus(proxy: Any, consensus_version: int) -> Tuple[str, str]: - oracle = interface.BaseOracle(proxy) - return oracle.address, oracle.setConsensusVersion.encode_input(consensus_version) - - -def encode_staking_router_update_csm_module_share() -> Tuple[str, str]: - """Encode call to update CSM share limit""" - return ( - contracts.staking_router.address, - contracts.staking_router.updateStakingModule.encode_input( - CS_MODULE_ID, - CS_MODULE_NEW_TARGET_SHARE_BP, - CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP, - CS_MODULE_MODULE_FEE_BP, - CS_MODULE_TREASURY_FEE_BP, - CS_MODULE_MAX_DEPOSITS_PER_BLOCK, - CS_MODULE_MIN_DEPOSIT_BLOCK_DISTANCE, - ), - ) - - -def to_percent(bp: int) -> float: - """ - Convert basis points to percentage. - """ - return bp / 10000 * 100 - - -def get_vote_items(): - dg_items = [ - # --- locator - # "1. Update locator implementation", - agent_forward([encode_proxy_upgrade_to(contracts.lido_locator, LIDO_LOCATOR_IMPL)]), - # --- VEB - # "2. Update VEBO implementation", - agent_forward([encode_proxy_upgrade_to(contracts.validators_exit_bus_oracle, VALIDATORS_EXIT_BUS_ORACLE_IMPL)]), - # "3. Call finalizeUpgrade_v2 on VEBO", - agent_forward( - [ - ( - contracts.validators_exit_bus_oracle.address, - contracts.validators_exit_bus_oracle.finalizeUpgrade_v2.encode_input( - MAX_VALIDATORS_PER_REPORT, MAX_EXIT_REQUESTS_LIMIT, EXITS_PER_FRAME, FRAME_DURATION_IN_SEC - ), - ) - ] - ), - # "4. Grant VEBO role MANAGE_CONSENSUS_VERSION_ROLE to the AGENT", - agent_forward( - [ - encode_oz_grant_role( - contract=contracts.validators_exit_bus_oracle, - role_name="MANAGE_CONSENSUS_VERSION_ROLE", - grant_to=contracts.agent, - ) - ] - ), - # "5. Bump VEBO consensus version to `4`", - agent_forward([encode_oracle_upgrade_consensus(contracts.validators_exit_bus_oracle, VEBO_CONSENSUS_VERSION)]), - # "6. Revoke VEBO role MANAGE_CONSENSUS_VERSION_ROLE from the AGENT", - agent_forward( - [ - encode_oz_revoke_role( - contract=contracts.validators_exit_bus_oracle, - role_name="MANAGE_CONSENSUS_VERSION_ROLE", - revoke_from=contracts.agent, - ) - ] - ), - # "7. Grant SUBMIT_REPORT_HASH_ROLE on Validator Exit Bus Oracle to the EasyTrack EVM Script Executor", - agent_forward( - [ - encode_oz_grant_role( - contract=contracts.validators_exit_bus_oracle, - role_name="SUBMIT_REPORT_HASH_ROLE", - grant_to=EASYTRACK_EVMSCRIPT_EXECUTOR, - ) - ] - ), - # --- Triggerable Withdrawals Gateway (TWG) - # "8. Grant TWG role ADD_FULL_WITHDRAWAL_REQUEST_ROLE to the CS Ejector", - agent_forward( - [ - encode_oz_grant_role( - contract=interface.TriggerableWithdrawalsGateway(TRIGGERABLE_WITHDRAWALS_GATEWAY), - role_name="ADD_FULL_WITHDRAWAL_REQUEST_ROLE", - grant_to=CS_EJECTOR_ADDRESS, - ) - ] - ), - # "9. Grant TWG role ADD_FULL_WITHDRAWAL_REQUEST_ROLE to the VEB", - agent_forward( - [ - encode_oz_grant_role( - contract=interface.TriggerableWithdrawalsGateway(TRIGGERABLE_WITHDRAWALS_GATEWAY), - role_name="ADD_FULL_WITHDRAWAL_REQUEST_ROLE", - grant_to=contracts.validators_exit_bus_oracle, - ) - ] - ), - # "10. Connect TRIGGERABLE_WITHDRAWALS_GATEWAY to Dual Governance tiebreaker", - ( - contracts.dual_governance.address, - contracts.dual_governance.addTiebreakerSealableWithdrawalBlocker.encode_input( - TRIGGERABLE_WITHDRAWALS_GATEWAY - ), - ), - # --- WV - # "11. Update WithdrawalVault implementation", - agent_forward([encode_wv_proxy_upgrade_to(contracts.withdrawal_vault, WITHDRAWAL_VAULT_IMPL)]), - # "12. Call finalizeUpgrade_v2 on WithdrawalVault", - agent_forward( - [ - ( - contracts.withdrawal_vault.address, - contracts.withdrawal_vault.finalizeUpgrade_v2.encode_input(), - ) - ] - ), - # --- AO - # "13. Update Accounting Oracle implementation", - agent_forward([encode_proxy_upgrade_to(contracts.accounting_oracle, ACCOUNTING_ORACLE_IMPL)]), - # "14. Grant AO MANAGE_CONSENSUS_VERSION_ROLE to the AGENT", - agent_forward( - [ - encode_oz_grant_role( - contract=contracts.accounting_oracle, - role_name="MANAGE_CONSENSUS_VERSION_ROLE", - grant_to=contracts.agent, - ) - ] - ), - # "15. Bump AO consensus version to `4`", - agent_forward([encode_oracle_upgrade_consensus(contracts.accounting_oracle, AO_CONSENSUS_VERSION)]), - # "16. Revoke AO MANAGE_CONSENSUS_VERSION_ROLE from the AGENT", - agent_forward( - [ - encode_oz_revoke_role( - contract=contracts.accounting_oracle, - role_name="MANAGE_CONSENSUS_VERSION_ROLE", - revoke_from=contracts.agent, - ) - ] - ), - # "17. Call finalizeUpgrade_v3() on AO", - agent_forward( - [ - ( - contracts.accounting_oracle.address, - contracts.accounting_oracle.finalizeUpgrade_v3.encode_input(), - ) - ] - ), - # --- SR - # "18. Update SR implementation", - agent_forward([encode_staking_router_proxy_update(STAKING_ROUTER_IMPL)]), - # "19. Call finalizeUpgrade_v3() on SR", - agent_forward( - [ - ( - contracts.staking_router.address, - contracts.staking_router.finalizeUpgrade_v3.encode_input(), - ) - ] - ), - # "20. Grant SR role REPORT_VALIDATOR_EXITING_STATUS_ROLE to ValidatorExitDelayVerifier", - agent_forward( - [ - encode_oz_grant_role( - contract=contracts.staking_router, - role_name="REPORT_VALIDATOR_EXITING_STATUS_ROLE", - grant_to=VALIDATOR_EXIT_VERIFIER, - ) - ] - ), - # "21. Grant SR role REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE to TWG", - agent_forward( - [ - encode_oz_grant_role( - contract=contracts.staking_router, - role_name="REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE", - grant_to=interface.TriggerableWithdrawalsGateway( - TRIGGERABLE_WITHDRAWALS_GATEWAY - ), # FIXME: simply use the address - ) - ] - ), - # --- Curated Staking Module and sDVT - # "22. Grant APP_MANAGER_ROLE role to the AGENT", - agent_forward( - [ - ( - contracts.acl.address, - contracts.acl.grantPermission.encode_input( - AGENT, - ARAGON_KERNEL, - convert.to_uint(web3.keccak(text="APP_MANAGER_ROLE")), # FIXME: no need for to_uint I guess - ), - ) - ] - ), - # "23. Update `NodeOperatorsRegistry` implementation", - agent_forward( - [ - ( - contracts.kernel.address, - contracts.kernel.setApp.encode_input( - contracts.kernel.APP_BASES_NAMESPACE(), - NODE_OPERATORS_REGISTRY_ARAGON_APP_ID, - NODE_OPERATORS_REGISTRY_IMPL, - ), - ) - ] - ), - # "24. Call finalizeUpgrade_v4 on Curated Staking Module", - agent_forward( - [ - ( - interface.NodeOperatorsRegistry(contracts.node_operators_registry).address, - interface.NodeOperatorsRegistry(contracts.node_operators_registry).finalizeUpgrade_v4.encode_input( - NOR_EXIT_DEADLINE_IN_SEC - ), - ) - ] - ), - # "25. Update `SDVT` implementation", - agent_forward( - [ - ( - contracts.kernel.address, - contracts.kernel.setApp.encode_input( - contracts.kernel.APP_BASES_NAMESPACE(), - SIMPLE_DVT_ARAGON_APP_ID, - NODE_OPERATORS_REGISTRY_IMPL, - ), - ) - ] - ), - # "26. Call finalizeUpgrade_v4 on SDVT", - agent_forward( - [ - ( - interface.NodeOperatorsRegistry(contracts.simple_dvt).address, - interface.NodeOperatorsRegistry(contracts.simple_dvt).finalizeUpgrade_v4.encode_input( - NOR_EXIT_DEADLINE_IN_SEC - ), - ) - ] - ), - # "27. Revoke APP_MANAGER_ROLE role from the AGENT", - agent_forward( - [ - ( - contracts.acl.address, - contracts.acl.revokePermission.encode_input( - AGENT, - ARAGON_KERNEL, - convert.to_uint(web3.keccak(text="APP_MANAGER_ROLE")), # FIXME: remove to_uint - ), - ) - ] - ), - # --- Oracle configs - # "28. Grant CONFIG_MANAGER_ROLE role to the AGENT", - agent_forward( - [ - encode_oz_grant_role( - contract=contracts.oracle_daemon_config, - role_name="CONFIG_MANAGER_ROLE", - grant_to=contracts.agent, # FIXME: misleading usage of contract - ) - ] - ), - # "29. Remove NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP variable from OracleDaemonConfig", - agent_forward( - [ - ( - contracts.oracle_daemon_config.address, - contracts.oracle_daemon_config.unset.encode_input("NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP"), - ) - ] - ), - # "30. Remove VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS variable from OracleDaemonConfig", - agent_forward( - [ - ( - contracts.oracle_daemon_config.address, - contracts.oracle_daemon_config.unset.encode_input("VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS"), - ) - ] - ), - # "31. Remove VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS variable from OracleDaemonConfig", - agent_forward( - [ - ( - contracts.oracle_daemon_config.address, - contracts.oracle_daemon_config.unset.encode_input("VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS"), - ) - ] - ), - # "32. Add EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS variable to OracleDaemonConfig", - agent_forward( - [ - ( - contracts.oracle_daemon_config.address, - contracts.oracle_daemon_config.set.encode_input( - "EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS", EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS - ), - ) - ] - ), - # "33. Revoke CONFIG_MANAGER_ROLE role from the AGENT", - agent_forward( - [ - encode_oz_revoke_role( - contract=contracts.oracle_daemon_config, - role_name="CONFIG_MANAGER_ROLE", - revoke_from=contracts.agent, # FIXME: typing says its str - ) - ] - ), - # --- CSM - # "34. Upgrade CSM implementation on proxy", - agent_forward( - [ - encode_proxy_upgrade_to( - contracts.csm, - CSM_IMPL_V2_ADDRESS, - ) - ] - ), - # "35. Call `finalizeUpgradeV2()` on CSM contract", - agent_forward( - [ - ( - contracts.csm.address, - contracts.csm.finalizeUpgradeV2.encode_input(), - ) - ] - ), - # "36. Upgrade CSAccounting implementation on proxy", - agent_forward( - [ - encode_proxy_upgrade_to( - contracts.cs_accounting, - CS_ACCOUNTING_IMPL_V2_ADDRESS, - ) - ] - ), - # "37. Call `finalizeUpgradeV2(bondCurves)` on CSAccounting contract", - agent_forward( - [ - ( - contracts.cs_accounting.address, - contracts.cs_accounting.finalizeUpgradeV2.encode_input(CS_CURVES), - ) - ] - ), - # "38. Upgrade CSFeeOracle implementation on proxy", - agent_forward( - [ - encode_proxy_upgrade_to( - contracts.cs_fee_oracle, - CS_FEE_ORACLE_IMPL_V2_ADDRESS, - ) - ] - ), - # "39. Call `finalizeUpgradeV2(consensusVersion)` on CSFeeOracle contract", - agent_forward( - [ - ( - contracts.cs_fee_oracle.address, - contracts.cs_fee_oracle.finalizeUpgradeV2.encode_input(CSM_CONSENSUS_VERSION), - ) - ] - ), - # "40. Upgrade CSFeeDistributor implementation on proxy", - agent_forward( - [ - encode_proxy_upgrade_to( - contracts.cs_fee_distributor, - CS_FEE_DISTRIBUTOR_IMPL_V2_ADDRESS, - ) - ] - ), - # "41. Call `finalizeUpgradeV2(admin)` on CSFeeDistributor contract", - agent_forward( - [ - ( - contracts.cs_fee_distributor.address, - contracts.cs_fee_distributor.finalizeUpgradeV2.encode_input(contracts.agent), - ) - ] - ), - # "42. Revoke CSAccounting role SET_BOND_CURVE_ROLE from the CSM contract", - agent_forward( - [ - encode_oz_revoke_role( - contract=contracts.cs_accounting, - role_name="SET_BOND_CURVE_ROLE", - revoke_from=contracts.csm, - ) - ] - ), - # "43. Revoke CSAccounting role RESET_BOND_CURVE_ROLE from the CSM contract", - agent_forward( - [ - encode_oz_revoke_role( - contract=contracts.cs_accounting, - role_name="RESET_BOND_CURVE_ROLE", - revoke_from=contracts.csm, - ) - ] - ), - # "44. Revoke CSAccounting role RESET_BOND_CURVE_ROLE from the CSM committee", - agent_forward( - [ - encode_oz_revoke_role( - contract=contracts.cs_accounting, - role_name="RESET_BOND_CURVE_ROLE", - revoke_from=CSM_COMMITTEE_MS, - ) - ] - ), - # "45. Grant CSM role CREATE_NODE_OPERATOR_ROLE for the permissionless gate", - agent_forward( - [ - encode_oz_grant_role( - contract=contracts.csm, - role_name="CREATE_NODE_OPERATOR_ROLE", - grant_to=CS_PERMISSIONLESS_GATE_ADDRESS, - ) - ] - ), - # "46. Grant CSM role CREATE_NODE_OPERATOR_ROLE for the vetted gate", - agent_forward( - [ - encode_oz_grant_role( - contract=contracts.csm, - role_name="CREATE_NODE_OPERATOR_ROLE", - grant_to=CS_VETTED_GATE_ADDRESS, - ) - ] - ), - # "47. Grant CSAccounting role SET_BOND_CURVE_ROLE for the vetted gate", - agent_forward( - [ - encode_oz_grant_role( - contract=contracts.cs_accounting, - role_name="SET_BOND_CURVE_ROLE", - grant_to=CS_VETTED_GATE_ADDRESS, - ) - ] - ), - # "48. Revoke role VERIFIER_ROLE from the previous instance of the Verifier contract", - agent_forward( - [ - encode_oz_revoke_role( - contract=contracts.csm, - role_name="VERIFIER_ROLE", - revoke_from=CS_VERIFIER_ADDRESS_OLD, - ) - ] - ), - # "49. Grant role VERIFIER_ROLE to the new instance of the Verifier contract", - agent_forward( - [ - encode_oz_grant_role( - contract=contracts.csm, - role_name="VERIFIER_ROLE", - grant_to=CS_VERIFIER_V2_ADDRESS, - ) - ] - ), - # "50. Revoke CSM role PAUSE_ROLE from the previous GateSeal instance", - agent_forward( - [ - encode_oz_revoke_role( - contract=contracts.csm, - role_name="PAUSE_ROLE", - revoke_from=CS_GATE_SEAL_ADDRESS, - ) - ] - ), - # "51. Revoke CSAccounting role PAUSE_ROLE from the previous GateSeal instance", - agent_forward( - [ - encode_oz_revoke_role( - contract=contracts.cs_accounting, - role_name="PAUSE_ROLE", - revoke_from=CS_GATE_SEAL_ADDRESS, - ) - ] - ), - # "52. Revoke CSFeeOracle role PAUSE_ROLE from the previous GateSeal instance", - agent_forward( - [ - encode_oz_revoke_role( - contract=contracts.cs_fee_oracle, - role_name="PAUSE_ROLE", - revoke_from=CS_GATE_SEAL_ADDRESS, - ) - ] - ), - # "53. Grant CSM role PAUSE_ROLE for the new GateSeal instance", - agent_forward( - [ - encode_oz_grant_role( - contract=contracts.csm, - role_name="PAUSE_ROLE", - grant_to=CS_GATE_SEAL_V2_ADDRESS, - ) - ] - ), - # "54. Grant CSAccounting role PAUSE_ROLE for the new GateSeal instance", - agent_forward( - [ - encode_oz_grant_role( - contract=contracts.cs_accounting, - role_name="PAUSE_ROLE", - grant_to=CS_GATE_SEAL_V2_ADDRESS, - ) - ] - ), - # "55. Grant CSFeeOracle role PAUSE_ROLE for the new GateSeal instance", - agent_forward( - [ - encode_oz_grant_role( - contract=contracts.cs_fee_oracle, - role_name="PAUSE_ROLE", - grant_to=CS_GATE_SEAL_V2_ADDRESS, - ) - ] - ), - # "56. Grant MANAGE_BOND_CURVES_ROLE to the AGENT", - agent_forward( - [ - encode_oz_grant_role( - contract=contracts.cs_accounting, - role_name="MANAGE_BOND_CURVES_ROLE", - grant_to=contracts.agent, - ) - ] - ), - # "57. Add Identified Community Stakers Gate Bond Curve", - agent_forward( - [ - ( - contracts.cs_accounting.address, - contracts.cs_accounting.addBondCurve.encode_input(CS_ICS_GATE_BOND_CURVE), - ) - ] - ), - # "58. Revoke MANAGE_BOND_CURVES_ROLE from the AGENT", - agent_forward( - [ - encode_oz_revoke_role( - contract=contracts.cs_accounting, - role_name="MANAGE_BOND_CURVES_ROLE", - revoke_from=contracts.agent, - ) - ] - ), - # "59. Increase CSM share in Staking Router from 15% to 16%", - agent_forward([encode_staking_router_update_csm_module_share()]), - # --- Gate Seals - # "60. Revoke PAUSE_ROLE on WithdrawalQueue from the old GateSeal", - agent_forward( - [ - encode_oz_revoke_role( - contract=contracts.withdrawal_queue, - role_name="PAUSE_ROLE", - revoke_from=OLD_GATE_SEAL_ADDRESS, - ) - ] - ), - # "61. Revoke PAUSE_ROLE on ValidatorsExitBusOracle from the old GateSeal", - agent_forward( - [ - encode_oz_revoke_role( - contract=contracts.validators_exit_bus_oracle, - role_name="PAUSE_ROLE", - revoke_from=OLD_GATE_SEAL_ADDRESS, - ) - ] - ), - # "62. Grant PAUSE_ROLE on WithdrawalQueue to the new WithdrawalQueue GateSeal", - agent_forward( - [ - encode_oz_grant_role( - contract=contracts.withdrawal_queue, - role_name="PAUSE_ROLE", - grant_to=NEW_WQ_GATE_SEAL, - ) - ] - ), - # "63. Grant PAUSE_ROLE on ValidatorsExitBusOracle to the new Triggerable Withdrawals GateSeal", - agent_forward( - [ - encode_oz_grant_role( - contract=contracts.validators_exit_bus_oracle, - role_name="PAUSE_ROLE", - grant_to=NEW_TW_GATE_SEAL, - ) - ] - ), - # "64. Grant PAUSE_ROLE on TriggerableWithdrawalsGateway to the new Triggerable Withdrawals GateSeal", - agent_forward( - [ - encode_oz_grant_role( - contract=interface.TriggerableWithdrawalsGateway(TRIGGERABLE_WITHDRAWALS_GATEWAY), - role_name="PAUSE_ROLE", - grant_to=NEW_TW_GATE_SEAL, - ) - ] - ), - # "65. Grant PAUSE_ROLE on TriggerableWithdrawalsGateway to ResealManager", - agent_forward( - [ - encode_oz_grant_role( - contract=interface.TriggerableWithdrawalsGateway(TRIGGERABLE_WITHDRAWALS_GATEWAY), - role_name="PAUSE_ROLE", - grant_to=RESEAL_MANAGER, - ) - ] - ), - # "66. Grant RESUME_ROLE on TriggerableWithdrawalsGateway to ResealManager", - agent_forward( - [ - encode_oz_grant_role( - contract=interface.TriggerableWithdrawalsGateway(TRIGGERABLE_WITHDRAWALS_GATEWAY), - role_name="RESUME_ROLE", - grant_to=RESEAL_MANAGER, - ) - ] - ), - # "67. Rename Node Operator ID 25 from Nethermind to Twinstake" - agent_forward( - [ - encode_set_node_operator_name(id=NETHERMIND_NO_ID, name=NETHERMIND_NEW_NO_NAME, registry=contracts.node_operators_registry), - ] - ), - # "68. Change Node Operator ID 25 reward address from 0x237DeE529A47750bEcdFa8A59a1D766e3e7B5F91 to 0x36201ed66DbC284132046ee8d99272F8eEeb24c8" - agent_forward( - [ - encode_set_node_operator_reward_address(id=NETHERMIND_NO_ID, rewardAddress=NETHERMIND_NEW_REWARD_ADDRESS, registry=contracts.node_operators_registry), - ] - ), - # "69. Remove Kiln guardian" - agent_forward( - [ - encode_remove_guardian(dsm=contracts.deposit_security_module, guardian_address=OLD_KILN_ADDRESS, quorum_size=4), - ] - ), - # "70. Add new Kiln guardian" - agent_forward( - [ - encode_add_guardian(dsm=contracts.deposit_security_module, guardian_address=NEW_KILN_ADDRESS, quorum_size=4), - ] - ), - ] - dg_call_script = submit_proposals( - [ - ( - dg_items, - "Upgrade to CSM v2 and Triggerable Withdrawals", - ) - ] - ) - - vote_desc_items, call_script_items = zip( - ( - """ ---- Locator -1. Update locator implementation ---- VEB -2. Update VEBO implementation -3. Call finalizeUpgrade_v2(maxValidatorsPerReport, maxExitRequestsLimit, exitsPerFrame, frameDurationInSec) on VEBO -4. Grant VEBO role MANAGE_CONSENSUS_VERSION_ROLE to the AGENT -5. Bump VEBO consensus version to `4` -6. Revoke VEBO role MANAGE_CONSENSUS_VERSION_ROLE from the AGENT -7. Grant SUBMIT_REPORT_HASH_ROLE on Validator Exit Bus Oracle to the EasyTrack EVM Script Executor ---- Triggerable Withdrawals Gateway (TWG) -8. Grant TWG role ADD_FULL_WITHDRAWAL_REQUEST_ROLE to the CS Ejector -9. Grant TWG role ADD_FULL_WITHDRAWAL_REQUEST_ROLE to the VEB -10. Connect TRIGGERABLE_WITHDRAWALS_GATEWAY to Dual Governance tiebreaker ---- WV -11. Update WithdrawalVault implementation -12. Call finalizeUpgrade_v2() on WithdrawalVault ---- AO -13. Update Accounting Oracle implementation -14. Grant AO MANAGE_CONSENSUS_VERSION_ROLE to the AGENT -15. Bump AO consensus version to `4` -16. Revoke AO MANAGE_CONSENSUS_VERSION_ROLE from the AGENT -17. Call finalizeUpgrade_v3() on AO ---- SR -18. Update SR implementation -19. Call finalizeUpgrade_v3() on SR -20. Grant SR role REPORT_VALIDATOR_EXITING_STATUS_ROLE to ValidatorExitVerifier -21. Grant SR role REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE to TWG ---- Curated Staking Module -22. Grant APP_MANAGER_ROLE role to the AGENT on Kernel -23. Update `NodeOperatorsRegistry` implementation -24. Call finalizeUpgrade_v4 on Curated Staking Module ---- sDVT -25. Update `SimpleDVT` implementation -26. Call finalizeUpgrade_v4 on sDVT -27. Revoke APP_MANAGER_ROLE role from the AGENT on Kernel ---- Oracle configs --- -28. Grant CONFIG_MANAGER_ROLE role to the AGENT -29. Remove NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP variable from OracleDaemonConfig -30. Remove VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS variable from OracleDaemonConfig -31. Remove VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS variable from OracleDaemonConfig -32. Add EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS variable to OracleDaemonConfig -33. Revoke CONFIG_MANAGER_ROLE role from the AGENT ---- CSM --- -34. Upgrade CSM implementation on proxy -35. Call `finalizeUpgradeV2()` on CSM contract -36. Upgrade CSAccounting implementation on proxy -37. Call `finalizeUpgradeV2(bondCurves)` on CSAccounting contract -38. Upgrade CSFeeOracle implementation on proxy -39. Call `finalizeUpgradeV2(consensusVersion)` on CSFeeOracle contract -40. Upgrade CSFeeDistributor implementation on proxy -41. Call `finalizeUpgradeV2(admin)` on CSFeeDistributor contract -42. Revoke CSAccounting role SET_BOND_CURVE_ROLE from the CSM contract -43. Revoke CSAccounting role RESET_BOND_CURVE_ROLE from the CSM contract -44. Revoke CSAccounting role RESET_BOND_CURVE_ROLE from the CSM committee -45. Grant CSM role CREATE_NODE_OPERATOR_ROLE for the permissionless gate -46. Grant CSM role CREATE_NODE_OPERATOR_ROLE for the vetted gate -47. Grant CSAccounting role SET_BOND_CURVE_ROLE for the vetted gate -48. Revoke role VERIFIER_ROLE from the previous instance of the Verifier contract -49. Grant role VERIFIER_ROLE to the new instance of the Verifier contract -50. Revoke CSM role PAUSE_ROLE from the previous GateSeal instance -51. Revoke CSAccounting role PAUSE_ROLE from the previous GateSeal instance -52. Revoke CSFeeOracle role PAUSE_ROLE from the previous GateSeal instance -53. Grant CSM role PAUSE_ROLE for the new GateSeal instance -54. Grant CSAccounting role PAUSE_ROLE for the new GateSeal instance -55. Grant CSFeeOracle role PAUSE_ROLE for the new GateSeal instance -56. Grant MANAGE_BOND_CURVES_ROLE to the AGENT -57. Add Identified Community Stakers Gate Bond Curve -58. Revoke MANAGE_BOND_CURVES_ROLE from the AGENT -59. Increase CSM share in Staking Router from 15% to 16% ---- Gate Seals --- -60. Revoke PAUSE_ROLE on WithdrawalQueue from the old GateSeal -61. Revoke PAUSE_ROLE on ValidatorsExitBusOracle from the old GateSeal -62. Grant PAUSE_ROLE on WithdrawalQueue to the new WithdrawalQueue GateSeal -63. Grant PAUSE_ROLE on ValidatorsExitBusOracle to the new Triggerable Withdrawals GateSeal -64. Grant PAUSE_ROLE on TriggerableWithdrawalsGateway to the new Triggerable Withdrawals GateSeal ---- ResealManager --- -65. Grant PAUSE_ROLE on TriggerableWithdrawalsGateway to ResealManager -66. Grant RESUME_ROLE on TriggerableWithdrawalsGateway to ResealManager ---- Node Operators Registry rename and reward address change --- -67. Rename Node Operator ID 25 from Nethermind to Twinstake -68. Change Node Operator ID 25 reward address from 0x237DeE529A47750bEcdFa8A59a1D766e3e7B5F91 to 0x36201ed66DbC284132046ee8d99272F8eEeb24c8 ---- Kiln DSM rotation --- -69. Remove Kiln guardian -70. Add new Kiln guardian ---- EasyTrack --- -71. Add CSSetVettedGateTree factory to EasyTrack with permissions -72. Add `SubmitValidatorsExitRequestHashes` (SDVT) EVM script factory to Easy Track -73. Add `SubmitValidatorsExitRequestHashes` (Curated Module) EVM script factory to Easy Track""", - dg_call_script[0], - ), - ( - "71. Add CSSetVettedGateTree factory to EasyTrack with permissions", - add_evmscript_factory( - factory=EASYTRACK_CS_SET_VETTED_GATE_TREE_FACTORY, - permissions=(create_permissions(interface.CSVettedGate(CS_VETTED_GATE_ADDRESS), "setTreeParams")), - ), - ), - ( - "72. Add `SubmitValidatorsExitRequestHashes` (SDVT) EVM script factory to Easy Track", - add_evmscript_factory( - factory=EASYTRACK_SDVT_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY, - permissions=(create_permissions(contracts.validators_exit_bus_oracle, "submitExitRequestsHash")), - ), - ), - ( - "73. Add `SubmitValidatorsExitRequestHashes` (Curated Module) EVM script factory to Easy Track", - add_evmscript_factory( - factory=EASYTRACK_CURATED_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY, - permissions=(create_permissions(contracts.validators_exit_bus_oracle, "submitExitRequestsHash")), - ), - ), - ) - - return vote_desc_items, call_script_items - - -def start_vote(tx_params: Dict[str, str], silent: bool = False): - vote_desc_items, call_script_items = get_vote_items() - vote_items = bake_vote_items(list(vote_desc_items), list(call_script_items)) - - desc_ipfs = ( - calculate_vote_ipfs_description(IPFS_DESCRIPTION) if silent else upload_vote_ipfs_description(IPFS_DESCRIPTION) - ) - - assert confirm_vote_script(vote_items, silent, desc_ipfs) - - return create_vote(vote_items, tx_params, desc_ipfs=desc_ipfs) - - -def main(): - tx_params: Dict[str, str] = {"from": get_deployer_account().address} - if get_is_live(): - tx_params["priority_fee"] = get_priority_fee() - - vote_id, _ = start_vote(tx_params=tx_params, silent=False) - vote_id >= 0 and print(f"Vote created: {vote_id}.") - - time.sleep(5) # hack for waiting thread #2. - - -def start_and_execute_vote_on_fork_manual(): - if get_is_live(): - raise Exception("This script is for local testing only.") - - tx_params = {"from": get_deployer_account()} - vote_id, _ = start_vote(tx_params=tx_params, silent=True) - print(f"Vote created: {vote_id}.") - pass_and_exec_dao_vote(int(vote_id), step_by_step=True) diff --git a/tests/acceptance/test_csm.py b/tests/acceptance/test_csm.py index 861750918..ca33c1cef 100644 --- a/tests/acceptance/test_csm.py +++ b/tests/acceptance/test_csm.py @@ -24,11 +24,8 @@ CS_ORACLE_EPOCHS_PER_FRAME, ORACLE_QUORUM, ORACLE_COMMITTEE, - CS_PARAMS_REGISTRY_ADDRESS, - CS_EXIT_PENALTIES_ADDRESS, - CS_STRIKES_ADDRESS, - CS_EJECTOR_ADDRESS ) +from utils.test.helpers import ETH contracts: ContractsLazyLoader = contracts @@ -41,104 +38,61 @@ def _str_to_bytes32(s: str) -> str: def csm(): return contracts.csm +@pytest.fixture(scope="module") +def early_adoption(): + return contracts.cs_early_adoption @pytest.fixture(scope="module") def fee_distributor(): return contracts.cs_fee_distributor - @pytest.fixture(scope="module") def fee_oracle(): return contracts.cs_fee_oracle - @pytest.fixture(scope="module") def hash_consensus(): return contracts.csm_hash_consensus - @pytest.fixture(scope="module") def accounting(): return contracts.cs_accounting - @pytest.fixture(scope="module") def verifier(): return contracts.cs_verifier -@pytest.fixture(scope="module") -def permissionless_gate(): - return contracts.cs_permissionless_gate - - -@pytest.fixture(scope="module") -def vetted_gate(): - return contracts.cs_vetted_gate - - -@pytest.fixture(scope="module") -def parameters_registry(): - return contracts.cs_parameters_registry - - -@pytest.fixture(scope="module") -def ejector(): - return contracts.cs_ejector - - -@pytest.fixture(scope="module") -def strikes(): - return contracts.cs_strikes - - -@pytest.fixture(scope="module") -def exit_penalties(): - return contracts.cs_exit_penalties - - @pytest.fixture(scope="module") def lido(): return interface.Lido(LIDO) - -def test_proxy( - csm, - accounting, - fee_distributor, - fee_oracle, - vetted_gate, - strikes, - exit_penalties, -): +def test_proxy(csm, accounting, fee_distributor, fee_oracle): assert interface.OssifiableProxy(csm).proxy__getAdmin() == contracts.agent.address assert interface.OssifiableProxy(accounting).proxy__getAdmin() == contracts.agent.address assert interface.OssifiableProxy(fee_distributor).proxy__getAdmin() == contracts.agent.address assert interface.OssifiableProxy(fee_oracle).proxy__getAdmin() == contracts.agent.address - assert interface.OssifiableProxy(vetted_gate).proxy__getAdmin() == contracts.agent.address - assert interface.OssifiableProxy(strikes).proxy__getAdmin() == contracts.agent.address - assert interface.OssifiableProxy(exit_penalties).proxy__getAdmin() == contracts.agent.address class TestCSM: def test_init_state(self, csm): assert csm.getType() == _str_to_bytes32("community-onchain-v1") assert csm.LIDO_LOCATOR() == LIDO_LOCATOR - assert csm.PARAMETERS_REGISTRY() == CS_PARAMS_REGISTRY_ADDRESS - assert csm.ACCOUNTING() == CS_ACCOUNTING_ADDRESS - assert csm.EXIT_PENALTIES() == CS_EXIT_PENALTIES_ADDRESS + assert csm.accounting() == CS_ACCOUNTING_ADDRESS + assert csm.keyRemovalCharge() == 0 # Updated from 0.02 to 0 in vote 2025/07/16 assert not csm.isPaused() + assert csm.publicRelease() class TestAccounting: def test_initial_state(self, accounting): - assert accounting.MODULE() == CSM_ADDRESS + assert accounting.CSM() == CSM_ADDRESS assert accounting.LIDO_LOCATOR() == LIDO_LOCATOR assert accounting.LIDO() == LIDO assert accounting.WITHDRAWAL_QUEUE() == WITHDRAWAL_QUEUE assert accounting.WSTETH() == WSTETH_TOKEN - assert accounting.FEE_DISTRIBUTOR() == CS_FEE_DISTRIBUTOR_ADDRESS + assert accounting.feeDistributor() == CS_FEE_DISTRIBUTOR_ADDRESS assert accounting.chargePenaltyRecipient() == AGENT assert not accounting.isPaused() @@ -148,14 +102,12 @@ def test_allowances(self, lido): assert lido.allowance(CS_ACCOUNTING_ADDRESS, WITHDRAWAL_QUEUE) == uin256_max assert lido.allowance(CS_ACCOUNTING_ADDRESS, BURNER) == uin256_max - class TestFeeDistributor: def test_initial_state(self, fee_distributor): assert fee_distributor.STETH() == LIDO assert fee_distributor.ACCOUNTING() == CS_ACCOUNTING_ADDRESS assert fee_distributor.ORACLE() == CS_FEE_ORACLE_ADDRESS - assert fee_distributor.rebateRecipient() == AGENT class TestFeeOracle: @@ -163,14 +115,13 @@ class TestFeeOracle: def test_initial_state(self, fee_oracle): assert fee_oracle.SECONDS_PER_SLOT() == CHAIN_SECONDS_PER_SLOT assert fee_oracle.GENESIS_TIME() == CHAIN_GENESIS_TIME - assert fee_oracle.FEE_DISTRIBUTOR() == CS_FEE_DISTRIBUTOR_ADDRESS - assert fee_oracle.STRIKES() == CS_STRIKES_ADDRESS - assert fee_oracle.getContractVersion() == 2 + assert fee_oracle.feeDistributor() == CS_FEE_DISTRIBUTOR_ADDRESS + assert fee_oracle.getContractVersion() == 1 assert fee_oracle.getConsensusContract() == CS_ORACLE_HASH_CONSENSUS_ADDRESS - assert fee_oracle.getConsensusVersion() == 3 + assert fee_oracle.getConsensusVersion() == 2 + assert fee_oracle.avgPerfLeewayBP() == 500 assert not fee_oracle.isPaused() - class TestHashConsensus: def test_initial_state(self, hash_consensus): @@ -180,69 +131,35 @@ def test_initial_state(self, hash_consensus): assert chain_config["genesisTime"] == CHAIN_GENESIS_TIME frame_config = hash_consensus.getFrameConfig() - assert frame_config["initialEpoch"] == 326715 + assert frame_config["initialEpoch"] >= 326715 assert frame_config["epochsPerFrame"] == CS_ORACLE_EPOCHS_PER_FRAME assert frame_config["fastLaneLengthSlots"] == 1800 assert hash_consensus.getQuorum() == ORACLE_QUORUM - assert hash_consensus.getInitialRefSlot() == 10454879 + assert hash_consensus.getInitialRefSlot() >= 326715 * CHAIN_SLOTS_PER_EPOCH - 1 members = hash_consensus.getMembers() assert sorted(members["addresses"]) == sorted(ORACLE_COMMITTEE) assert hash_consensus.getReportProcessor() == CS_FEE_ORACLE_ADDRESS - -def test_permissionless_gate_state(permissionless_gate): - assert permissionless_gate.MODULE() == CSM_ADDRESS - assert permissionless_gate.CURVE_ID() == 0 - - -def test_vetted_gate_state(vetted_gate): - assert vetted_gate.MODULE() == CSM_ADDRESS - assert vetted_gate.curveId() == 2 - - -def test_ejector_state(ejector): - assert ejector.MODULE() == CSM_ADDRESS - assert ejector.STRIKES() == CS_STRIKES_ADDRESS - assert ejector.STAKING_MODULE_ID() == 3 - - -def test_strikes_state(strikes): - assert strikes.MODULE() == CSM_ADDRESS - assert strikes.EXIT_PENALTIES() == CS_EXIT_PENALTIES_ADDRESS - assert strikes.ORACLE() == CS_FEE_ORACLE_ADDRESS - assert strikes.PARAMETERS_REGISTRY() == CS_PARAMS_REGISTRY_ADDRESS - assert strikes.ejector() == CS_EJECTOR_ADDRESS - - -def test_exit_penalties_state(exit_penalties): - assert exit_penalties.MODULE() == CSM_ADDRESS - assert exit_penalties.PARAMETERS_REGISTRY() == CS_PARAMS_REGISTRY_ADDRESS - assert exit_penalties.STRIKES() == CS_STRIKES_ADDRESS - - -def test_parameters_registry_state(parameters_registry): - assert parameters_registry.QUEUE_LOWEST_PRIORITY() == 5 - assert parameters_registry.QUEUE_LEGACY_PRIORITY() == 4 - +def test_early_adoption_state(early_adoption): + assert early_adoption.MODULE() == CSM_ADDRESS + assert early_adoption.CURVE_ID() == 1 def test_verifier_state(verifier): assert verifier.WITHDRAWAL_ADDRESS() == WITHDRAWAL_VAULT assert verifier.MODULE() == CSM_ADDRESS assert verifier.SLOTS_PER_EPOCH() == CHAIN_SLOTS_PER_EPOCH - assert verifier.GI_FIRST_WITHDRAWAL_PREV() == HexString("0x000000000000000000000000000000000000000000000000000000000161c004", "bytes") + with reverts(): # The new CS Verifier (vote 2025/07/16) doesn't have these 2 methods + verifier.GI_HISTORICAL_SUMMARIES_PREV() + verifier.GI_HISTORICAL_SUMMARIES_CURR() + + assert verifier.GI_FIRST_WITHDRAWAL_PREV() == HexString("0x0000000000000000000000000000000000000000000000000000000000e1c004", "bytes") assert verifier.GI_FIRST_WITHDRAWAL_CURR() == HexString("0x000000000000000000000000000000000000000000000000000000000161c004", "bytes") - assert verifier.GI_FIRST_VALIDATOR_PREV() == HexString("0x0000000000000000000000000000000000000000000000000096000000000028", "bytes") + assert verifier.GI_FIRST_VALIDATOR_PREV() == HexString("0x0000000000000000000000000000000000000000000000000056000000000028", "bytes") assert verifier.GI_FIRST_VALIDATOR_CURR() == HexString("0x0000000000000000000000000000000000000000000000000096000000000028", "bytes") - assert verifier.GI_FIRST_HISTORICAL_SUMMARY_PREV() == HexString("0x000000000000000000000000000000000000000000000000000000b600000018", "bytes") - assert verifier.GI_FIRST_HISTORICAL_SUMMARY_CURR() == HexString("0x000000000000000000000000000000000000000000000000000000b600000018", "bytes") - assert verifier.GI_FIRST_BLOCK_ROOT_IN_SUMMARY_PREV() == HexString("0x000000000000000000000000000000000000000000000000000000000040000d", "bytes") - assert verifier.GI_FIRST_BLOCK_ROOT_IN_SUMMARY_CURR() == HexString("0x000000000000000000000000000000000000000000000000000000000040000d", "bytes") - - assert verifier.FIRST_SUPPORTED_SLOT() == 364032 * CHAIN_SLOTS_PER_EPOCH - assert verifier.PIVOT_SLOT() == verifier.FIRST_SUPPORTED_SLOT() - assert verifier.CAPELLA_SLOT() == 194048 * CHAIN_SLOTS_PER_EPOCH + assert verifier.FIRST_SUPPORTED_SLOT() == 8626176 + assert verifier.PIVOT_SLOT() == 11649024 diff --git a/tests/regression/test_csm.py b/tests/regression/test_csm.py index bc0e3c869..2b69d294a 100644 --- a/tests/regression/test_csm.py +++ b/tests/regression/test_csm.py @@ -1,6 +1,6 @@ import pytest -from brownie import reverts, web3, ZERO_ADDRESS, accounts, chain +from brownie import reverts, web3, ZERO_ADDRESS, accounts from utils.balance import set_balance_in_wei from utils.config import ( @@ -10,7 +10,7 @@ from utils.dsm import UnvetArgs, to_bytes, set_single_guardian from utils.evm_script import encode_error from utils.staking_module import calc_module_reward_shares -from utils.test.csm_helpers import csm_add_node_operator, csm_upload_keys, get_ics_members, csm_add_ics_node_operator +from utils.test.csm_helpers import csm_add_node_operator, get_ea_member, csm_upload_keys, get_ea_members from utils.test.deposits_helpers import fill_deposit_buffer from utils.test.helpers import ETH from utils.test.oracle_report_helpers import ( @@ -36,26 +36,11 @@ def csm(): return contracts.csm -@pytest.fixture(scope="module") -def permissionless_gate(): - return contracts.cs_permissionless_gate - - -@pytest.fixture(scope="module") -def vetted_gate(): - return contracts.cs_vetted_gate - - @pytest.fixture(scope="module") def accounting(): return contracts.cs_accounting -@pytest.fixture(scope="module") -def parameters_registry(): - return contracts.cs_parameters_registry - - @pytest.fixture(scope="module") def fee_distributor(): return contracts.cs_fee_distributor @@ -67,14 +52,14 @@ def fee_oracle(): @pytest.fixture(scope="module") -def ejector(): - return contracts.cs_ejector +def early_adoption(): + return contracts.cs_early_adoption @pytest.fixture -def node_operator(csm, permissionless_gate, accounting, accounts) -> int: - address = accounts[7].address - return csm_add_node_operator(csm, permissionless_gate, accounting, address) +def node_operator(csm, accounting) -> int: + address, proof = get_ea_member() + return csm_add_node_operator(csm, accounting, address, proof) @pytest.fixture @@ -98,19 +83,6 @@ def deposits_to_csm(csm, pause_modules, node_operator, remove_stake_limit): (_, _, depositable) = csm.getStakingModuleSummary() fill_deposit_buffer(depositable) increase_staking_module_share(module_id=CSM_MODULE_ID, share_multiplier=2) - - if contracts.withdrawal_queue.isBunkerModeActive(): - # Disable bunker mode to allow deposits - web3.provider.make_request( - "hardhat_setStorageAt", - [ - contracts.withdrawal_queue.address, - web3.keccak(text="lido.WithdrawalQueue.bunkerModeSinceTimestamp").hex(), - web3.to_hex(2**256 - 1) # type(uint256).max - ], - ) - assert not contracts.withdrawal_queue.isBunkerModeActive() - for i in range(0, depositable, MAX_DEPOSITS): contracts.lido.deposit(MAX_DEPOSITS, CSM_MODULE_ID, "0x", {"from": contracts.deposit_security_module}) @@ -145,28 +117,19 @@ def distribute_reward_tree(node_operator, ref_slot): return tree -def get_sys_fee_to_eject(): - withdrawal_request_sys_address = '0x00000961Ef480Eb55e80D19ad83579A64c007002' - val = web3.eth.call({ - "to": withdrawal_request_sys_address, - "data": "0x", - }) - return int.from_bytes(val, "big") - - -@pytest.mark.parametrize("address, proof", get_ics_members()) -def test_add_node_operator_ics(csm, vetted_gate, accounting, address, proof): - no_id = csm_add_ics_node_operator(csm, vetted_gate, accounting, address, proof) +@pytest.mark.parametrize("address, proof", get_ea_members()) +def test_add_ea_node_operator(csm, accounting, early_adoption, address, proof): + no_id = csm_add_node_operator(csm, accounting, address, proof) no = csm.getNodeOperator(no_id) assert no["managerAddress"] == address assert no["rewardAddress"] == address - assert accounting.getBondCurveId(no_id) == vetted_gate.curveId() + assert accounting.getBondCurveId(no_id) == early_adoption.CURVE_ID() -def test_add_node_operator_permissionless(csm, permissionless_gate, accounting, accounts): +def test_add_node_operator_permissionless(csm, accounting, accounts): address = accounts[8].address - no_id = csm_add_node_operator(csm, permissionless_gate, accounting, address) + no_id = csm_add_node_operator(csm, accounting, address, proof=[]) no = csm.getNodeOperator(no_id) assert no["managerAddress"] == address @@ -174,6 +137,34 @@ def test_add_node_operator_permissionless(csm, permissionless_gate, accounting, assert accounting.getBondCurveId(no_id) == accounting.DEFAULT_BOND_CURVE_ID() +def test_add_node_operator_keys_more_than_limit(csm, accounting): + address, proof = get_ea_member() + keys_count = csm.MAX_SIGNING_KEYS_PER_OPERATOR_BEFORE_PUBLIC_RELEASE() + 1 + no_id = csm_add_node_operator(csm, accounting, address, proof, keys_count=keys_count) + no = csm.getNodeOperator(no_id) + + assert no["totalAddedKeys"] == keys_count + + +def test_add_node_operator_permissionless_keys_more_than_limit(csm, accounting, accounts): + keys_count = csm.MAX_SIGNING_KEYS_PER_OPERATOR_BEFORE_PUBLIC_RELEASE() + 1 + address = accounts[8].address + no_id = csm_add_node_operator(csm, accounting, address, proof=[], keys_count=keys_count) + no = csm.getNodeOperator(no_id) + + assert no["totalAddedKeys"] == keys_count + + +def test_upload_keys_more_than_limit(csm, accounting, node_operator): + no = csm.getNodeOperator(node_operator) + keys_before = no["totalAddedKeys"] + keys_count = csm.MAX_SIGNING_KEYS_PER_OPERATOR_BEFORE_PUBLIC_RELEASE() - keys_before + 1 + csm_upload_keys(csm, accounting, node_operator, keys_count) + + no = csm.getNodeOperator(node_operator) + assert no["totalAddedKeys"] == keys_count + keys_before + + @pytest.mark.usefixtures("pause_modules") def test_deposit(node_operator, csm, remove_stake_limit): (_, _, depositable_validators_count) = csm.getStakingModuleSummary() @@ -212,11 +203,19 @@ def test_csm_target_limits(csm, node_operator): assert no["targetLimit"] == target_limit +def test_csm_update_refunded(node_operator): + refunded_validators_count = 1 + with reverts(encode_error("NotSupported()")): + contracts.staking_router.updateRefundedValidatorsCount( + CSM_MODULE_ID, node_operator, refunded_validators_count, {"from": contracts.agent} + ) + + @pytest.mark.usefixtures("deposits_to_csm") def test_csm_report_exited(csm, node_operator, extra_data_service): total_exited = csm.getStakingModuleSummary()["totalExitedValidators"] exited_keys = 5 - extra_data = extra_data_service.collect({(CSM_MODULE_ID, node_operator): exited_keys}, exited_keys, exited_keys) + extra_data = extra_data_service.collect({}, {(CSM_MODULE_ID, node_operator): exited_keys}, exited_keys, exited_keys) oracle_report( extraDataFormat=1, extraDataHashList=extra_data.extra_data_hash_list, @@ -230,6 +229,24 @@ def test_csm_report_exited(csm, node_operator, extra_data_service): assert no["totalExitedKeys"] == exited_keys +@pytest.mark.usefixtures("deposits_to_csm") +def test_csm_report_stuck(csm, node_operator, extra_data_service): + total_exited = csm.getStakingModuleSummary()["totalExitedValidators"] + stuck_keys = 5 + extra_data = extra_data_service.collect({(CSM_MODULE_ID, node_operator): stuck_keys}, {}, stuck_keys, stuck_keys) + oracle_report( + extraDataFormat=1, + extraDataHashList=extra_data.extra_data_hash_list, + extraDataItemsCount=1, + extraDataList=extra_data.extra_data_list, + stakingModuleIdsWithNewlyExitedValidators=[CSM_MODULE_ID], + numExitedValidatorsByStakingModule=[total_exited], + ) + + no = csm.getNodeOperator(node_operator) + assert no["stuckValidatorsCount"] == stuck_keys + + @pytest.mark.usefixtures("deposits_to_csm") def test_csm_get_staking_module_summary(csm, accounting, node_operator, extra_data_service, remove_stake_limit): (exited_before, deposited_before, depositable_before) = contracts.staking_router.getStakingModuleSummary( @@ -238,7 +255,7 @@ def test_csm_get_staking_module_summary(csm, accounting, node_operator, extra_da # Assure there are new exited keys exited_keys = 5 - extra_data = extra_data_service.collect({(CSM_MODULE_ID, node_operator): exited_keys}, exited_keys, exited_keys) + extra_data = extra_data_service.collect({}, {(CSM_MODULE_ID, node_operator): exited_keys}, exited_keys, exited_keys) oracle_report( extraDataFormat=1, extraDataHashList=extra_data.extra_data_hash_list, @@ -271,13 +288,14 @@ def test_csm_get_node_operator_summary(csm, node_operator, extra_data_service): total_exited = csm.getStakingModuleSummary()["totalExitedValidators"] no = csm.getNodeOperator(node_operator) exited_keys = 1 + stuck_keys = 1 extra_data = extra_data_service.collect( - {(CSM_MODULE_ID, node_operator): exited_keys}, exited_keys, exited_keys + {(CSM_MODULE_ID, node_operator): stuck_keys}, {(CSM_MODULE_ID, node_operator): exited_keys}, 2, 2 ) oracle_report( extraDataFormat=1, extraDataHashList=extra_data.extra_data_hash_list, - extraDataItemsCount=1, + extraDataItemsCount=2, extraDataList=extra_data.extra_data_list, stakingModuleIdsWithNewlyExitedValidators=[CSM_MODULE_ID], numExitedValidatorsByStakingModule=[total_exited], @@ -286,11 +304,9 @@ def test_csm_get_node_operator_summary(csm, node_operator, extra_data_service): summary = contracts.staking_router.getNodeOperatorSummary(CSM_MODULE_ID, node_operator) assert summary["targetLimitMode"] == 0 assert summary["targetValidatorsCount"] == 0 - # DEPRECATED # - assert summary["stuckValidatorsCount"] == 0 + assert summary["stuckValidatorsCount"] == stuck_keys assert summary["refundedValidatorsCount"] == 0 assert summary["stuckPenaltyEndTimestamp"] == 0 - ############## assert summary["totalExitedValidators"] == exited_keys assert summary["totalDepositedValidators"] == no["totalDepositedKeys"] assert summary["depositableValidatorsCount"] == 0 @@ -320,8 +336,7 @@ def test_csm_decrease_vetted_keys(csm, node_operator, stranger): @pytest.mark.usefixtures("deposits_to_csm") def test_csm_penalize_node_operator(csm, accounting, node_operator, helpers): bond_shares_before = accounting.getBondShares(node_operator) - withdrawal_info = (node_operator, 0, ETH(30)) - tx = csm.submitWithdrawals([withdrawal_info], {"from": contracts.cs_verifier}) + tx = csm.submitInitialSlashing(node_operator, 0, {"from": contracts.cs_verifier}) assert "StETHBurnRequested" in tx.events burnt_shares = tx.events["StETHBurnRequested"]["amountOfShares"] assert accounting.getBondShares(node_operator) == bond_shares_before - burnt_shares @@ -334,7 +349,7 @@ def test_csm_eth_bond(csm, accounting, node_operator): bond_shares_before = accounting.getBondShares(node_operator) shares = contracts.lido.getSharesByPooledEth(ETH(1)) - accounting.depositETH(node_operator, {"from": manager_address, "value": ETH(1)}) + csm.depositETH(node_operator, {"from": manager_address, "value": ETH(1)}) assert accounting.getBondShares(node_operator) == bond_shares_before + shares @@ -348,7 +363,7 @@ def test_csm_steth_bond(csm, accounting, node_operator): contracts.lido.approve(accounting, ETH(2), {"from": manager_address}) shares = contracts.lido.getSharesByPooledEth(ETH(1)) - accounting.depositStETH(node_operator, ETH(1), (0, 0, 0, 0, 0), {"from": manager_address}) + csm.depositStETH(node_operator, ETH(1), (0, 0, 0, 0, 0), {"from": manager_address}) assert accounting.getBondShares(node_operator) == bond_shares_before + shares @@ -365,14 +380,14 @@ def test_csm_wsteth_bond(csm, accounting, node_operator): contracts.wsteth.getStETHByWstETH(contracts.wsteth.balanceOf(manager_address)) ) bond_shares_before = accounting.getBondShares(node_operator) - accounting.depositWstETH( + csm.depositWstETH( node_operator, contracts.wsteth.balanceOf(manager_address), (0, 0, 0, 0, 0), {"from": manager_address} ) assert accounting.getBondShares(node_operator) == bond_shares_before + shares @pytest.mark.usefixtures("deposits_to_csm") -def test_csm_claim_rewards_steth(csm, accounting, node_operator, ref_slot): +def test_csm_claim_rewards_steth(csm, node_operator, ref_slot): reward_address = csm.getNodeOperator(node_operator)["rewardAddress"] shares_before = contracts.lido.sharesOf(reward_address) accounting_shares_before = contracts.lido.sharesOf(contracts.cs_accounting) @@ -381,103 +396,48 @@ def test_csm_claim_rewards_steth(csm, accounting, node_operator, ref_slot): shares = tree.values[0]["value"][1] proof = list(tree.get_proof(tree.find(tree.leaf((node_operator, shares))))) - accounting.claimRewardsStETH(node_operator, ETH(1), shares, proof, {"from": reward_address}) + csm.claimRewardsStETH(node_operator, ETH(1), shares, proof, {"from": reward_address}) shares_after = contracts.lido.sharesOf(reward_address) accounting_shares_after = contracts.lido.sharesOf(contracts.cs_accounting) assert shares_after == shares_before + (accounting_shares_before + shares - accounting_shares_after) @pytest.mark.usefixtures("deposits_to_csm") -def test_csm_claim_rewards_wsteth(csm, accounting, node_operator, ref_slot): +def test_csm_claim_rewards_wsteth(csm, node_operator, ref_slot): tree = distribute_reward_tree(node_operator, ref_slot).tree shares = tree.values[0]["value"][1] proof = list(tree.get_proof(tree.find(tree.leaf((node_operator, shares))))) reward_address = csm.getNodeOperator(node_operator)["rewardAddress"] wsteth_before = contracts.wsteth.balanceOf(reward_address) - accounting.claimRewardsWstETH(node_operator, ETH(1), shares, proof, {"from": reward_address}) + csm.claimRewardsWstETH(node_operator, ETH(1), shares, proof, {"from": reward_address}) assert contracts.wsteth.balanceOf(reward_address) > wsteth_before @pytest.mark.usefixtures("deposits_to_csm") -def test_csm_claim_rewards_eth(csm, accounting, node_operator, ref_slot): +def test_csm_claim_rewards_eth(csm, node_operator, ref_slot): tree = distribute_reward_tree(node_operator, ref_slot).tree shares = tree.values[0]["value"][1] proof = list(tree.get_proof(tree.find(tree.leaf((node_operator, shares))))) reward_address = csm.getNodeOperator(node_operator)["rewardAddress"] withdrawal_requests = contracts.withdrawal_queue.getWithdrawalRequests(reward_address) - accounting.claimRewardsUnstETH(node_operator, ETH(1), shares, proof, {"from": reward_address}) + csm.claimRewardsUnstETH(node_operator, ETH(1), shares, proof, {"from": reward_address}) assert len(contracts.withdrawal_queue.getWithdrawalRequests(reward_address)) == len(withdrawal_requests) + 1 -def test_csm_remove_key(csm, parameters_registry, accounting, node_operator): +def test_csm_remove_key(csm, node_operator): no = csm.getNodeOperator(node_operator) keys_before = no["totalAddedKeys"] manager_address = csm.getNodeOperator(node_operator)["managerAddress"] tx = csm.removeKeys(node_operator, 0, 1, {"from": manager_address}) - - assert "KeyRemovalChargeApplied" in tx.events - assert "BondCharged" in tx.events - - expected_charge_amount = contracts.lido.getPooledEthByShares( - contracts.lido.getSharesByPooledEth(parameters_registry.getKeyRemovalCharge(accounting.DEFAULT_BOND_CURVE_ID())) + assert "KeyRemovalChargeApplied" not in tx.events + assert "BondCharged" not in tx.events + charge_amount = contracts.lido.getPooledEthByShares( + contracts.lido.getSharesByPooledEth(csm.keyRemovalCharge()) ) - assert tx.events["BondCharged"]["toChargeAmount"] == expected_charge_amount + + assert charge_amount == 0 # keyRemovalCharge is zero since vote 2025/07/16 no = csm.getNodeOperator(node_operator) assert no["totalAddedKeys"] == keys_before - 1 - - -@pytest.mark.usefixtures("deposits_to_csm") -def test_eject_bad_performer(csm, ejector, node_operator): - eject_payment_value = get_sys_fee_to_eject() - - index_to_eject = 0 - tx = ejector.ejectBadPerformer( - node_operator, index_to_eject, ZERO_ADDRESS, {"value": eject_payment_value, "from": contracts.cs_strikes} - ) - - assert "TriggeredExitFeeRecorded" in tx.events - assert tx.events["TriggeredExitFeeRecorded"]["nodeOperatorId"] == node_operator - pubkey = csm.getSigningKeys(node_operator, index_to_eject, 1) - assert tx.events["TriggeredExitFeeRecorded"]["pubkey"] == pubkey - assert tx.events["TriggeredExitFeeRecorded"]["exitType"] == 1 - assert tx.events["TriggeredExitFeeRecorded"]["withdrawalRequestPaidFee"] == eject_payment_value - assert tx.events["TriggeredExitFeeRecorded"]["withdrawalRequestRecordedFee"] == eject_payment_value - - -@pytest.mark.usefixtures("deposits_to_csm") -def test_voluntary_eject(csm, ejector, node_operator): - eject_payment_value = get_sys_fee_to_eject() - operator_address = csm.getNodeOperator(node_operator)["rewardAddress"] - - tx = ejector.voluntaryEject( - node_operator, 0, 1, ZERO_ADDRESS, {"value": eject_payment_value, "from": operator_address} - ) - assert "TriggeredExitFeeRecorded" not in tx.events - - -def test_report_validator_exit_delay(csm, node_operator): - pubkey = csm.getSigningKeys(node_operator, 0, 1) - day_in_seconds = 60 * 60 * 24 - - tx = csm.reportValidatorExitDelay(node_operator, 0, pubkey, 7 * day_in_seconds, {"from": contracts.staking_router}) - assert "ValidatorExitDelayProcessed" in tx.events - assert tx.events["ValidatorExitDelayProcessed"]["nodeOperatorId"] == node_operator - assert tx.events["ValidatorExitDelayProcessed"]["pubkey"] == pubkey - assert tx.events["ValidatorExitDelayProcessed"]["delayPenalty"] == 100000000000000000 # FIXME: should be taken from CSParametersRegistry - - -def test_on_validator_exit_triggered(csm, node_operator): - eject_payment_value = 1 - pubkey = csm.getSigningKeys(node_operator, 0, 1) - exit_type = 3 - - tx = csm.onValidatorExitTriggered(node_operator, pubkey, 1, exit_type, {"from": contracts.staking_router}) - assert "TriggeredExitFeeRecorded" in tx.events - assert tx.events["TriggeredExitFeeRecorded"]["nodeOperatorId"] == node_operator - assert tx.events["TriggeredExitFeeRecorded"]["pubkey"] == pubkey - assert tx.events["TriggeredExitFeeRecorded"]["exitType"] == exit_type - assert tx.events["TriggeredExitFeeRecorded"]["withdrawalRequestPaidFee"] == eject_payment_value - assert tx.events["TriggeredExitFeeRecorded"]["withdrawalRequestRecordedFee"] == eject_payment_value diff --git a/tests/test_vote_tw_csm2_mainnet.py b/tests/test_vote_tw_csm2_mainnet.py deleted file mode 100644 index ba2dd136a..000000000 --- a/tests/test_vote_tw_csm2_mainnet.py +++ /dev/null @@ -1,1827 +0,0 @@ -from typing import Optional -from brownie.network.transaction import TransactionReceipt - -from utils.dsm import encode_remove_guardian, encode_add_guardian -from utils.test.tx_tracing_helpers import ( - count_vote_items_by_events, - display_dg_events, -) - -from brownie.exceptions import VirtualMachineError -from brownie import interface, reverts, chain, convert, web3, ZERO_ADDRESS # type: ignore -from brownie.network.event import EventDict -from utils.easy_track import create_permissions -from utils.evm_script import encode_call_script -from utils.voting import find_metadata_by_vote_id -from utils.ipfs import get_lido_vote_cid_from_str -from utils.test.tx_tracing_helpers import display_voting_events -from utils.dual_governance import PROPOSAL_STATUS -from utils.test.event_validators.node_operators_registry import ( - validate_node_operator_name_set_event, - validate_node_operator_reward_address_set_event, - NodeOperatorNameSetItem, - NodeOperatorRewardAddressSetItem, -) -from utils.test.tx_tracing_helpers import group_voting_events_from_receipt, group_dg_events_from_receipt -from utils.test.event_validators.easy_track import validate_evmscript_factory_added_event, EVMScriptFactoryAdded -from utils.test.event_validators.dual_governance import validate_dual_governance_submit_event -from utils.config import ( - CS_MODULE_ID, - CS_MODULE_MODULE_FEE_BP, - CS_MODULE_MAX_DEPOSITS_PER_BLOCK, - CS_MODULE_MIN_DEPOSIT_BLOCK_DISTANCE, - CS_MODULE_TREASURY_FEE_BP, - CS_GATE_SEAL_ADDRESS, - contracts, -) - - -def validate_proxy_upgrade_event(event: EventDict, implementation: str, emitted_by: Optional[str] = None): - assert "Upgraded" in event, "No Upgraded event found" - - assert event["Upgraded"][0]["implementation"] == implementation, "Wrong implementation address" - - if emitted_by is not None: - assert convert.to_address(event["Upgraded"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" - - -def validate_consensus_version_set_event(event: EventDict, new_version: int, prev_version: int, emitted_by: Optional[str] = None): - assert "ConsensusVersionSet" in event, "No ConsensusVersionSet event found" - - assert event["ConsensusVersionSet"][0]["version"] == new_version, "Wrong new version" - - assert event["ConsensusVersionSet"][0]["prevVersion"] == prev_version, "Wrong previous version" - - if emitted_by is not None: - assert convert.to_address(event["ConsensusVersionSet"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" - - -def validate_role_grant_event(event: EventDict, role_hash: str, account: str, emitted_by: Optional[str] = None): - assert "RoleGranted" in event, "No RoleGranted event found" - - # Strip 0x prefix for consistent comparison - expected_role_hash = role_hash.replace('0x', '') - actual_role_hash = event["RoleGranted"][0]["role"].hex().replace('0x', '') - - assert actual_role_hash == expected_role_hash, "Wrong role hash" - - assert convert.to_address(event["RoleGranted"][0]["account"]) == convert.to_address(account), "Wrong account" - - if emitted_by is not None: - assert convert.to_address(event["RoleGranted"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" - - -def validate_role_revoke_event(event: EventDict, role_hash: str, account: str, emitted_by: Optional[str] = None): - assert "RoleRevoked" in event, "No RoleRevoked event found" - - # Strip 0x prefix for consistent comparison - expected_role_hash = role_hash.replace('0x', '') - actual_role_hash = event["RoleRevoked"][0]["role"].hex().replace('0x', '') - - assert actual_role_hash == expected_role_hash, "Wrong role hash" - - assert convert.to_address(event["RoleRevoked"][0]["account"]) == convert.to_address(account), "Wrong account" - - if emitted_by is not None: - assert convert.to_address(event["RoleRevoked"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" - - -def validate_contract_version_set_event(event: EventDict, version: int, emitted_by: Optional[str] = None): - assert "ContractVersionSet" in event, "No ContractVersionSet event found" - - assert event["ContractVersionSet"][0]["version"] == version, "Wrong version" - - if emitted_by is not None: - assert convert.to_address(event["ContractVersionSet"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" - - -def validate_bond_curve_added_event(event: EventDict, curve_id: int, emitted_by: Optional[str] = None): - assert "BondCurveAdded" in event, "No BondCurveAdded event found" - - assert event["BondCurveAdded"][0]["curveId"] == curve_id, "Wrong curve ID" - # FIXME: Where is the intervals check? - - if emitted_by is not None: - assert convert.to_address(event["BondCurveAdded"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" - -def validate_remove_guardian_event(event: EventDict, guardian_address: str, emitted_by: Optional[str] = None): - assert "GuardianRemoved" in event, "No GuardianRemoved event found" - - assert event["GuardianRemoved"][0]["guardian"] == guardian_address, "Wrong guardian address" - - if emitted_by is not None: - assert convert.to_address(event["GuardianRemoved"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" - -def validate_add_guardian_event(event: EventDict, guardian_address: str, emitted_by: Optional[str] = None): - assert "GuardianAdded" in event, "No GuardianAdded event found" - - assert event["GuardianAdded"][0]["guardian"] == guardian_address, "Wrong guardian address" - - if emitted_by is not None: - assert convert.to_address(event["GuardianAdded"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" - - -def validate_staking_module_update_event( - event: EventDict, - module_id: int, - share_limit: int, - priority_share_threshold: int, - module_fee_points_bp: int, - treasury_fee_points_bp: int, - max_deposits_per_block: int, - min_deposit_block_distance: int, - emitted_by: Optional[str] = None -): - assert "StakingModuleShareLimitSet" in event, "No StakingModuleShareLimitSet event found" - assert "StakingModuleFeesSet" in event, "No StakingModuleFeesSet event found" - assert "StakingModuleMaxDepositsPerBlockSet" in event, "No StakingModuleMaxDepositsPerBlockSet event found" - assert "StakingModuleMinDepositBlockDistanceSet" in event, "No StakingModuleMinDepositBlockDistanceSet event found" - - assert len(event["StakingModuleShareLimitSet"]) == 1, "Multiple StakingModuleShareLimitSet events found" - assert len(event["StakingModuleFeesSet"]) == 1, "Multiple StakingModuleFeesSet events found" - assert len(event["StakingModuleMaxDepositsPerBlockSet"]) == 1, "Multiple StakingModuleMaxDepositsPerBlockSet events found" - assert len(event["StakingModuleMinDepositBlockDistanceSet"]) == 1, "Multiple StakingModuleMinDepositBlockDistanceSet events found" - - assert event["StakingModuleShareLimitSet"][0]["stakingModuleId"] == module_id, "Wrong module ID" - assert event["StakingModuleShareLimitSet"][0]["stakeShareLimit"] == share_limit, "Wrong share limit" - assert event["StakingModuleShareLimitSet"][0]["priorityExitShareThreshold"] == priority_share_threshold, "Wrong priority threshold" - - assert event["StakingModuleFeesSet"][0]["stakingModuleFee"] == module_fee_points_bp, "Wrong fee points" - assert event["StakingModuleFeesSet"][0]["treasuryFee"] == treasury_fee_points_bp, "Wrong treasury fee points" - - assert event["StakingModuleMaxDepositsPerBlockSet"][0]["maxDepositsPerBlock"] == max_deposits_per_block, "Wrong max deposits" - - assert event["StakingModuleMinDepositBlockDistanceSet"][0]["minDepositBlockDistance"] == min_deposit_block_distance, "Wrong min distance" - - if emitted_by is not None: - assert convert.to_address(event["StakingModuleShareLimitSet"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" - assert convert.to_address(event["StakingModuleFeesSet"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" - assert convert.to_address(event["StakingModuleMaxDepositsPerBlockSet"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" - assert convert.to_address(event["StakingModuleMinDepositBlockDistanceSet"][0]["_emitted_by"]) == convert.to_address(emitted_by), "Wrong event emitter" - - -def get_ossifiable_proxy_impl(proxy_address): - """Get implementation address from an OssifiableProxy""" - proxy = interface.OssifiableProxy(proxy_address) - return proxy.proxy__getImplementation() - - -def get_wv_contract_proxy_impl(proxy_address): - """Get implementation address from an WithdrawalContractProxy""" - proxy = interface.WithdrawalContractProxy(proxy_address) - return proxy.implementation() - - -# FIXME: no method for WV? -def check_proxy_implementation(proxy_address, expected_impl): - """Check that proxy has expected implementation""" - actual_impl = get_ossifiable_proxy_impl(proxy_address) - assert actual_impl == expected_impl, f"Expected impl {expected_impl}, got {actual_impl}" - - -# ============================================================================ -# ============================== Import vote ================================= -# ============================================================================ -from scripts.vote_tw_csm2_mainnet import start_vote, get_vote_items, encode_wv_proxy_upgrade_to, \ - NETHERMIND_NEW_REWARD_ADDRESS - -# ============================================================================ -# ============================== Constants =================================== -# ============================================================================ -VOTING = "0x2e59A20f205bB85a89C53f1936454680651E618e" -EMERGENCY_PROTECTED_TIMELOCK = "0xCE0425301C85c5Ea2A0873A2dEe44d78E02D2316" -DUAL_GOVERNANCE = "0xC1db28B3301331277e307FDCfF8DE28242A4486E" -DUAL_GOVERNANCE_ADMIN_EXECUTOR = "0x23E0B465633FF5178808F4A75186E2F2F9537021" -AGENT = "0x3e40D73EB977Dc6a537aF587D48316feE66E9C8c" -ARAGON_KERNEL = "0xb8FFC3Cd6e7Cf5a098A1c92F48009765B24088Dc" -STETH = "0xAE7ab96520DE3A18E5e111B5EaAb095312D7fE84" - -# New core contracts implementations -LIDO_LOCATOR_IMPL = "0x2C298963FB763f74765829722a1ebe0784f4F5Cf" -ACCOUNTING_ORACLE_IMPL = "0xE9906E543274cebcd335d2C560094089e9547e8d" -VALIDATORS_EXIT_BUS_ORACLE_IMPL = "0x905A211eD6830Cfc95643f0bE2ff64E7f3bf9b94" -WITHDRAWAL_VAULT_IMPL = "0x7D2BAa6094E1C4B60Da4cbAF4A77C3f4694fD53D" -STAKING_ROUTER_IMPL = "0x226f9265CBC37231882b7409658C18bB7738173A" -NODE_OPERATORS_REGISTRY_IMPL = "0x6828b023e737f96B168aCd0b5c6351971a4F81aE" - -TRIGGERABLE_WITHDRAWALS_GATEWAY = "0xDC00116a0D3E064427dA2600449cfD2566B3037B" -VALIDATOR_EXIT_VERIFIER = "0xbDb567672c867DB533119C2dcD4FB9d8b44EC82f" - -# Add missing constants -OLD_GATE_SEAL_ADDRESS = "0xf9C9fDB4A5D2AA1D836D5370AB9b28BC1847e178" -NEW_WQ_GATE_SEAL = "0x8A854C4E750CDf24f138f34A9061b2f556066912" -NEW_TW_GATE_SEAL = "0xA6BC802fAa064414AA62117B4a53D27fFfF741F1" -RESEAL_MANAGER = "0x7914b5a1539b97Bd0bbd155757F25FD79A522d24" - -# Add EasyTrack constants -EASYTRACK_EVMSCRIPT_EXECUTOR = "0x79a20FD0FA36453B2F45eAbab19bfef43575Ba9E" -EASYTRACK_SDVT_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY = "0xAa3D6A8B52447F272c1E8FAaA06EA06658bd95E2" -EASYTRACK_CURATED_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY = "0x397206ecdbdcb1A55A75e60Fc4D054feC72E5f63" - -# Oracle consensus versions -AO_CONSENSUS_VERSION = 4 -VEBO_CONSENSUS_VERSION = 4 -CSM_CONSENSUS_VERSION = 3 - -EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS = 14 * 7200 - -NOR_EXIT_DEADLINE_IN_SEC = 172800 - -# CSM -CS_MODULE_NEW_TARGET_SHARE_BP = 3500 # 3.5% -CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP = 3750 # 3.75% - -CS_ACCOUNTING_IMPL_V2_ADDRESS = "0x6f09d2426c7405C5546413e6059F884D2D03f449" -CS_FEE_DISTRIBUTOR_IMPL_V2_ADDRESS = "0x5DCF7cF7c6645E9E822a379dF046a8b0390251A1" -CS_FEE_ORACLE_IMPL_V2_ADDRESS = "0xe0B234f99E413E27D9Bc31aBba9A49A3e570Da97" -CSM_IMPL_V2_ADDRESS = "0x1eB6d4da13ca9566c17F526aE0715325d7a07665" - -CS_GATE_SEAL_V2_ADDRESS = "0xE1686C2E90eb41a48356c1cC7FaA17629af3ADB3" - -# CSM consensus version -CSM_CONSENSUS_VERSION = 3 - -# Bond curves for CS Accounting -CS_CURVES = [ - ([1, 2.4 * 10 ** 18], [2, 1.3 * 10 ** 18]), # Default Curve - ([1, 1.5 * 10 ** 18], [2, 1.3 * 10 ** 18]), # Legacy EA Curve -] -CS_ICS_GATE_BOND_CURVE = ([1, 1.5 * 10 ** 18], [2, 1.3 * 10 ** 18]) # Identified Community Stakers Gate Bond Curve - -# CSM committee and config addresses (imported from config in actual script) -CSM_COMMITTEE_MS = "0xC52fC3081123073078698F1EAc2f1Dc7Bd71880f" -CS_GATE_SEAL_ADDRESS = "0x16Dbd4B85a448bE564f1742d5c8cCdD2bB3185D0" - -# CSM staking module constants (from config) -CS_ORACLE_EPOCHS_PER_FRAME = 225 * 28 # 28 days -CS_MODULE_ID = 3 -CS_MODULE_NAME = "Community Staking" -CS_MODULE_MODULE_FEE_BP = 600 -CS_MODULE_TREASURY_FEE_BP = 400 -CS_MODULE_TARGET_SHARE_BP = 300 # Updated from 200 to 300 in vote 2025/07/16 -CS_MODULE_PRIORITY_EXIT_SHARE_THRESHOLD = 375 # Updated from 250 to 375 in vote 2025/07/16 -CS_MODULE_MAX_DEPOSITS_PER_BLOCK = 30 -CS_MODULE_MIN_DEPOSIT_BLOCK_DISTANCE = 25 -CS_EJECTOR_ADDRESS = "0xc72b58aa02E0e98cF8A4a0E9Dce75e763800802C" -CS_PERMISSIONLESS_GATE_ADDRESS = "0xcF33a38111d0B1246A3F38a838fb41D626B454f0" -CS_VETTED_GATE_ADDRESS = "0xB314D4A76C457c93150d308787939063F4Cc67E0" -CS_VERIFIER_V2_ADDRESS = "0xdC5FE1782B6943f318E05230d688713a560063DC" - -CS_VERIFIER_ADDRESS_OLD = "0xeC6Cc185f671F627fb9b6f06C8772755F587b05d" - -CS_CURVES = [ - ([1, 2.4 * 10 ** 18], [2, 1.3 * 10 ** 18]), # Default Curve - ([1, 1.5 * 10 ** 18], [2, 1.3 * 10 ** 18]), # Legacy EA Curve -] -CS_ICS_GATE_BOND_CURVE = ([1, 1.5 * 10 ** 18], [2, 1.3 * 10 ** 18]) # Identified Community Stakers Gate Bond Curve - -# Contract versions expected after upgrade -CSM_V2_VERSION = 2 -CS_ACCOUNTING_V2_VERSION = 2 -CS_FEE_ORACLE_V2_VERSION = 2 -CS_FEE_DISTRIBUTOR_V2_VERSION = 2 - -EASYTRACK_CS_SET_VETTED_GATE_TREE_FACTORY = "0xBc5642bDD6F2a54b01A75605aAe9143525D97308" - -EXPECTED_VOTE_ID = None -EXPECTED_DG_PROPOSAL_ID = 5 -EXPECTED_VOTE_EVENTS_COUNT = 4 -EXPECTED_DG_EVENTS_FROM_AGENT = 69 -EXPECTED_DG_EVENTS_COUNT = 70 -IPFS_DESCRIPTION_HASH = "bafkreih5app23xbevhswk56r6d2cjdqui5tckki6szo7loi7xe25bfgol4" - -NETHERMIND_NO_ID = 25 -NETHERMIND_NO_NAME_OLD = "Nethermind" -NETHERMIND_NO_NAME_NEW = "Twinstake" -NETHERMIND_NO_STAKING_REWARDS_ADDRESS_OLD = "0x237DeE529A47750bEcdFa8A59a1D766e3e7B5F91" -NETHERMIND_NO_STAKING_REWARDS_ADDRESS_NEW = "0x36201ed66DbC284132046ee8d99272F8eEeb24c8" -NODE_OPERATORS_REGISTRY_ADDRESS = "0x55032650b14df07b85bF18A3a3eC8E0Af2e028d5" - -NODE_OPERATORS_REGISTRY_ARAGON_APP_ID = "0x7071f283424072341f856ac9e947e7ec0eb68719f757a7e785979b6b8717579d" -SIMPLE_DVT_ARAGON_APP_ID = "0xe1635b63b5f7b5e545f2a637558a4029dea7905361a2f0fc28c66e9136cf86a4" - -OLD_KILN_ADDRESS = "0x14D5d5B71E048d2D75a39FfC5B407e3a3AB6F314" -NEW_KILN_ADDRESS = "0x6d22aE126eB2c37F67a1391B37FF4f2863e61389" -MAX_VALIDATORS_PER_REPORT = 600 -MAX_EXIT_REQUESTS_LIMIT = 11200 -EXITS_PER_FRAME = 1 -FRAME_DURATION_IN_SEC = 48 - -import pytest -from utils.agent import agent_forward -from utils.permissions import encode_oz_grant_role, encode_oz_revoke_role -from utils.node_operators import encode_set_node_operator_name, encode_set_node_operator_reward_address - - -@pytest.fixture(scope="module") -def dual_governance_proposal_calls(): - """Returns list of dual governance proposal calls for events checking""" - - # Helper function to encode proxy upgrades - def encode_proxy_upgrade_to(proxy_contract, new_impl_address): - return (proxy_contract.address, proxy_contract.proxy__upgradeTo.encode_input(new_impl_address)) - - # Helper function to encode oracle consensus upgrades - def encode_oracle_upgrade_consensus(oracle_contract, new_version): - return (oracle_contract.address, oracle_contract.setConsensusVersion.encode_input(new_version)) - - # Cast contracts to OssifiableProxy interface to access proxy methods - _ = interface.StETH(STETH) # Loading ABI to parse DG events - lido_locator_proxy = interface.OssifiableProxy(contracts.lido_locator.address) - vebo_proxy = interface.OssifiableProxy(contracts.validators_exit_bus_oracle.address) - withdrawal_vault_proxy = interface.OssifiableProxy(contracts.withdrawal_vault.address) - accounting_oracle_proxy = interface.OssifiableProxy(contracts.accounting_oracle.address) - staking_router_proxy = interface.OssifiableProxy(contracts.staking_router.address) - csm_proxy = interface.OssifiableProxy(contracts.csm.address) - cs_accounting_proxy = interface.OssifiableProxy(contracts.cs_accounting.address) - cs_fee_oracle_proxy = interface.OssifiableProxy(contracts.cs_fee_oracle.address) - cs_fee_distributor_proxy = interface.OssifiableProxy(contracts.cs_fee_distributor.address) - - # Create all the dual governance calls that match the voting script - dg_items = [ - # 1. Update locator implementation - agent_forward([encode_proxy_upgrade_to(lido_locator_proxy, LIDO_LOCATOR_IMPL)]), - - # 2. Update VEBO implementation - agent_forward([encode_proxy_upgrade_to(vebo_proxy, VALIDATORS_EXIT_BUS_ORACLE_IMPL)]), - - # 3. Call finalizeUpgrade_v2 on VEBO - agent_forward([ - (contracts.validators_exit_bus_oracle.address, - contracts.validators_exit_bus_oracle.finalizeUpgrade_v2.encode_input(MAX_VALIDATORS_PER_REPORT, - MAX_EXIT_REQUESTS_LIMIT, - EXITS_PER_FRAME, - FRAME_DURATION_IN_SEC)) - ]), - - # 4. Grant VEBO role MANAGE_CONSENSUS_VERSION_ROLE to the AGENT - agent_forward([ - encode_oz_grant_role( - contract=contracts.validators_exit_bus_oracle, - role_name="MANAGE_CONSENSUS_VERSION_ROLE", - grant_to=contracts.agent - ) - ]), - - # 5. Bump VEBO consensus version to 4 - agent_forward([encode_oracle_upgrade_consensus(contracts.validators_exit_bus_oracle, VEBO_CONSENSUS_VERSION)]), - - # 6. Revoke VEBO role MANAGE_CONSENSUS_VERSION_ROLE from the AGENT - agent_forward([ - encode_oz_revoke_role( - contract=contracts.validators_exit_bus_oracle, - role_name="MANAGE_CONSENSUS_VERSION_ROLE", - revoke_from=contracts.agent - ) - ]), - - # 7. Grant SUBMIT_REPORT_HASH_ROLE on VEBO to EasyTrack executor - agent_forward([ - encode_oz_grant_role( - contract=contracts.validators_exit_bus_oracle, - role_name="SUBMIT_REPORT_HASH_ROLE", - grant_to=EASYTRACK_EVMSCRIPT_EXECUTOR - ) - ]), - - # 8. Grant TWG role ADD_FULL_WITHDRAWAL_REQUEST_ROLE to CS Ejector - agent_forward([ - encode_oz_grant_role( - contract=interface.TriggerableWithdrawalsGateway(TRIGGERABLE_WITHDRAWALS_GATEWAY), - role_name="ADD_FULL_WITHDRAWAL_REQUEST_ROLE", - grant_to=CS_EJECTOR_ADDRESS - ) - ]), - - # 9. Grant TWG role ADD_FULL_WITHDRAWAL_REQUEST_ROLE to VEBO - agent_forward([ - encode_oz_grant_role( - contract=interface.TriggerableWithdrawalsGateway(TRIGGERABLE_WITHDRAWALS_GATEWAY), - role_name="ADD_FULL_WITHDRAWAL_REQUEST_ROLE", - grant_to=contracts.validators_exit_bus_oracle.address - ) - ]), - - # 10. Connect TWG to Dual Governance tiebreaker - ( - interface.DualGovernance(DUAL_GOVERNANCE).address, - interface.DualGovernance(DUAL_GOVERNANCE).addTiebreakerSealableWithdrawalBlocker.encode_input( - TRIGGERABLE_WITHDRAWALS_GATEWAY) - ), - - # 11. Update WithdrawalVault implementation - agent_forward([encode_wv_proxy_upgrade_to(withdrawal_vault_proxy, WITHDRAWAL_VAULT_IMPL)]), - - # 12. Call finalizeUpgrade_v2() on WithdrawalVault - agent_forward([ - (contracts.withdrawal_vault.address, contracts.withdrawal_vault.finalizeUpgrade_v2.encode_input()) - ]), - - # 13. Update Accounting Oracle implementation - agent_forward([encode_proxy_upgrade_to(accounting_oracle_proxy, ACCOUNTING_ORACLE_IMPL)]), - - # 14. Grant AO MANAGE_CONSENSUS_VERSION_ROLE to the AGENT - agent_forward([ - encode_oz_grant_role( - contract=contracts.accounting_oracle, - role_name="MANAGE_CONSENSUS_VERSION_ROLE", - grant_to=contracts.agent - ) - ]), - - # 15. Bump AO consensus version to 4 - agent_forward([encode_oracle_upgrade_consensus(contracts.accounting_oracle, AO_CONSENSUS_VERSION)]), - - # 16. Revoke AO MANAGE_CONSENSUS_VERSION_ROLE from the AGENT - agent_forward([ - encode_oz_revoke_role( - contract=contracts.accounting_oracle, - role_name="MANAGE_CONSENSUS_VERSION_ROLE", - revoke_from=contracts.agent - ) - ]), - - # 17. Call finalizeUpgrade_v3() on AO - agent_forward([ - (contracts.accounting_oracle.address, contracts.accounting_oracle.finalizeUpgrade_v3.encode_input()) - ]), - - # 18. Update SR implementation - agent_forward([encode_proxy_upgrade_to(staking_router_proxy, STAKING_ROUTER_IMPL)]), - - # 19. Call finalizeUpgrade_v3() on SR - agent_forward([ - (contracts.staking_router.address, contracts.staking_router.finalizeUpgrade_v3.encode_input()) - ]), - - # 20. Grant SR role REPORT_VALIDATOR_EXITING_STATUS_ROLE to ValidatorExitVerifier - agent_forward([ - encode_oz_grant_role( - contract=contracts.staking_router, - role_name="REPORT_VALIDATOR_EXITING_STATUS_ROLE", - grant_to=VALIDATOR_EXIT_VERIFIER - ) - ]), - - # 21. Grant SR role REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE to TWG - agent_forward([ - encode_oz_grant_role( - contract=contracts.staking_router, - role_name="REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE", - grant_to=TRIGGERABLE_WITHDRAWALS_GATEWAY - ) - ]), - - # 22-27: Kernel and registry upgrades - # 22. Grant APP_MANAGER_ROLE role to the AGENT - agent_forward([ - (contracts.acl.address, - contracts.acl.grantPermission.encode_input( - AGENT, - ARAGON_KERNEL, - web3.keccak(text="APP_MANAGER_ROLE") - )) - ]), - - # 23. Update NodeOperatorsRegistry implementation - agent_forward([ - (contracts.kernel.address, - contracts.kernel.setApp.encode_input( - contracts.kernel.APP_BASES_NAMESPACE(), - NODE_OPERATORS_REGISTRY_ARAGON_APP_ID, - NODE_OPERATORS_REGISTRY_IMPL - )) - ]), - - # 24. Call finalizeUpgrade_v4 on Curated Staking Module - agent_forward([ - (interface.NodeOperatorsRegistry(contracts.node_operators_registry).address, - interface.NodeOperatorsRegistry(contracts.node_operators_registry).finalizeUpgrade_v4.encode_input( - NOR_EXIT_DEADLINE_IN_SEC)) - ]), - - # 25. Update SDVT implementation - agent_forward([ - (contracts.kernel.address, - contracts.kernel.setApp.encode_input( - contracts.kernel.APP_BASES_NAMESPACE(), - SIMPLE_DVT_ARAGON_APP_ID, - NODE_OPERATORS_REGISTRY_IMPL - )) - ]), - - # 26. Call finalizeUpgrade_v4 on SDVT - agent_forward([ - (interface.NodeOperatorsRegistry(contracts.simple_dvt).address, - interface.NodeOperatorsRegistry(contracts.simple_dvt).finalizeUpgrade_v4.encode_input( - NOR_EXIT_DEADLINE_IN_SEC)) - ]), - - # 27. Revoke APP_MANAGER_ROLE role from the AGENT - agent_forward([ - (contracts.acl.address, - contracts.acl.revokePermission.encode_input( - AGENT, - ARAGON_KERNEL, - web3.keccak(text="APP_MANAGER_ROLE") - )) - ]), - - # 28-33: Oracle daemon config changes - agent_forward([ - encode_oz_grant_role( - contract=contracts.oracle_daemon_config, - role_name="CONFIG_MANAGER_ROLE", - grant_to=contracts.agent - ) - ]), - - agent_forward([ - (contracts.oracle_daemon_config.address, - contracts.oracle_daemon_config.unset.encode_input('NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP')) - ]), - - agent_forward([ - (contracts.oracle_daemon_config.address, - contracts.oracle_daemon_config.unset.encode_input('VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS')) - ]), - - agent_forward([ - (contracts.oracle_daemon_config.address, - contracts.oracle_daemon_config.unset.encode_input('VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS')) - ]), - - agent_forward([ - (contracts.oracle_daemon_config.address, - contracts.oracle_daemon_config.set.encode_input('EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS', - EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS)) - ]), - - agent_forward([ - encode_oz_revoke_role( - contract=contracts.oracle_daemon_config, - role_name="CONFIG_MANAGER_ROLE", - revoke_from=contracts.agent - ) - ]), - - # CSM upgrades and role changes (steps 34-59) - # 34. Upgrade CSM implementation on proxy - agent_forward([encode_proxy_upgrade_to(csm_proxy, CSM_IMPL_V2_ADDRESS)]), - - # 35. Call finalizeUpgradeV2() on CSM contract - agent_forward([(contracts.csm.address, contracts.csm.finalizeUpgradeV2.encode_input())]), - - # 36. Upgrade CSAccounting implementation on proxy - agent_forward([encode_proxy_upgrade_to(cs_accounting_proxy, CS_ACCOUNTING_IMPL_V2_ADDRESS)]), - - # 37. Call finalizeUpgradeV2(bondCurves) on CSAccounting contract - agent_forward([ - (contracts.cs_accounting.address, - contracts.cs_accounting.finalizeUpgradeV2.encode_input(CS_CURVES)) - ]), - - # 38. Upgrade CSFeeOracle implementation on proxy - agent_forward([encode_proxy_upgrade_to(cs_fee_oracle_proxy, CS_FEE_ORACLE_IMPL_V2_ADDRESS)]), - - # 39. Call finalizeUpgradeV2(consensusVersion) on CSFeeOracle contract - agent_forward([ - (contracts.cs_fee_oracle.address, - contracts.cs_fee_oracle.finalizeUpgradeV2.encode_input(CSM_CONSENSUS_VERSION)) - ]), - - # 40. Upgrade CSFeeDistributor implementation on proxy - agent_forward([encode_proxy_upgrade_to(cs_fee_distributor_proxy, CS_FEE_DISTRIBUTOR_IMPL_V2_ADDRESS)]), - - # 41. Call finalizeUpgradeV2(admin) on CSFeeDistributor contract - agent_forward([ - (contracts.cs_fee_distributor.address, - contracts.cs_fee_distributor.finalizeUpgradeV2.encode_input(contracts.agent)) - ]), - - # 42. Revoke CSAccounting role SET_BOND_CURVE_ROLE from the CSM contract - agent_forward([ - encode_oz_revoke_role( - contract=contracts.cs_accounting, - role_name="SET_BOND_CURVE_ROLE", - revoke_from=contracts.csm - ) - ]), - - # 43. Revoke CSAccounting role RESET_BOND_CURVE_ROLE from the CSM contract - agent_forward([ - encode_oz_revoke_role( - contract=contracts.cs_accounting, - role_name="RESET_BOND_CURVE_ROLE", - revoke_from=contracts.csm - ) - ]), - - # 44. Revoke CSAccounting role RESET_BOND_CURVE_ROLE from the CSM committee - agent_forward([ - encode_oz_revoke_role( - contract=contracts.cs_accounting, - role_name="RESET_BOND_CURVE_ROLE", - revoke_from=CSM_COMMITTEE_MS - ) - ]), - - # 45. Grant CSM role CREATE_NODE_OPERATOR_ROLE for the permissionless gate - agent_forward([ - encode_oz_grant_role( - contract=contracts.csm, - role_name="CREATE_NODE_OPERATOR_ROLE", - grant_to=CS_PERMISSIONLESS_GATE_ADDRESS - ) - ]), - - # 46. Grant CSM role CREATE_NODE_OPERATOR_ROLE for the vetted gate - agent_forward([ - encode_oz_grant_role( - contract=contracts.csm, - role_name="CREATE_NODE_OPERATOR_ROLE", - grant_to=CS_VETTED_GATE_ADDRESS - ) - ]), - - # 47. Grant CSAccounting role SET_BOND_CURVE_ROLE for the vetted gate - agent_forward([ - encode_oz_grant_role( - contract=contracts.cs_accounting, - role_name="SET_BOND_CURVE_ROLE", - grant_to=CS_VETTED_GATE_ADDRESS - ) - ]), - - # 48. Revoke role VERIFIER_ROLE from the previous instance of the Verifier contract - agent_forward([ - encode_oz_revoke_role( - contract=contracts.csm, - role_name="VERIFIER_ROLE", - revoke_from=CS_VERIFIER_ADDRESS_OLD - ) - ]), - - # 49. Grant role VERIFIER_ROLE to the new instance of the Verifier contract - agent_forward([ - encode_oz_grant_role( - contract=contracts.csm, - role_name="VERIFIER_ROLE", - grant_to=CS_VERIFIER_V2_ADDRESS - ) - ]), - - # 50. Revoke CSM role PAUSE_ROLE from the previous GateSeal instance - agent_forward([ - encode_oz_revoke_role( - contract=contracts.csm, - role_name="PAUSE_ROLE", - revoke_from=CS_GATE_SEAL_ADDRESS - ) - ]), - - # 51. Revoke CSAccounting role PAUSE_ROLE from the previous GateSeal instance - agent_forward([ - encode_oz_revoke_role( - contract=contracts.cs_accounting, - role_name="PAUSE_ROLE", - revoke_from=CS_GATE_SEAL_ADDRESS - ) - ]), - - # 52. Revoke CSFeeOracle role PAUSE_ROLE from the previous GateSeal instance - agent_forward([ - encode_oz_revoke_role( - contract=contracts.cs_fee_oracle, - role_name="PAUSE_ROLE", - revoke_from=CS_GATE_SEAL_ADDRESS - ) - ]), - - # 53. Grant CSM role PAUSE_ROLE for the new GateSeal instance - agent_forward([ - encode_oz_grant_role( - contract=contracts.csm, - role_name="PAUSE_ROLE", - grant_to=CS_GATE_SEAL_V2_ADDRESS - ) - ]), - - # 54. Grant CSAccounting role PAUSE_ROLE for the new GateSeal instance - agent_forward([ - encode_oz_grant_role( - contract=contracts.cs_accounting, - role_name="PAUSE_ROLE", - grant_to=CS_GATE_SEAL_V2_ADDRESS - ) - ]), - - # 55. Grant CSFeeOracle role PAUSE_ROLE for the new GateSeal instance - agent_forward([ - encode_oz_grant_role( - contract=contracts.cs_fee_oracle, - role_name="PAUSE_ROLE", - grant_to=CS_GATE_SEAL_V2_ADDRESS - ) - ]), - - # 56. Grant MANAGE_BOND_CURVES_ROLE to the AGENT - agent_forward([ - encode_oz_grant_role( - contract=contracts.cs_accounting, - role_name="MANAGE_BOND_CURVES_ROLE", - grant_to=contracts.agent - ) - ]), - - # 57. Add Identified Community Stakers Gate Bond Curve - agent_forward([ - (contracts.cs_accounting.address, - contracts.cs_accounting.addBondCurve.encode_input(CS_ICS_GATE_BOND_CURVE)) - ]), - - # 58. Revoke MANAGE_BOND_CURVES_ROLE from the AGENT - agent_forward([ - encode_oz_revoke_role( - contract=contracts.cs_accounting, - role_name="MANAGE_BOND_CURVES_ROLE", - revoke_from=contracts.agent - ) - ]), - - # 59. Increase CSM share in Staking Router from 15% to 16% - agent_forward([ - (contracts.staking_router.address, - contracts.staking_router.updateStakingModule.encode_input( - CS_MODULE_ID, - CS_MODULE_NEW_TARGET_SHARE_BP, - CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP, - CS_MODULE_MODULE_FEE_BP, - CS_MODULE_TREASURY_FEE_BP, - CS_MODULE_MAX_DEPOSITS_PER_BLOCK, - CS_MODULE_MIN_DEPOSIT_BLOCK_DISTANCE - )) - ]), - - # Gate seals and node operator changes (steps 60-68) - # 60. Revoke PAUSE_ROLE on WithdrawalQueue from the old GateSeal - agent_forward([ - encode_oz_revoke_role( - contract=contracts.withdrawal_queue, - role_name="PAUSE_ROLE", - revoke_from=OLD_GATE_SEAL_ADDRESS - ) - ]), - - # 61. Revoke PAUSE_ROLE on ValidatorsExitBusOracle from the old GateSeal - agent_forward([ - encode_oz_revoke_role( - contract=contracts.validators_exit_bus_oracle, - role_name="PAUSE_ROLE", - revoke_from=OLD_GATE_SEAL_ADDRESS - ) - ]), - - # 62. Grant PAUSE_ROLE on WithdrawalQueue to the new WithdrawalQueue GateSeal - agent_forward([ - encode_oz_grant_role( - contract=contracts.withdrawal_queue, - role_name="PAUSE_ROLE", - grant_to=NEW_WQ_GATE_SEAL - ) - ]), - - # 63. Grant PAUSE_ROLE on ValidatorsExitBusOracle to the new Triggerable Withdrawals GateSeal - agent_forward([ - encode_oz_grant_role( - contract=contracts.validators_exit_bus_oracle, - role_name="PAUSE_ROLE", - grant_to=NEW_TW_GATE_SEAL - ) - ]), - - # 64. Grant PAUSE_ROLE on TriggerableWithdrawalsGateway to the new Triggerable Withdrawals GateSeal - agent_forward([ - encode_oz_grant_role( - contract=interface.TriggerableWithdrawalsGateway(TRIGGERABLE_WITHDRAWALS_GATEWAY), - role_name="PAUSE_ROLE", - grant_to=NEW_TW_GATE_SEAL - ) - ]), - - # 65. Grant PAUSE_ROLE on TriggerableWithdrawalsGateway to ResealManager - agent_forward([ - encode_oz_grant_role( - contract=interface.TriggerableWithdrawalsGateway(TRIGGERABLE_WITHDRAWALS_GATEWAY), - role_name="PAUSE_ROLE", - grant_to=RESEAL_MANAGER - ) - ]), - - # 66. Grant RESUME_ROLE on TriggerableWithdrawalsGateway to ResealManager - agent_forward([ - encode_oz_grant_role( - contract=interface.TriggerableWithdrawalsGateway(TRIGGERABLE_WITHDRAWALS_GATEWAY), - role_name="RESUME_ROLE", - grant_to=RESEAL_MANAGER - ) - ]), - - # Node operator changes - # 67. Rename Node Operator ID 25 from Nethermind to Twinstake - agent_forward( - [encode_set_node_operator_name(id=25, name="Twinstake", registry=contracts.node_operators_registry)]), - - # 68. Change Node Operator ID 17 reward address - agent_forward([encode_set_node_operator_reward_address(id=25, - rewardAddress="0x36201ed66DbC284132046ee8d99272F8eEeb24c8", - registry=contracts.node_operators_registry)]), - # "69. Remove Kiln guardian" - agent_forward([ - encode_remove_guardian(dsm=contracts.deposit_security_module, guardian_address=OLD_KILN_ADDRESS, quorum_size=4), - ]), - # "70. Add new Kiln guardian" - agent_forward([ - encode_add_guardian(dsm=contracts.deposit_security_module, guardian_address=NEW_KILN_ADDRESS, quorum_size=4), - ]), - ] - - # Convert each dg_item to the expected format - proposal_calls = [] - for dg_item in dg_items: - target, data = dg_item # agent_forward returns (target, data) - proposal_calls.append({ - "target": target, - "value": 0, - "data": data - }) - - return proposal_calls - - -def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_governance_proposal_calls): - # Save original implementations for comparison - locator_impl_before = get_ossifiable_proxy_impl(contracts.lido_locator) - accounting_oracle_impl_before = get_ossifiable_proxy_impl(contracts.accounting_oracle) - vebo_impl_before = get_ossifiable_proxy_impl(contracts.validators_exit_bus_oracle) - withdrawal_vault_impl_before = get_wv_contract_proxy_impl(contracts.withdrawal_vault) - staking_router_impl_before = get_ossifiable_proxy_impl(contracts.staking_router) - - csm_impl_before = get_ossifiable_proxy_impl(contracts.csm.address) - cs_accounting_impl_before = get_ossifiable_proxy_impl(contracts.cs_accounting.address) - cs_fee_oracle_impl_before = get_ossifiable_proxy_impl(contracts.cs_fee_oracle.address) - cs_fee_distributor_impl_before = get_ossifiable_proxy_impl(contracts.cs_fee_distributor.address) - - voting = interface.Voting(VOTING) - timelock = interface.EmergencyProtectedTimelock(EMERGENCY_PROTECTED_TIMELOCK) - dual_governance = interface.DualGovernance(DUAL_GOVERNANCE) - - # Not yet used by the protocol, but needed for the test - triggerable_withdrawals_gateway = interface.TriggerableWithdrawalsGateway(TRIGGERABLE_WITHDRAWALS_GATEWAY) - cs_ejector = interface.CSEjector(CS_EJECTOR_ADDRESS) - cs_permissionless_gate = interface.CSPermissionlessGate(CS_PERMISSIONLESS_GATE_ADDRESS) - cs_vetted_gate = interface.CSVettedGate(CS_VETTED_GATE_ADDRESS) - cs_verifier_v2 = interface.CSVerifierV2(CS_VERIFIER_V2_ADDRESS) - - no_registry = interface.NodeOperatorsRegistry(NODE_OPERATORS_REGISTRY_ADDRESS) - - # START VOTE - if vote_ids_from_env: - vote_id = vote_ids_from_env[0] - if EXPECTED_VOTE_ID is not None: - assert vote_id == EXPECTED_VOTE_ID - elif EXPECTED_VOTE_ID is not None and voting.votesLength() > EXPECTED_VOTE_ID: - vote_id = EXPECTED_VOTE_ID - else: - vote_id, _ = start_vote({"from": ldo_holder}, silent=True) - - _, call_script_items = get_vote_items() - onchain_script = voting.getVote(vote_id)["script"] - assert onchain_script == encode_call_script(call_script_items) - - # ============================================================================ - # ============================= Execute Vote ============================== - # ========================================================================= - is_executed = voting.getVote(vote_id)["executed"] - if not is_executed: - # ======================================================================= - # ========================= Before voting checks ======================== - # ======================================================================= - # CSM Step 65: EasyTrack factories before vote (pre-vote state) - initial_factories = contracts.easy_track.getEVMScriptFactories() - assert EASYTRACK_CS_SET_VETTED_GATE_TREE_FACTORY not in initial_factories, "EasyTrack should not have CSMSetVettedGateTree factory before vote" - assert EASYTRACK_SDVT_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY not in initial_factories, "EasyTrack should not have SDVT validator exit request hashes factory before vote" - assert EASYTRACK_CURATED_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY not in initial_factories, "EasyTrack should not have Curated validator exit request hashes factory before vote" - - assert get_lido_vote_cid_from_str(find_metadata_by_vote_id(vote_id)) == IPFS_DESCRIPTION_HASH - - vote_tx: TransactionReceipt = helpers.execute_vote(vote_id=vote_id, accounts=accounts, dao_voting=voting) - #display_voting_events(vote_tx) - vote_events = group_voting_events_from_receipt(vote_tx) - - # ======================================================================= - # ========================= After voting checks ========================= - # ======================================================================= - # Step 65: Add EasyTrack factory for CSSetVettedGateTree - new_factories = contracts.easy_track.getEVMScriptFactories() - assert EASYTRACK_CS_SET_VETTED_GATE_TREE_FACTORY in new_factories, "EasyTrack should have CSSetVettedGateTree factory after vote" - - # Steps 66-67: Validate EasyTrack factories for validator exit request hashes - assert EASYTRACK_SDVT_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY in new_factories, "EasyTrack should have SDVT validator exit request hashes factory after vote" - assert EASYTRACK_CURATED_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY in new_factories, "EasyTrack should have Curated validator exit request hashes factory after vote" - - # --- VALIDATE EVENTS --- - voting_events = group_voting_events_from_receipt(vote_tx) - # Validate voting events structure - dg_voting_event, dg_bypass_voting_event1, dg_bypass_voting_event2, dg_bypass_voting_event3 = voting_events - - assert len(vote_events) == EXPECTED_VOTE_EVENTS_COUNT, "Unexpected number of dual governance events" - assert count_vote_items_by_events(vote_tx, voting.address) == EXPECTED_VOTE_EVENTS_COUNT - if EXPECTED_DG_PROPOSAL_ID is not None: - assert EXPECTED_DG_PROPOSAL_ID == timelock.getProposalsCount() - - # Validate DG Proposal Submit event - validate_dual_governance_submit_event( - vote_events[0], - proposal_id=EXPECTED_DG_PROPOSAL_ID, - proposer=VOTING, - executor=DUAL_GOVERNANCE_ADMIN_EXECUTOR, - metadata="Upgrade to CSM v2 and Triggerable Withdrawals", - proposal_calls=dual_governance_proposal_calls, - emitted_by=[EMERGENCY_PROTECTED_TIMELOCK, DUAL_GOVERNANCE], - ) - - # Validate EasyTrack bypass events for new factories - validate_evmscript_factory_added_event( - event=dg_bypass_voting_event1, - p=EVMScriptFactoryAdded( - factory_addr=EASYTRACK_CS_SET_VETTED_GATE_TREE_FACTORY, - permissions=create_permissions(interface.CSVettedGate(CS_VETTED_GATE_ADDRESS), "setTreeParams") - ), - emitted_by=contracts.easy_track, - ) - - validate_evmscript_factory_added_event( - event=dg_bypass_voting_event2, - p=EVMScriptFactoryAdded( - factory_addr=EASYTRACK_SDVT_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY, - permissions=create_permissions(contracts.validators_exit_bus_oracle, "submitExitRequestsHash") - ), - emitted_by=contracts.easy_track, - ) - - validate_evmscript_factory_added_event( - event=dg_bypass_voting_event3, - p=EVMScriptFactoryAdded( - factory_addr=EASYTRACK_CURATED_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY, - permissions=create_permissions(contracts.validators_exit_bus_oracle, "submitExitRequestsHash") - ), - emitted_by=contracts.easy_track, - ) - - if EXPECTED_DG_PROPOSAL_ID is not None: - details = timelock.getProposalDetails(EXPECTED_DG_PROPOSAL_ID) - if details["status"] != PROPOSAL_STATUS["executed"]: - # ========================================================================= - # ================== DG before proposal executed checks =================== - # ========================================================================= - # Step 1: Check Lido Locator implementation initial state - assert locator_impl_before != LIDO_LOCATOR_IMPL, "Locator implementation should be different before upgrade" - - # Step 2: Check VEBO implementation initial state - assert vebo_impl_before != VALIDATORS_EXIT_BUS_ORACLE_IMPL, "VEBO implementation should be different before upgrade" - - # Step 3: Check VEBO finalizeUpgrade_v2 state - try: # FIXME: with reverts - assert contracts.validators_exit_bus_oracle.getMaxValidatorsPerReport() != 600, "VEBO max validators per report should not be 600 before upgrade" # FIXME: magic number - except Exception: - pass # Function might not exist yet - - # Steps 4-6: Check VEBO consensus version management - initial_vebo_consensus_version = contracts.validators_exit_bus_oracle.getConsensusVersion() - assert initial_vebo_consensus_version < VEBO_CONSENSUS_VERSION, f"VEBO consensus version should be less than {VEBO_CONSENSUS_VERSION}" - - # Step 7: Check TWG role for CS Ejector initial state - add_full_withdrawal_request_role = triggerable_withdrawals_gateway.ADD_FULL_WITHDRAWAL_REQUEST_ROLE() - assert not triggerable_withdrawals_gateway.hasRole(add_full_withdrawal_request_role, - cs_ejector), "CS Ejector should not have ADD_FULL_WITHDRAWAL_REQUEST_ROLE before upgrade" - - # Step 8: Check TWG role for VEB initial state - assert not triggerable_withdrawals_gateway.hasRole(add_full_withdrawal_request_role, - contracts.validators_exit_bus_oracle), "VEBO should not have ADD_FULL_WITHDRAWAL_REQUEST_ROLE before upgrade" - - # Step 9: Check EasyTrack VEB SUBMIT_REPORT_HASH_ROLE initial state - submit_report_hash_role = web3.keccak(text="SUBMIT_REPORT_HASH_ROLE") - assert not contracts.validators_exit_bus_oracle.hasRole(submit_report_hash_role, - EASYTRACK_EVMSCRIPT_EXECUTOR), "EasyTrack executor should not have SUBMIT_REPORT_HASH_ROLE on VEBO before upgrade" - - # Step 10: Check DualGovernance tiebreaker initial state - tiebreaker_details = contracts.dual_governance.getTiebreakerDetails() - initial_tiebreakers = tiebreaker_details[3] # sealableWithdrawalBlockers - assert TRIGGERABLE_WITHDRAWALS_GATEWAY not in initial_tiebreakers, "TWG should not be in tiebreaker list before upgrade" - - # Step 9: Check Withdrawal Vault implementation initial state - assert withdrawal_vault_impl_before != WITHDRAWAL_VAULT_IMPL, "Withdrawal Vault implementation should be different before upgrade" - - # Step 10: Withdrawal Vault finalizeUpgrade_v2 check is done post-execution - assert contracts.withdrawal_vault.getContractVersion() == 1, "Withdrawal Vault version should be 1 before upgrade" - - # Step 11: Check Accounting Oracle implementation initial state - assert accounting_oracle_impl_before != ACCOUNTING_ORACLE_IMPL, "Accounting Oracle implementation should be different before upgrade" - - # Steps 12-14: Check AO consensus version management - initial_ao_consensus_version = contracts.accounting_oracle.getConsensusVersion() - assert initial_ao_consensus_version < AO_CONSENSUS_VERSION, f"AO consensus version should be less than {AO_CONSENSUS_VERSION}" - assert not contracts.accounting_oracle.hasRole(contracts.accounting_oracle.MANAGE_CONSENSUS_VERSION_ROLE(), - contracts.agent), "Agent should not have MANAGE_CONSENSUS_VERSION_ROLE on AO before upgrade" - - # Step 17: Check AO version before finalizeUpgrade_v3 - assert contracts.accounting_oracle.getContractVersion() == 2, "AO contract version should be 2 before finalizeUpgrade_v3" - - # Step 15: Check Staking Router implementation initial state - assert staking_router_impl_before != STAKING_ROUTER_IMPL, "Staking Router implementation should be different before upgrade" - - # Steps 16-17: Check SR roles initial state - try: - report_validator_exiting_status_role = contracts.staking_router.REPORT_VALIDATOR_EXITING_STATUS_ROLE() - report_validator_exit_triggered_role = contracts.staking_router.REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE() - except Exception as e: - assert "Unknown typed error: 0x" in str(e), f"Unexpected error: {e}" - report_validator_exiting_status_role = ZERO_ADDRESS - report_validator_exit_triggered_role = ZERO_ADDRESS - - assert report_validator_exiting_status_role == ZERO_ADDRESS, "REPORT_VALIDATOR_EXITING_STATUS_ROLE should not exist before upgrade" - assert report_validator_exit_triggered_role == ZERO_ADDRESS, "REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE should not exist before upgrade" - - # Step 18: Check APP_MANAGER_ROLE initial state - app_manager_role = web3.keccak(text="APP_MANAGER_ROLE") - assert contracts.acl.getPermissionManager(ARAGON_KERNEL, - app_manager_role) == AGENT, "AGENT should be the permission manager for APP_MANAGER_ROLE" - assert contracts.node_operators_registry.kernel() == ARAGON_KERNEL, "Node Operators Registry must use the correct kernel" - assert not contracts.acl.hasPermission(VOTING, ARAGON_KERNEL, - app_manager_role), "VOTING should not have APP_MANAGER_ROLE before the upgrade" - assert not contracts.acl.hasPermission(AGENT, ARAGON_KERNEL, - app_manager_role), "AGENT should not have APP_MANAGER_ROLE before the upgrade" - - # Steps 19-23: Check NOR and sDVT initial state - assert not contracts.acl.hasPermission(contracts.agent, contracts.kernel, - app_manager_role), "Agent should not have APP_MANAGER_ROLE before upgrade" - assert contracts.node_operators_registry.getContractVersion() == 3, "Node Operators Registry version should be 3 before upgrade" - assert contracts.simple_dvt.getContractVersion() == 3, "Simple DVT version should be 3 before upgrade" - - # Step 24: Check CONFIG_MANAGER_ROLE initial state - config_manager_role = contracts.oracle_daemon_config.CONFIG_MANAGER_ROLE() - assert not contracts.oracle_daemon_config.hasRole(config_manager_role, - contracts.agent), "Agent should not have CONFIG_MANAGER_ROLE on Oracle Daemon Config before upgrade" - - # Steps 25-27: Check Oracle Daemon Config variables to be removed - try: - contracts.oracle_daemon_config.get('NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP') - contracts.oracle_daemon_config.get('VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS') - contracts.oracle_daemon_config.get('VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS') - except Exception as e: - assert False, f"Expected variables to exist before removal: {e}" - - # Step 28: Check that EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS doesn't exist yet - try: - contracts.oracle_daemon_config.get('EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS') - assert False, "EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS should not exist before vote" - except Exception: - pass # Expected to fail - - # Step 29: Check CSM implementation initial state - assert csm_impl_before != CSM_IMPL_V2_ADDRESS, "CSM implementation should be different before vote" - - # Step 30: Check CSM finalizeUpgradeV2 initial state - with reverts(): - # The function should not exist yet - contracts.csm.getInitializedVersion() - - # CSM Step 32: Check CSAccounting implementation (pre-vote state) - assert cs_accounting_impl_before != CS_ACCOUNTING_IMPL_V2_ADDRESS, "CSAccounting implementation should be different before vote" - - # CSM Step 33: Check CSAccounting finalizeUpgradeV2 was not called (pre-vote state) - with reverts(): - # The function should not exist yet - contracts.cs_accounting.getInitializedVersion() - - # CSM Step 34: Check CSFeeOracle implementation (pre-vote state) - assert cs_fee_oracle_impl_before != CS_FEE_ORACLE_IMPL_V2_ADDRESS, "CSFeeOracle implementation should be different before vote" - - # CSM Step 35: Check CSFeeOracle finalizeUpgradeV2 was not called (pre-vote state) - assert contracts.cs_fee_oracle.getContractVersion() < CS_FEE_ORACLE_V2_VERSION, f"CSFeeOracle version should be less than {CS_FEE_ORACLE_V2_VERSION} before vote" - assert contracts.cs_fee_oracle.getConsensusVersion() < 3, "CSFeeOracle consensus version should be less than 3 before vote" - - # CSM Step 36: Check CSFeeDistributor implementation (pre-vote state) - assert cs_fee_distributor_impl_before != CS_FEE_DISTRIBUTOR_IMPL_V2_ADDRESS, "CSFeeDistributor implementation should be different before vote" - - # CSM Step 37: Check CSFeeDistributor finalizeUpgradeV2 was not called (pre-vote state) - with reverts(): - # The function should not exist yet - contracts.cs_fee_distributor.getInitializedVersion() - - # CSM Steps 38-40: CSAccounting roles (pre-vote state) - assert contracts.cs_accounting.hasRole(contracts.cs_accounting.SET_BOND_CURVE_ROLE(), contracts.csm.address), "CSM should have SET_BOND_CURVE_ROLE on CSAccounting before vote" - assert contracts.cs_accounting.hasRole(web3.keccak(text="RESET_BOND_CURVE_ROLE"), contracts.csm.address), "CSM should have RESET_BOND_CURVE_ROLE on CSAccounting before vote" - assert contracts.cs_accounting.hasRole(web3.keccak(text="RESET_BOND_CURVE_ROLE"), CSM_COMMITTEE_MS), "CSM committee should have RESET_BOND_CURVE_ROLE on CSAccounting before vote" - - # CSM Steps 41-42: CSM roles (pre-vote state) - assert not contracts.csm.hasRole(web3.keccak(text="CREATE_NODE_OPERATOR_ROLE"), cs_permissionless_gate.address), "Permissionless gate should not have CREATE_NODE_OPERATOR_ROLE on CSM before vote" - assert not contracts.csm.hasRole(web3.keccak(text="CREATE_NODE_OPERATOR_ROLE"), cs_vetted_gate.address), "Vetted gate should not have CREATE_NODE_OPERATOR_ROLE on CSM before vote" - - # CSM Step 43: CSAccounting bond curve role for vetted gate (pre-vote state) - assert not contracts.cs_accounting.hasRole(contracts.cs_accounting.SET_BOND_CURVE_ROLE(), cs_vetted_gate.address), "Vetted gate should not have SET_BOND_CURVE_ROLE on CSAccounting before vote" - - # CSM Steps 44-45: Verifier roles (pre-vote state) - assert contracts.csm.hasRole(contracts.csm.VERIFIER_ROLE(), CS_VERIFIER_ADDRESS_OLD), "Old verifier should have VERIFIER_ROLE on CSM before vote" - assert not contracts.csm.hasRole(contracts.csm.VERIFIER_ROLE(), cs_verifier_v2.address), "New verifier should not have VERIFIER_ROLE on CSM before vote" - - # CSM Steps 46-51: GateSeal roles (pre-vote state) - assert contracts.csm.hasRole(contracts.csm.PAUSE_ROLE(), CS_GATE_SEAL_ADDRESS), "Old GateSeal should have PAUSE_ROLE on CSM before vote" - assert contracts.cs_accounting.hasRole(contracts.cs_accounting.PAUSE_ROLE(), CS_GATE_SEAL_ADDRESS), "Old GateSeal should have PAUSE_ROLE on CSAccounting before vote" - assert contracts.cs_fee_oracle.hasRole(contracts.cs_fee_oracle.PAUSE_ROLE(), CS_GATE_SEAL_ADDRESS), "Old GateSeal should have PAUSE_ROLE on CSFeeOracle before vote" - - assert not contracts.csm.hasRole(contracts.csm.PAUSE_ROLE(), CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should not have PAUSE_ROLE on CSM before vote" - assert not contracts.cs_accounting.hasRole(contracts.cs_accounting.PAUSE_ROLE(), CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should not have PAUSE_ROLE on CSAccounting before vote" - assert not contracts.cs_fee_oracle.hasRole(contracts.cs_fee_oracle.PAUSE_ROLE(), CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should not have PAUSE_ROLE on CSFeeOracle before vote" - - # CSM Step 52: Staking Router CSM module state before vote (pre-vote state) - csm_module_before = contracts.staking_router.getStakingModule(CS_MODULE_ID) - csm_share_before = csm_module_before['stakeShareLimit'] - csm_priority_exit_threshold_before = csm_module_before['priorityExitShareThreshold'] - assert csm_share_before != CS_MODULE_NEW_TARGET_SHARE_BP, f"CSM share should not be {CS_MODULE_NEW_TARGET_SHARE_BP} before vote, current: {csm_share_before}" - assert csm_priority_exit_threshold_before != CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP, f"CSM priority exit threshold should not be {CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP} before vote, current: {csm_priority_exit_threshold_before}" - - # Gate Seals: Check initial states before vote - assert contracts.withdrawal_queue.hasRole(contracts.withdrawal_queue.PAUSE_ROLE(), OLD_GATE_SEAL_ADDRESS), "Old GateSeal should have PAUSE_ROLE on WithdrawalQueue before vote" - assert contracts.validators_exit_bus_oracle.hasRole(contracts.validators_exit_bus_oracle.PAUSE_ROLE(), OLD_GATE_SEAL_ADDRESS), "Old GateSeal should have PAUSE_ROLE on VEBO before vote" - assert not contracts.withdrawal_queue.hasRole(contracts.withdrawal_queue.PAUSE_ROLE(), NEW_WQ_GATE_SEAL), "New WQ GateSeal should not have PAUSE_ROLE on WithdrawalQueue before vote" - assert not contracts.validators_exit_bus_oracle.hasRole(contracts.validators_exit_bus_oracle.PAUSE_ROLE(), NEW_TW_GATE_SEAL), "New TW GateSeal should not have PAUSE_ROLE on VEBO before vote" - assert not triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.PAUSE_ROLE(), NEW_TW_GATE_SEAL), "New TW GateSeal should not have PAUSE_ROLE on TWG before vote" - - # ResealManager: Check initial states before vote - assert not triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.PAUSE_ROLE(), RESEAL_MANAGER), "ResealManager should not have PAUSE_ROLE on TWG before vote" - assert not triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.RESUME_ROLE(), RESEAL_MANAGER), "ResealManager should not have RESUME_ROLE on TWG before vote" - # Rename Nethermind NO - nethermind_no_data_before = no_registry.getNodeOperator(NETHERMIND_NO_ID, True) - - assert nethermind_no_data_before["rewardAddress"] == NETHERMIND_NO_STAKING_REWARDS_ADDRESS_OLD - assert nethermind_no_data_before["name"] == NETHERMIND_NO_NAME_OLD - - if details["status"] == PROPOSAL_STATUS["submitted"]: - chain.sleep(timelock.getAfterSubmitDelay() + 1) - dual_governance.scheduleProposal(EXPECTED_DG_PROPOSAL_ID, {"from": stranger}) - - if timelock.getProposalDetails(EXPECTED_DG_PROPOSAL_ID)["status"] == PROPOSAL_STATUS["scheduled"]: - chain.sleep(timelock.getAfterScheduleDelay() + 1) - dg_tx: TransactionReceipt = timelock.execute(EXPECTED_DG_PROPOSAL_ID, {"from": stranger}) - display_dg_events(dg_tx) - dg_events = group_dg_events_from_receipt( - dg_tx, - timelock=EMERGENCY_PROTECTED_TIMELOCK, - admin_executor=DUAL_GOVERNANCE_ADMIN_EXECUTOR, - ) - assert count_vote_items_by_events(dg_tx, AGENT) == EXPECTED_DG_EVENTS_FROM_AGENT - assert len(dg_events) == EXPECTED_DG_EVENTS_COUNT - - # === DG EXECUTION EVENTS VALIDATION === - # 0. Lido Locator upgrade events - validate_proxy_upgrade_event(dg_events[0], LIDO_LOCATOR_IMPL, emitted_by=contracts.lido_locator) - - # 1. VEBO upgrade events - validate_proxy_upgrade_event(dg_events[1], VALIDATORS_EXIT_BUS_ORACLE_IMPL, emitted_by=contracts.validators_exit_bus_oracle) - - # 2. VEBO finalize upgrade events - validate_contract_version_set_event(dg_events[2], version=2, emitted_by=contracts.validators_exit_bus_oracle) - assert 'ExitRequestsLimitSet' in dg_events[2], "ExitRequestsLimitSet event not found" - assert dg_events[2]['ExitRequestsLimitSet'][0]['maxExitRequestsLimit'] == MAX_EXIT_REQUESTS_LIMIT, "Wrong maxExitRequestsLimit" - assert dg_events[2]['ExitRequestsLimitSet'][0]['exitsPerFrame'] == EXITS_PER_FRAME, "Wrong exitsPerFrame" - assert dg_events[2]['ExitRequestsLimitSet'][0]['frameDurationInSec'] == FRAME_DURATION_IN_SEC, "Wrong frameDurationInSec" - - # 3. Grant VEBO MANAGE_CONSENSUS_VERSION_ROLE to Agent - validate_role_grant_event( - dg_events[3], - role_hash=web3.keccak(text="MANAGE_CONSENSUS_VERSION_ROLE").hex(), - account=contracts.agent.address, - emitted_by=contracts.validators_exit_bus_oracle - ) - - # 4. Set VEBO consensus version to 4 - validate_consensus_version_set_event( - dg_events[4], - new_version=4, - prev_version=3, - emitted_by=contracts.validators_exit_bus_oracle - ) - - # 5. Revoke VEBO MANAGE_CONSENSUS_VERSION_ROLE from Agent - validate_role_revoke_event( - dg_events[5], - role_hash=web3.keccak(text="MANAGE_CONSENSUS_VERSION_ROLE").hex(), - account=contracts.agent.address, - emitted_by=contracts.validators_exit_bus_oracle - ) - - # 6. Grant VEBO SUBMIT_REPORT_HASH_ROLE to EasyTrack executor - validate_role_grant_event( - dg_events[6], - role_hash=web3.keccak(text="SUBMIT_REPORT_HASH_ROLE").hex(), - account=EASYTRACK_EVMSCRIPT_EXECUTOR, - emitted_by=contracts.validators_exit_bus_oracle - ) - - # 7. Grant TWG ADD_FULL_WITHDRAWAL_REQUEST_ROLE to CS Ejector - validate_role_grant_event( - dg_events[7], - role_hash=web3.keccak(text="ADD_FULL_WITHDRAWAL_REQUEST_ROLE").hex(), - account=CS_EJECTOR_ADDRESS, - emitted_by=triggerable_withdrawals_gateway - ) - - # 8. Grant TWG ADD_FULL_WITHDRAWAL_REQUEST_ROLE to VEBO - validate_role_grant_event( - dg_events[8], - role_hash=web3.keccak(text="ADD_FULL_WITHDRAWAL_REQUEST_ROLE").hex(), - account=contracts.validators_exit_bus_oracle.address, - emitted_by=triggerable_withdrawals_gateway - ) - - # 9. Connect TWG to Dual Governance tiebreaker - assert 'SealableWithdrawalBlockerAdded' in dg_events[ - 9], "SealableWithdrawalBlockerAdded event not found" - assert dg_events[9]['SealableWithdrawalBlockerAdded'][0]['sealable'] == TRIGGERABLE_WITHDRAWALS_GATEWAY, "Wrong sealableWithdrawalBlocker" - - # 10. Update WithdrawalVault implementation - validate_proxy_upgrade_event(dg_events[10], WITHDRAWAL_VAULT_IMPL, emitted_by=contracts.withdrawal_vault) - - # 11. Call finalizeUpgrade_v2 on WithdrawalVault - validate_contract_version_set_event(dg_events[11], version=2, emitted_by=contracts.withdrawal_vault) - - # 12. Update AO implementation - validate_proxy_upgrade_event(dg_events[12], ACCOUNTING_ORACLE_IMPL, emitted_by=contracts.accounting_oracle) - - # 13. Grant AO MANAGE_CONSENSUS_VERSION_ROLE to the AGENT - validate_role_grant_event( - dg_events[13], - role_hash=web3.keccak(text="MANAGE_CONSENSUS_VERSION_ROLE").hex(), - account=contracts.agent.address, - emitted_by=contracts.accounting_oracle - ) - - # 14. Bump AO consensus version to 4 - validate_consensus_version_set_event( - dg_events[14], - new_version=4, - prev_version=3, - emitted_by=contracts.accounting_oracle - ) - - # 15. Revoke AO MANAGE_CONSENSUS_VERSION_ROLE from the AGENT - validate_role_revoke_event( - dg_events[15], - role_hash=web3.keccak(text="MANAGE_CONSENSUS_VERSION_ROLE").hex(), - account=contracts.agent.address, - emitted_by=contracts.accounting_oracle - ) - - # 16. Call finalizeUpgrade_v3() on AO - validate_contract_version_set_event(dg_events[16], version=3, emitted_by=contracts.accounting_oracle) - - # 17. Update SR implementation - validate_proxy_upgrade_event(dg_events[17], STAKING_ROUTER_IMPL, emitted_by=contracts.staking_router) - - # 18. Call finalizeUpgrade_v3() on SR - validate_contract_version_set_event(dg_events[18], version=3, emitted_by=contracts.staking_router) - - # 19. Grant SR REPORT_VALIDATOR_EXITING_STATUS_ROLE to ValidatorExitVerifier - validate_role_grant_event( - dg_events[19], - role_hash=web3.keccak(text="REPORT_VALIDATOR_EXITING_STATUS_ROLE").hex(), - account=VALIDATOR_EXIT_VERIFIER, - emitted_by=contracts.staking_router - ) - - # 20. Grant SR REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE to TWG - validate_role_grant_event( - dg_events[20], - role_hash=web3.keccak(text="REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE").hex(), - account=triggerable_withdrawals_gateway.address, - emitted_by=contracts.staking_router - ) - - # 21. Grant APP_MANAGER_ROLE on Kernel to Voting - assert 'SetPermission' in dg_events[21] - assert dg_events[21]['SetPermission'][0]['allowed'] is True - - # 22. Set new implementation for NOR - assert 'SetApp' in dg_events[22] - - # 23. Finalize upgrade for NOR - validate_contract_version_set_event(dg_events[23], version=4, emitted_by=contracts.node_operators_registry) - assert 'ExitDeadlineThresholdChanged' in dg_events[23] - assert dg_events[23]['ExitDeadlineThresholdChanged'][0]['threshold'] == NOR_EXIT_DEADLINE_IN_SEC - - # 24. Set new implementation for sDVT - assert 'SetApp' in dg_events[24] - - # 25. Finalize upgrade for sDVT - validate_contract_version_set_event(dg_events[25], version=4, emitted_by=contracts.simple_dvt) - assert 'ExitDeadlineThresholdChanged' in dg_events[25] - assert dg_events[25]['ExitDeadlineThresholdChanged'][0]['threshold'] == NOR_EXIT_DEADLINE_IN_SEC - - # 26. Revoke APP_MANAGER_ROLE on Kernel from Voting - assert 'SetPermission' in dg_events[26] - assert dg_events[26]['SetPermission'][0]['allowed'] is False - - # 27. Grant CONFIG_MANAGER_ROLE on OracleDaemonConfig to Agent - validate_role_grant_event( - dg_events[27], - role_hash=contracts.oracle_daemon_config.CONFIG_MANAGER_ROLE().hex(), - account=contracts.agent.address, - emitted_by=contracts.oracle_daemon_config - ) - - # 28. Unset NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP - assert 'ConfigValueUnset' in dg_events[28] - assert 'NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP' in \ - dg_events[28]['ConfigValueUnset'][0]['key'] - - # 29. Unset VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS - assert 'ConfigValueUnset' in dg_events[29] - assert 'VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS' in dg_events[29]['ConfigValueUnset'][0]['key'] - - # 30. Unset VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS - assert 'ConfigValueUnset' in dg_events[30] - assert 'VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS' in dg_events[30]['ConfigValueUnset'][0]['key'] - - # 31. Set EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS - assert 'ConfigValueSet' in dg_events[31] - assert 'EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS' in dg_events[31]['ConfigValueSet'][0]['key'] - assert convert.to_int(dg_events[31]['ConfigValueSet'][0]['value']) == EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS - - # 32. Revoke CONFIG_MANAGER_ROLE from the AGENT - validate_role_revoke_event( - dg_events[32], - role_hash=contracts.oracle_daemon_config.CONFIG_MANAGER_ROLE().hex(), - account=contracts.agent.address, - emitted_by=contracts.oracle_daemon_config - ) - - # 33. CSM implementation upgrade - validate_proxy_upgrade_event(dg_events[33], CSM_IMPL_V2_ADDRESS, emitted_by=contracts.csm) - - # 34. CSM finalize upgrade validation - assert 'Initialized' in dg_events[34] - assert dg_events[34]['Initialized'][0]['version'] == CSM_V2_VERSION - - # 35. CSAccounting implementation upgrade - validate_proxy_upgrade_event(dg_events[35], CS_ACCOUNTING_IMPL_V2_ADDRESS, emitted_by=contracts.cs_accounting) - - # 36. CSAccounting finalize upgrade with bond curves - assert 'BondCurveAdded' in dg_events[36] - assert len(dg_events[36]['BondCurveAdded']) == len(CS_CURVES) - assert 'Initialized' in dg_events[36] - assert dg_events[36]['Initialized'][0]['version'] == CS_ACCOUNTING_V2_VERSION - - # 37. CSFeeOracle implementation upgrade - validate_proxy_upgrade_event(dg_events[37], CS_FEE_ORACLE_IMPL_V2_ADDRESS, emitted_by=contracts.cs_fee_oracle) - - # 38. CSFeeOracle finalize upgrade with consensus version - validate_consensus_version_set_event(dg_events[38], new_version=3, prev_version=2, emitted_by=contracts.cs_fee_oracle) - validate_contract_version_set_event(dg_events[38], version=CS_FEE_ORACLE_V2_VERSION, emitted_by=contracts.cs_fee_oracle) - - # 39. CSFeeDistributor implementation upgrade - validate_proxy_upgrade_event(dg_events[39], CS_FEE_DISTRIBUTOR_IMPL_V2_ADDRESS, emitted_by=contracts.cs_fee_distributor) - - # 40. CSFeeDistributor finalize upgrade - assert 'RebateRecipientSet' in dg_events[40] - assert 'Initialized' in dg_events[40] - assert dg_events[40]['Initialized'][0]['version'] == CS_FEE_DISTRIBUTOR_V2_VERSION - - # 41. Revoke SET_BOND_CURVE_ROLE from CSM on CSAccounting - validate_role_revoke_event( - dg_events[41], - role_hash=contracts.cs_accounting.SET_BOND_CURVE_ROLE().hex(), - account=contracts.csm.address, - emitted_by=contracts.cs_accounting - ) - - # 42. Revoke RESET_BOND_CURVE_ROLE from CSM on CSAccounting - validate_role_revoke_event( - dg_events[42], - role_hash=web3.keccak(text="RESET_BOND_CURVE_ROLE").hex(), - account=contracts.csm.address, - emitted_by=contracts.cs_accounting - ) - - # 43. Revoke RESET_BOND_CURVE_ROLE from CSM committee on CSAccounting - validate_role_revoke_event( - dg_events[43], - role_hash=web3.keccak(text="RESET_BOND_CURVE_ROLE").hex(), - account=CSM_COMMITTEE_MS, - emitted_by=contracts.cs_accounting - ) - - # 44. Grant CREATE_NODE_OPERATOR_ROLE to permissionless gate on CSM - validate_role_grant_event( - dg_events[44], - role_hash=contracts.csm.CREATE_NODE_OPERATOR_ROLE().hex(), - account=CS_PERMISSIONLESS_GATE_ADDRESS, - emitted_by=contracts.csm - ) - - # 45. Grant CREATE_NODE_OPERATOR_ROLE to vetted gate on CSM - validate_role_grant_event( - dg_events[45], - role_hash=contracts.csm.CREATE_NODE_OPERATOR_ROLE().hex(), - account=CS_VETTED_GATE_ADDRESS, - emitted_by=contracts.csm - ) - - # 46. Grant SET_BOND_CURVE_ROLE to vetted gate on CSAccounting - validate_role_grant_event( - dg_events[46], - role_hash=contracts.cs_accounting.SET_BOND_CURVE_ROLE().hex(), - account=CS_VETTED_GATE_ADDRESS, - emitted_by=contracts.cs_accounting - ) - - # 47. Revoke VERIFIER_ROLE from old verifier on CSM - validate_role_revoke_event( - dg_events[47], - role_hash=contracts.csm.VERIFIER_ROLE().hex(), - account=CS_VERIFIER_ADDRESS_OLD, - emitted_by=contracts.csm - ) - - # 48. Grant VERIFIER_ROLE to new verifier on CSM - validate_role_grant_event( - dg_events[48], - role_hash=contracts.csm.VERIFIER_ROLE().hex(), - account=CS_VERIFIER_V2_ADDRESS, - emitted_by=contracts.csm - ) - - # 49. Revoke PAUSE_ROLE from old GateSeal on CSM - validate_role_revoke_event( - dg_events[49], - role_hash=contracts.csm.PAUSE_ROLE().hex(), - account=CS_GATE_SEAL_ADDRESS, - emitted_by=contracts.csm - ) - - # 50. Revoke PAUSE_ROLE from old GateSeal on CSAccounting - validate_role_revoke_event( - dg_events[50], - role_hash=contracts.cs_accounting.PAUSE_ROLE().hex(), - account=CS_GATE_SEAL_ADDRESS, - emitted_by=contracts.cs_accounting - ) - - # 51. Revoke PAUSE_ROLE from old GateSeal on CSFeeOracle - validate_role_revoke_event( - dg_events[51], - role_hash=contracts.cs_fee_oracle.PAUSE_ROLE().hex(), - account=CS_GATE_SEAL_ADDRESS, - emitted_by=contracts.cs_fee_oracle - ) - - # 52. Grant PAUSE_ROLE to new GateSeal on CSM - validate_role_grant_event( - dg_events[52], - role_hash=contracts.csm.PAUSE_ROLE().hex(), - account=CS_GATE_SEAL_V2_ADDRESS, - emitted_by=contracts.csm - ) - - # 53. Grant PAUSE_ROLE to new GateSeal on CSAccounting - validate_role_grant_event( - dg_events[53], - role_hash=contracts.cs_accounting.PAUSE_ROLE().hex(), - account=CS_GATE_SEAL_V2_ADDRESS, - emitted_by=contracts.cs_accounting - ) - - # 54. Grant PAUSE_ROLE to new GateSeal on CSFeeOracle - validate_role_grant_event( - dg_events[54], - role_hash=contracts.cs_fee_oracle.PAUSE_ROLE().hex(), - account=CS_GATE_SEAL_V2_ADDRESS, - emitted_by=contracts.cs_fee_oracle - ) - - # 55. Grant MANAGE_BOND_CURVES_ROLE to agent on CSAccounting - validate_role_grant_event( - dg_events[55], - role_hash=contracts.cs_accounting.MANAGE_BOND_CURVES_ROLE().hex(), - account=contracts.agent.address, - emitted_by=contracts.cs_accounting - ) - - # 56. Add ICS bond curve - ics_curve_id = len(CS_CURVES) - validate_bond_curve_added_event(dg_events[56], curve_id=ics_curve_id, emitted_by=contracts.cs_accounting) - - # 57. Revoke MANAGE_BOND_CURVES_ROLE from agent on CSAccounting - validate_role_revoke_event( - dg_events[57], - role_hash=contracts.cs_accounting.MANAGE_BOND_CURVES_ROLE().hex(), - account=contracts.agent.address, - emitted_by=contracts.cs_accounting - ) - - # 58. Increase CSM share in Staking Router - validate_staking_module_update_event( - dg_events[58], - module_id=CS_MODULE_ID, - share_limit=CS_MODULE_NEW_TARGET_SHARE_BP, - priority_share_threshold=CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP, - module_fee_points_bp=CS_MODULE_MODULE_FEE_BP, - treasury_fee_points_bp=CS_MODULE_TREASURY_FEE_BP, - max_deposits_per_block=CS_MODULE_MAX_DEPOSITS_PER_BLOCK, - min_deposit_block_distance=CS_MODULE_MIN_DEPOSIT_BLOCK_DISTANCE, - emitted_by=contracts.staking_router - ) - - # 59-65. Gate Seals and ResealManager role updates - # 59. Revoke PAUSE_ROLE on WithdrawalQueue from the old GateSeal - validate_role_revoke_event( - dg_events[59], - role_hash=contracts.withdrawal_queue.PAUSE_ROLE().hex(), - account=OLD_GATE_SEAL_ADDRESS, - emitted_by=contracts.withdrawal_queue - ) - - # 60. Revoke PAUSE_ROLE on ValidatorsExitBusOracle from the old GateSeal - validate_role_revoke_event( - dg_events[60], - role_hash=contracts.validators_exit_bus_oracle.PAUSE_ROLE().hex(), - account=OLD_GATE_SEAL_ADDRESS, - emitted_by=contracts.validators_exit_bus_oracle - ) - - # 61. Grant PAUSE_ROLE on WithdrawalQueue to the new WithdrawalQueue GateSeal - validate_role_grant_event( - dg_events[61], - role_hash=contracts.withdrawal_queue.PAUSE_ROLE().hex(), - account=NEW_WQ_GATE_SEAL, - emitted_by=contracts.withdrawal_queue - ) - - # 62. Grant PAUSE_ROLE on ValidatorsExitBusOracle to the new Triggerable Withdrawals GateSeal - validate_role_grant_event( - dg_events[62], - role_hash=contracts.validators_exit_bus_oracle.PAUSE_ROLE().hex(), - account=NEW_TW_GATE_SEAL, - emitted_by=contracts.validators_exit_bus_oracle - ) - - # 63. Grant PAUSE_ROLE on TriggerableWithdrawalsGateway to the new Triggerable Withdrawals GateSeal - validate_role_grant_event( - dg_events[63], - role_hash=triggerable_withdrawals_gateway.PAUSE_ROLE().hex(), - account=NEW_TW_GATE_SEAL, - emitted_by=triggerable_withdrawals_gateway - ) - - # 64. Grant PAUSE_ROLE on TriggerableWithdrawalsGateway to ResealManager - validate_role_grant_event( - dg_events[64], - role_hash=triggerable_withdrawals_gateway.PAUSE_ROLE().hex(), - account=RESEAL_MANAGER, - emitted_by=triggerable_withdrawals_gateway - ) - - # 65. Grant RESUME_ROLE on TriggerableWithdrawalsGateway to ResealManager - validate_role_grant_event( - dg_events[65], - role_hash=triggerable_withdrawals_gateway.RESUME_ROLE().hex(), - account=RESEAL_MANAGER, - emitted_by=triggerable_withdrawals_gateway - ) - - # Validate Nethermind NO name change - validate_node_operator_name_set_event( - dg_events[66], - NodeOperatorNameSetItem(nodeOperatorId=NETHERMIND_NO_ID, name=NETHERMIND_NO_NAME_NEW), - emitted_by=no_registry, - is_dg_event=True, - ) - - # Validate Nethermind NO rewards address change - validate_node_operator_reward_address_set_event( - dg_events[67], - NodeOperatorRewardAddressSetItem( - nodeOperatorId=NETHERMIND_NO_ID, reward_address=NETHERMIND_NO_STAKING_REWARDS_ADDRESS_NEW - ), - emitted_by=no_registry, - is_dg_event=True, - ) - # Guardian remove event - validate_remove_guardian_event( - dg_events[68], - OLD_KILN_ADDRESS, - emitted_by=contracts.deposit_security_module.address, - ) - # Guardian add event - validate_add_guardian_event( - dg_events[69], - NEW_KILN_ADDRESS, - emitted_by=contracts.deposit_security_module.address, - ) - # Step 1: Validate Lido Locator implementation was updated - assert get_ossifiable_proxy_impl( - contracts.lido_locator) == LIDO_LOCATOR_IMPL, "Locator implementation should be updated to the new value" - - # Step 2-3: Validate VEBO implementation was updated and configured - assert get_ossifiable_proxy_impl( - contracts.validators_exit_bus_oracle) == VALIDATORS_EXIT_BUS_ORACLE_IMPL, "VEBO implementation should be updated" - assert contracts.validators_exit_bus_oracle.getMaxValidatorsPerReport() == 600, "VEBO max validators per report should be set to 600" - - # Validate exit request limit parameters from finalizeUpgrade_v2 call - exit_request_limits = contracts.validators_exit_bus_oracle.getExitRequestLimitFullInfo() - assert exit_request_limits[0] == MAX_EXIT_REQUESTS_LIMIT, "maxExitRequestsLimit should be 11200" - assert exit_request_limits[1] == EXITS_PER_FRAME, "exitsPerFrame should be 1" - assert exit_request_limits[2] == FRAME_DURATION_IN_SEC, "frameDurationInSec should be 48 in seconds" - - # Steps 4-6: Validate VEBO consensus version management - assert not contracts.validators_exit_bus_oracle.hasRole( - contracts.validators_exit_bus_oracle.MANAGE_CONSENSUS_VERSION_ROLE(), - contracts.agent), "Agent should not have MANAGE_CONSENSUS_VERSION_ROLE on VEBO" - assert contracts.validators_exit_bus_oracle.getConsensusVersion() == VEBO_CONSENSUS_VERSION, f"VEBO consensus version should be set to {VEBO_CONSENSUS_VERSION}" - - # Step 7: Validate EasyTrack VEB SUBMIT_REPORT_HASH_ROLE - assert contracts.validators_exit_bus_oracle.hasRole(submit_report_hash_role, EASYTRACK_EVMSCRIPT_EXECUTOR), "EasyTrack executor should have SUBMIT_REPORT_HASH_ROLE on VEBO" - - # Steps 8-9: Validate TWG roles - assert triggerable_withdrawals_gateway.hasRole(add_full_withdrawal_request_role, cs_ejector), "CS Ejector should have ADD_FULL_WITHDRAWAL_REQUEST_ROLE on TWG" - assert triggerable_withdrawals_gateway.hasRole(add_full_withdrawal_request_role, contracts.validators_exit_bus_oracle), "VEBO should have ADD_FULL_WITHDRAWAL_REQUEST_ROLE on TWG" - - # Step 10: Validate DualGovernance tiebreaker connection - final_tiebreaker_details = contracts.dual_governance.getTiebreakerDetails() - final_tiebreakers = final_tiebreaker_details[3] # sealableWithdrawalBlockers - assert TRIGGERABLE_WITHDRAWALS_GATEWAY in final_tiebreakers, "TWG should be in tiebreaker list after upgrade" - - # Steps 11-12: Validate Withdrawal Vault upgrade - assert get_wv_contract_proxy_impl(contracts.withdrawal_vault) == WITHDRAWAL_VAULT_IMPL, "Withdrawal Vault implementation should be updated" - assert contracts.withdrawal_vault.getContractVersion() == 2, "Withdrawal Vault version should be 2 after finalizeUpgrade_v2" - - # Steps 13-16: Validate Accounting Oracle upgrade - assert get_ossifiable_proxy_impl( - contracts.accounting_oracle) == ACCOUNTING_ORACLE_IMPL, "Accounting Oracle implementation should be updated" - assert not contracts.accounting_oracle.hasRole(contracts.accounting_oracle.MANAGE_CONSENSUS_VERSION_ROLE(), contracts.agent), "Agent should not have MANAGE_CONSENSUS_VERSION_ROLE on AO" - assert contracts.accounting_oracle.getConsensusVersion() == AO_CONSENSUS_VERSION, f"AO consensus version should be set to {AO_CONSENSUS_VERSION}" - - # Step 17: Validate AO finalizeUpgrade_v3 - assert contracts.accounting_oracle.getContractVersion() == 3, "AO contract version should be 3 after finalizeUpgrade_v3" - - # Steps 18-21: Validate Staking Router upgrade - assert get_ossifiable_proxy_impl(contracts.staking_router) == STAKING_ROUTER_IMPL, "Staking Router implementation should be updated" - assert contracts.staking_router.getContractVersion() == 3, "Staking Router version should be 3 after finalizeUpgrade_v3" - assert contracts.staking_router.hasRole(contracts.staking_router.REPORT_VALIDATOR_EXITING_STATUS_ROLE(), VALIDATOR_EXIT_VERIFIER), "ValidatorExitVerifier should have REPORT_VALIDATOR_EXITING_STATUS_ROLE on SR" - assert contracts.staking_router.hasRole(contracts.staking_router.REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE(), triggerable_withdrawals_gateway), "TWG should have REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE on SR" - - # Steps 22-27: Validate NOR and sDVT updates - assert not contracts.acl.hasPermission(contracts.agent, contracts.kernel,app_manager_role), "Agent should not have APP_MANAGER_ROLE after vote" - assert contracts.node_operators_registry.getContractVersion() == 4, "Node Operators Registry version should be updated to 4" - assert contracts.simple_dvt.getContractVersion() == 4, "Simple DVT version should be updated to 4" - assert contracts.node_operators_registry.exitDeadlineThreshold(0) == NOR_EXIT_DEADLINE_IN_SEC, "NOR exit deadline threshold should be set correctly after finalizeUpgrade_v4" - assert contracts.simple_dvt.exitDeadlineThreshold(0) == NOR_EXIT_DEADLINE_IN_SEC, "sDVT exit deadline threshold should be set correctly after finalizeUpgrade_v4" - - # Steps 28-33: Validate Oracle Daemon Config changes - assert not contracts.oracle_daemon_config.hasRole(config_manager_role, contracts.agent), "Agent should not have CONFIG_MANAGER_ROLE on Oracle Daemon Config" - for var_name in ['NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP', 'VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS', - 'VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS']: - try: - contracts.oracle_daemon_config.get(var_name) - except VirtualMachineError: - pass # Expected to fail - variable should be removed - else: - raise AssertionError(f"Variable {var_name} should have been removed") - assert convert.to_uint(contracts.oracle_daemon_config.get( - 'EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS')) == EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS, f"EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS should be set to {EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS}" - - # Step 34: Validate CSM implementation upgrade - check_proxy_implementation(contracts.csm.address, CSM_IMPL_V2_ADDRESS) - - # Step 35: Validate CSM finalizeUpgradeV2 was called - assert contracts.csm.getInitializedVersion() == CSM_V2_VERSION, f"CSM version should be {CSM_V2_VERSION} after vote" - - # Step 36: Validate CSAccounting implementation upgrade - check_proxy_implementation(contracts.cs_accounting.address, CS_ACCOUNTING_IMPL_V2_ADDRESS) - - # Step 37: Validate CSAccounting finalizeUpgradeV2 was called with bond curves - assert contracts.cs_accounting.getInitializedVersion() == CS_ACCOUNTING_V2_VERSION, f"CSAccounting version should be {CS_ACCOUNTING_V2_VERSION} after vote" - # FIXME: check bond curves - - # Step 38: Validate CSFeeOracle implementation upgrade - check_proxy_implementation(contracts.cs_fee_oracle.address, CS_FEE_ORACLE_IMPL_V2_ADDRESS) - - # Step 39: Validate CSFeeOracle finalizeUpgradeV2 was called with consensus version 3 - assert contracts.cs_fee_oracle.getContractVersion() == CS_FEE_ORACLE_V2_VERSION, f"CSFeeOracle version should be {CS_FEE_ORACLE_V2_VERSION} after vote" - assert contracts.cs_fee_oracle.getConsensusVersion() == CSM_CONSENSUS_VERSION, "CSFeeOracle consensus version should be 3 after vote" - - # Step 40: Validate CSFeeDistributor implementation upgrade - check_proxy_implementation(contracts.cs_fee_distributor.address, CS_FEE_DISTRIBUTOR_IMPL_V2_ADDRESS) - - # Step 41: Validate CSFeeDistributor finalizeUpgradeV2 was called - assert contracts.cs_fee_distributor.getInitializedVersion() == CS_FEE_DISTRIBUTOR_V2_VERSION, f"CSFeeDistributor version should be {CS_FEE_DISTRIBUTOR_V2_VERSION} after vote" - assert contracts.cs_fee_distributor.rebateRecipient() == contracts.agent.address, "Rebate recipient should be the agent after vote" - - # Step 42: Validate SET_BOND_CURVE_ROLE was revoked from CSM on CSAccounting - assert not contracts.cs_accounting.hasRole(contracts.cs_accounting.SET_BOND_CURVE_ROLE(), - contracts.csm.address), "CSM should not have SET_BOND_CURVE_ROLE on CSAccounting after vote" - - # Step 43: Validate RESET_BOND_CURVE_ROLE was revoked from CSM on CSAccounting - assert not contracts.cs_accounting.hasRole(web3.keccak(text="RESET_BOND_CURVE_ROLE"), - contracts.csm.address), "CSM should not have RESET_BOND_CURVE_ROLE on CSAccounting after vote" - - # Step 44: Validate RESET_BOND_CURVE_ROLE was revoked from CSM committee on CSAccounting - assert not contracts.cs_accounting.hasRole(web3.keccak(text="RESET_BOND_CURVE_ROLE"), - CSM_COMMITTEE_MS), "CSM committee should not have RESET_BOND_CURVE_ROLE on CSAccounting after vote" - - # Step 45: Validate CREATE_NODE_OPERATOR_ROLE was granted to permissionless gate on CSM - assert contracts.csm.hasRole(contracts.csm.CREATE_NODE_OPERATOR_ROLE(), - cs_permissionless_gate.address), "Permissionless gate should have CREATE_NODE_OPERATOR_ROLE on CSM after vote" - - # Step 46: Validate CREATE_NODE_OPERATOR_ROLE was granted to vetted gate on CSM - assert contracts.csm.hasRole(contracts.csm.CREATE_NODE_OPERATOR_ROLE(), - cs_vetted_gate.address), "Vetted gate should have CREATE_NODE_OPERATOR_ROLE on CSM after vote" - - # Step 47: Validate SET_BOND_CURVE_ROLE was granted to vetted gate on CSAccounting - assert contracts.cs_accounting.hasRole(contracts.cs_accounting.SET_BOND_CURVE_ROLE(), - cs_vetted_gate.address), "Vetted gate should have SET_BOND_CURVE_ROLE on CSAccounting after vote" - - # Step 48: Validate VERIFIER_ROLE was revoked from old verifier on CSM - assert not contracts.csm.hasRole(contracts.csm.VERIFIER_ROLE(), - CS_VERIFIER_ADDRESS_OLD), "Old verifier should not have VERIFIER_ROLE on CSM after vote" - - # Step 49: Validate VERIFIER_ROLE was granted to new verifier on CSM - assert contracts.csm.hasRole(contracts.csm.VERIFIER_ROLE(), - cs_verifier_v2.address), "New verifier should have VERIFIER_ROLE on CSM after vote" - - # Step 50: Validate PAUSE_ROLE was revoked from old GateSeal on CSM - assert not contracts.csm.hasRole(contracts.csm.PAUSE_ROLE(), - CS_GATE_SEAL_ADDRESS), "Old GateSeal should not have PAUSE_ROLE on CSM after vote" - - # Step 51: Validate PAUSE_ROLE was revoked from old GateSeal on CSAccounting - assert not contracts.cs_accounting.hasRole(contracts.cs_accounting.PAUSE_ROLE(), - CS_GATE_SEAL_ADDRESS), "Old GateSeal should not have PAUSE_ROLE on CSAccounting after vote" - - # Step 52: Validate PAUSE_ROLE was revoked from old GateSeal on CSFeeOracle - assert not contracts.cs_fee_oracle.hasRole(contracts.cs_fee_oracle.PAUSE_ROLE(), - CS_GATE_SEAL_ADDRESS), "Old GateSeal should not have PAUSE_ROLE on CSFeeOracle after vote" - - # Step 53: Validate PAUSE_ROLE was granted to new GateSeal on CSM - assert contracts.csm.hasRole(contracts.csm.PAUSE_ROLE(), - CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should have PAUSE_ROLE on CSM after vote" - - # Step 54: Validate PAUSE_ROLE was granted to new GateSeal on CSAccounting - assert contracts.cs_accounting.hasRole(contracts.cs_accounting.PAUSE_ROLE(), - CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should have PAUSE_ROLE on CSAccounting after vote" - - # Step 55: Validate PAUSE_ROLE was granted to new GateSeal on CSFeeOracle - assert contracts.cs_fee_oracle.hasRole(contracts.cs_fee_oracle.PAUSE_ROLE(), - CS_GATE_SEAL_V2_ADDRESS), "New GateSeal should have PAUSE_ROLE on CSFeeOracle after vote" - - # Step 50-52: Check add ICS Bond Curve to CSAccounting - assert not contracts.cs_accounting.hasRole(contracts.cs_accounting.MANAGE_BOND_CURVES_ROLE(), - contracts.agent), "Agent should not have MANAGE_BOND_CURVES_ROLE on CSAccounting after vote" - assert contracts.cs_accounting.getCurvesCount() == len( - CS_CURVES) + 1, "CSAccounting should have legacy bond curves and ICS Bond Curve after vote" - # FIXME: Check curves? - - # Step 53: Increase CSM share in Staking Router - csm_module_after = contracts.staking_router.getStakingModule(CS_MODULE_ID) - csm_share_after = csm_module_after['stakeShareLimit'] - assert csm_share_after == CS_MODULE_NEW_TARGET_SHARE_BP, f"CSM share should be {CS_MODULE_NEW_TARGET_SHARE_BP} after vote, but got {csm_share_after}" - - csm_priority_exit_threshold_after = csm_module_after['priorityExitShareThreshold'] - assert csm_priority_exit_threshold_after == CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP, f"CSM priority exit threshold should be {CS_MODULE_NEW_PRIORITY_EXIT_THRESHOLD_BP} after vote, but got {csm_priority_exit_threshold_after}" - - # Steps 58-62: Validate Gate Seals updates - assert not contracts.withdrawal_queue.hasRole(contracts.withdrawal_queue.PAUSE_ROLE(), - OLD_GATE_SEAL_ADDRESS), "Old GateSeal should not have PAUSE_ROLE on WithdrawalQueue after vote" - assert not contracts.validators_exit_bus_oracle.hasRole(contracts.validators_exit_bus_oracle.PAUSE_ROLE(), - OLD_GATE_SEAL_ADDRESS), "Old GateSeal should not have PAUSE_ROLE on VEBO after vote" - assert contracts.withdrawal_queue.hasRole(contracts.withdrawal_queue.PAUSE_ROLE(), - NEW_WQ_GATE_SEAL), "New WQ GateSeal should have PAUSE_ROLE on WithdrawalQueue after vote" - assert contracts.validators_exit_bus_oracle.hasRole(contracts.validators_exit_bus_oracle.PAUSE_ROLE(), - NEW_TW_GATE_SEAL), "New TW GateSeal should have PAUSE_ROLE on VEBO after vote" - assert triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.PAUSE_ROLE(), - NEW_TW_GATE_SEAL), "New TW GateSeal should have PAUSE_ROLE on TWG after vote" - - # Steps 63-64: Validate ResealManager roles - assert triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.PAUSE_ROLE(), - RESEAL_MANAGER), "ResealManager should have PAUSE_ROLE on TWG after vote" - assert triggerable_withdrawals_gateway.hasRole(triggerable_withdrawals_gateway.RESUME_ROLE(), - RESEAL_MANAGER), "ResealManager should have RESUME_ROLE on TWG after vote" - - # 67-68. Rename Node Operator ID 25 from Nethermind to Twinstake - no = contracts.node_operators_registry.getNodeOperator(NETHERMIND_NO_ID, True) - - assert no[1] == NETHERMIND_NO_NAME_NEW - assert no[2] == NETHERMIND_NEW_REWARD_ADDRESS - - assert contracts.deposit_security_module.isGuardian(OLD_KILN_ADDRESS) is False, "Old Kiln address should be removed from guardians" - assert contracts.deposit_security_module.isGuardian(NEW_KILN_ADDRESS) is True, "New Kiln address should be added to guardians" diff --git a/utils/config.py b/utils/config.py index 4abf5b202..a8877702b 100644 --- a/utils/config.py +++ b/utils/config.py @@ -210,6 +210,11 @@ def simple_dvt(self) -> interface.SimpleDVT: def csm(self) -> interface.CSModule: return interface.CSModule(CSM_ADDRESS) + @property + def cs_early_adoption(self) -> interface.CSEarlyAdoption: + """Deprecated""" + return interface.CSEarlyAdoption(CS_EARLY_ADOPTION_ADDRESS) + @property def cs_permissionless_gate(self) -> interface.CSPermissionlessGate: return interface.CSPermissionlessGate(CS_PERMISSIONLESS_GATE_ADDRESS) @@ -222,10 +227,6 @@ def cs_vetted_gate(self) -> interface.CSVettedGate: def cs_accounting(self) -> interface.CSAccounting: return interface.CSAccounting(CS_ACCOUNTING_ADDRESS) - @property - def cs_parameters_registry(self) -> interface.CSParametersRegistry: - return interface.CSParametersRegistry(CS_PARAMS_REGISTRY_ADDRESS) - @property def cs_fee_distributor(self) -> interface.CSFeeDistributor: return interface.CSFeeDistributor(CS_FEE_DISTRIBUTOR_ADDRESS) @@ -240,11 +241,15 @@ def csm_hash_consensus(self) -> interface.CSHashConsensus: @property def cs_verifier(self) -> interface.CSVerifier: - return interface.CSVerifier(CS_VERIFIER_V2_ADDRESS) + return interface.CSVerifier(CS_VERIFIER_ADDRESS) + + @property + def cs_verifier_v2(self) -> interface.CSVerifierV2: + return interface.CSVerifierV2(CS_VERIFIER_V2_ADDRESS) @property def cs_exit_penalties(self) -> interface.CSExitPenalties: - return interface.CSExitPenalties(CS_EXIT_PENALTIES_ADDRESS) + return interface.CSExitPenalties(CS_EXIT_PENALTIES) @property def cs_ejector(self) -> interface.CSEjector: diff --git a/utils/dsm.py b/utils/dsm.py index a0f6d47fc..9b28aed29 100644 --- a/utils/dsm.py +++ b/utils/dsm.py @@ -126,16 +126,3 @@ def set_single_guardian(dsm, agent, new_guardian): assert len(dsm.getGuardians()) == 1 assert dsm.isGuardian(new_guardian.address) - - -def encode_add_guardian(dsm, guardian_address, quorum_size): - return ( - dsm.address, - dsm.addGuardian.encode_input(guardian_address, quorum_size) - ) - -def encode_remove_guardian(dsm, guardian_address, quorum_size): - return ( - dsm.address, - dsm.removeGuardian.encode_input(guardian_address, quorum_size) - ) \ No newline at end of file diff --git a/utils/test/csm_helpers.py b/utils/test/csm_helpers.py index c4ed1cb18..a99bb0be9 100644 --- a/utils/test/csm_helpers.py +++ b/utils/test/csm_helpers.py @@ -5,97 +5,140 @@ from utils.test.keys_helpers import random_pubkeys_batch, random_signatures_batch from utils.config import contracts - -def get_ics_members(): - """Few ICS members from mainnet list""" +def get_ea_member(): + """ + Random address and proof for EA member + """ + address = "0x00200f4e638e81ebe172daa18c9193a33a50bbbd" + proof = [ + "0x6afd64d1f8e5feed98652d45b758fcbff17eea77665d51f0e531d692a5054756", + "0x52e265b49b47b47690ed87febf862cd32a651b9ab187cad973bc9b77749bb219", + "0x35e699543254ce0682e153798e663901c7b14a637c6823def95687ce98c3bfd2", + "0x90c4d893c062e47126e1fb88c62d7f1addb6787d7681c8b4783e77848fd94ce3", + "0xcc571b6d9faf0a49b61d00cb56d518a9ac9bc61b9ef63c7b6376a3ead99bd455", + "0x190eb8e475726914932a14a9f62b854636a9dcb6323c4d97ac6630fcd29dc33c", + "0x4ac93583eb5d1fb5546b438eac0a489b07b0d62910c4bab3e7b41f0042831d48", + "0xcdc54828056fbe5307ece8e4138766177cd9568ffd68564b37d3deaaf112bb6c", + "0x4d63ec7d0dcc7a38ac4984b6ea8fad8255dfd6419c6c66684e49676d3112e062", + "0x5c39f6b822174cc0267fa29cb2c74340b837859bbc95beca29997689334b4895", + "0x2980e52feb24b69169c73a9618107b58ae5bea120649a045aba137b07e822172", + "0xdbaa84b6f34f08ec11a23797a3497898e75dec4e99bf42d63e7cbfee0dee67d6", + "0xc4556dc19f0330ccc6c929b09a965e05c360d32a5c71c3f64b4123fda973b8dd", + "0x617a04e701d0b1c8e0e96c278ba4caf00e2d787e4287e52fcc4b5f248d89c2b3" + ] + return address, proof + + +def get_ea_members(): + """Each ea member from different source""" return (( - "0xf4c1b69a65f3fdbafcae0786c5fb02dad3e0f353", - [ - "0x5f1fbf1cda5a3dd4d863cd96f6513c24f4f5973e9de0d4524ba5c65bdbff09c6", - "0x459f8832de04e639e148bfdf73d008f9496bc5473b76c76fcb2681dd2806b34f", - "0x38b9c0886c7f5a0115688d538e14318a22856470d265c03778b63e775bfce55a", - "0x007c11b18270c5b5ec10e821b3b2763fd7b28f889b11ec0ae297ab3c55ab0dba", - "0x5cb1b7f8a3505a0d36cb64886bfd5d48e28e62d2ff0fd52aa12d3f5933fe1916", - "0x429e5ae3d28582cb7efcebca05bae5430e9915f8f5bef58c79563938479fa791", - "0x31003203efa870c41458f35927908e17c10f24b615b0e6af863d01c0d8ea3065", - "0xbe5b3c65dec940f408d96c86777263868e45fa74b9848871c1f508bde4d731e1" - ] - ), ("0x9b4064c9d9801f062f377512e61bd19484e7f365", - [ - "0x3dca0828b389d4a4f72eb381ac3edd6f96f51a04b0446db2e7a77892b61ba7c7", - "0x8f5af01242e34310a430415a1bda6ad42ea09b7ed487de5b38c2626d7acb08b1", - "0x2ae5c4b9c69f91edb90caf2594e595e01758c58ae9719311cd3d5d41a32f0b66", - "0x1f7e8e488cf08018ea5796a648b39f2218f1aad23223dcd6c3733cf775950dff", - "0xdbc36608e64ffee165ab914565b18e83b526b81771c46fc4689e7579c426a567", - "0xf676e62b1ca138f69927c196ec23e6f43e4e430e2865637fa5db83cc26670372", - "0x31003203efa870c41458f35927908e17c10f24b615b0e6af863d01c0d8ea3065", - "0xbe5b3c65dec940f408d96c86777263868e45fa74b9848871c1f508bde4d731e1" - ] - ), ("0xb8f8e5751b2c5bad790ff0d2f5574ab38246272e", - [ - "0x96441bf0ea1e2d069560e692ff9b5baec46e83a364ffe3203c5b16d91bc0321f", - "0x5e7c84656af7b03dc12353898f2cafda93166fc9c85aec6d797e7410a38390b2", - "0x90efa708c8677e4589f86f98d788a2b6096b1202358cabc31558ccc716bab269", - "0x1392ec14e24fb65c06527743cafc6c408653a312511fbeb4f7a385ee62cbb201", - "0xc656eee8bb516c8ef59fa3c73f68276c87aa2e707b1394cfe0d0d2151a60ecb8", - "0x994eb932575dc2f3b0a55262fcdfd0108cdf5573228a2fdac5c82bc689cbb90d", - "0xc878b4f250b6b2616245fe079be412dac4605b48aede5ac8f695fe219931051d", - "0xf0e2720fdd888df5369e9aa081347d97603fadbd22f5a1978b08fbaa7c13e6f7" - ] - ), ( - "0x88792bee0d8a4c46acb7a2d8bfbef7e3a678639e", - [ - "0x955c8105dfeed6dd47fccc580e67b00090043c2e0fe00dd9269adaf1864ac073", - "0xfb254edbb3d5dc888dd77e1779146b94268fb5964d0dc9f71815fad8da58612c", - "0x90efa708c8677e4589f86f98d788a2b6096b1202358cabc31558ccc716bab269", - "0x1392ec14e24fb65c06527743cafc6c408653a312511fbeb4f7a385ee62cbb201", - "0xc656eee8bb516c8ef59fa3c73f68276c87aa2e707b1394cfe0d0d2151a60ecb8", - "0x994eb932575dc2f3b0a55262fcdfd0108cdf5573228a2fdac5c82bc689cbb90d", - "0xc878b4f250b6b2616245fe079be412dac4605b48aede5ac8f695fe219931051d", - "0xf0e2720fdd888df5369e9aa081347d97603fadbd22f5a1978b08fbaa7c13e6f7" - ] - ), ( - "0x1ea60eaa2883173e2f8d6b7b025fce33ebc08738", - [ - "0xd5d55039d3530cc365d80d5bdb249c6a21024ecd2d0f3629ab256da3030e5f4a", - "0xad535120c80dea856727178e9ffc03a549ae69c71fa8fd69e7da87500d94ed5e", - "0x18c929c35a4632f9aea2684bba2fb918a1a32035c2c2aa1c50d7d48ab6f84960", - "0x1eae092568547d900432cc755ab381fedac95d4847e6de94bbdec79ca7706b47", - "0xe8c3fe7bc103e7c4da1d5a7d2bafbc6e9d1b1d42cbdb8b75bc9136701e18dd4d", - "0xd456f32b3f050d9204e43c123bb5a81c01c482ea56c9a0249ad60e36c64468af", - "0xbf3f96fd42d14dc9db9126b57923d8845d8434c7e64dcf9a1a23f17afec30aad", - "0xf0e2720fdd888df5369e9aa081347d97603fadbd22f5a1978b08fbaa7c13e6f7" - ] - )) - - -def csm_add_node_operator(csm, permissionless_gate, accounting, node_operator, keys_count=5, curve_id=0): - pubkeys_batch = random_pubkeys_batch(keys_count) - signatures_batch = random_signatures_batch(keys_count) - - value = accounting.getBondAmountByKeysCount(keys_count, curve_id) - set_balance_in_wei(node_operator, value + ETH(10)) - - permissionless_gate.addNodeOperatorETH( - keys_count, - pubkeys_batch, - signatures_batch, - (ZERO_ADDRESS, ZERO_ADDRESS, False), - ZERO_ADDRESS, - {"from": node_operator, "value": value} + "0x113e5bA177D3021E4515e847bc4779B074AA0813", [ # good performer + "0xb3f1d62e731a0ac46f103f3423265baaae773036410890c1ee4bc4ba4a5b6806", + "0xdd218546f8029d89f8bb325d50e9a272543ac9642e88d60c6d5b0f1d11db14ea", + "0x82a14915d66df3004c15749f90a53606faaa8adcf890ef9159974a470df16a1f", + "0x9f7ee78a4e733ab2715190ae5481a1456b81b3d5b65a05cd070bcf95fe7a7c92", + "0x68431bdd53ada7d0fcbc0eeae8a7e0f614cbd3da6b54b16214bfedc9e42ea753", + "0x2006bffe956465add92037dd50b5001f7bfdc9ed531fb40b9bbcdff3586ffb63", + "0xbf0015b0b477df4cd5a81eda856a20d65f1a631f033eeb4d630fbebf962a8310", + "0x03c02b7b15ef3c91ae99e86c4c3b1eee48c776e38ffff1a99dcbe4f78942679f", + "0xacbd1f9b565d87a3156b972c1a860a71b5365992f503821166f2c11f591748ec", + "0x8ac7d39a7d9d96d17f5b42f8ef026c44ebb17bd62c995f12e3124b5ca4bfc5e7", + "0x582edbfcd0fb5f0a95caca952bdb943a8cd008c4d114c586e4e03c839bc7c7cd", + "0x772f2c70f39b9a6848799e13c16fe05bdfd1eded3c2b588834bf751b79a9fce5", + "0x3f53e44db24145c061bbbf7d1df796a0ab059b7125c9c2cacf7064bc3904c9d1", + "0x617a04e701d0b1c8e0e96c278ba4caf00e2d787e4287e52fcc4b5f248d89c2b3" + ]), + ("0x6D08b74BD14b2D6Deb468BA31D578a002D0AdDE8", [ # Galxe point holder + "0x6184b17c37f752a58be2c14d26abf9220efff1349fb5c561d9b688b798237d13", + "0xe2d16f320a6de8ef9c8fdca825bad92bb3df1da7995b035d4c0ce2a68cbd3e2a", + "0x35f55c85e9331c8767bf00735389eebc9ba335f52922809cc9cf8d8487646d27", + "0x6442dd1037d0faced9476b99c7f93987326845cd36114be02abebf734759e8a9", + "0xc7f4e2bc84d3a89a6046c9feae416160dad7b28a6209b1e3dff004a3d2b4d0de", + "0xc69995256422fbd2478a7bb8201c777383493e4c1a2fc6a45620341d8108103d", + "0xd703c9506f78ffe85059902bf94a1da7d0efa195424ee10d436af20867700d7c", + "0xfa6b80e968a2f48fc65a45e6763f5a0d470f7640f75edf648d001cb46acefe3c", + "0x9950a0f220017fcd05a338574cbc289a3c00de804ca8d10867a177afd673c347", + "0x83389a6b368766d86b6d57720596f25ff3aeccd4ad21a3b683dbbd231755a2df", + "0x2980e52feb24b69169c73a9618107b58ae5bea120649a045aba137b07e822172", + "0xdbaa84b6f34f08ec11a23797a3497898e75dec4e99bf42d63e7cbfee0dee67d6", + "0xc4556dc19f0330ccc6c929b09a965e05c360d32a5c71c3f64b4123fda973b8dd", + "0x617a04e701d0b1c8e0e96c278ba4caf00e2d787e4287e52fcc4b5f248d89c2b3" + ]), + ("0xe95fb9768cef2893445bc02e7056dead0c32fe6a", [ # dappnode buyer + "0x6fdf504e61ce21367058bc13a34c21f94a4320e29b75c632aa371dd228f2595e", + "0xeeda87c6ce2ef88e9748f7987a64a7147a93be2297f62f44c75f38e5c5756111", + "0x852b5fdd3cf28c632af3270443231205b4d5fa8186b6e241e4f8d3414bfbb540", + "0xa4d359ba49c62fe93c99b49ac4453cf544252e6bf1a42fababa321bb23850163", + "0x8a9297667d1dbe4f17916ff6bc052e58790a3df7703b22baac3f4d224c06a444", + "0x696335ac8a25acf05c2b7b85bd97e0473219f8fff3bc89f49601ba6084f54e51", + "0x6aa7a7a69448a2170b3dc9f6f6227cd0926dd71962e4c15e63448a984369c7a4", + "0x5f87b1e6bfecfd3440114bd9829647532aad1328699af183aeb490d1406003cd", + "0x9d117f35be949e6db5e479949f91cb0710ea3e85be2a58deed5a0b4c05763fe3", + "0x70d5df1f59c0f5fd1667e832f91b8e389adc70f69a520a9f9ca333861bdb27e2", + "0x398e90a61a92850edce556da82fbb16b5f520bcf3fb3c1a5d7cdc6a1baf4883c", + "0xdbaa84b6f34f08ec11a23797a3497898e75dec4e99bf42d63e7cbfee0dee67d6", + "0xc4556dc19f0330ccc6c929b09a965e05c360d32a5c71c3f64b4123fda973b8dd", + "0x617a04e701d0b1c8e0e96c278ba4caf00e2d787e4287e52fcc4b5f248d89c2b3" + ]), + ("0x024813b4972428003c725ea756348dcd79b826e6", [ # obol teche credentials + "0xfc49117ff5d49126e2ed0ee2a6229678604428fc175670aaf6dfcacfba55c414", + "0xa9011da71acb5f3c61c0cc80f5c8b89f916345efb9c149ead010aac852dfbac3", + "0xa0af25f19dde818bb362aae34d967c6d141cfe4b2666a9aeef5fb03cf705ab1b", + "0xb8a34c5bdc302c3944e1f1919f304aa25168e0db81b7e2b67c6afe8a7fa8cc46", + "0x6c209589c3c08d2b8441263874648617f70ebfd255d513840aa191284b5815a9", + "0x45493cc5f6e07014c06f4fe700bc91cedbe7947bdae3d3bdf960ae67abab3adf", + "0xa6df3cbb3e9113c1c429e842c8999b3597d1b6b55c9c979c2703e995b0f762c6", + "0x9e70b4cb13a9517ad1a4fe4920b02abd9eeab2236b9a541e20beaee5557ad7fd", + "0x0a9dc8737db2646bbfc1539e073b563f203e9bfed2aabacfcd03d9d16e8f9739", + "0x2f362f8032842941fe910be787723b082ab7a21effb5cd38022b36c75a103013", + "0x6a5e8cf1bacfe83bee183d9ed803f679d8714103a8106301ad9e355f7790e901", + "0xd001326ce1fa4bfc303be10f953c87ad779c22268ea03d357da5d8e26659e50b", + "0xd597d21fed5e65b2a6de1c6fe70dfdb2df43ab5495a5c0a01c915e60c14c6edb", + "0xf99292f2fccc3f4fa8cef73512bd5f21a46214d922dfed8e8a65f763c13dfb72" + ]), + ("0xe3a2417f8eaafb93a93dc896724e20d0bc1a1feb", [ # rated + "0x2faac9fec99b1a1d464422f5cc64c153514da1d3a438362ef7f1aaa5f585cf65", + "0xf17a0bdf45def725c1ad7bf6c457d4c749705f02ff4282c6739e54dc8965340b", + "0xa0530504a2c0e61ab5de781f0ee4467097595b7a9815b9b2371e33daf920e25c", + "0x1d95475075f06c85ba13b81f01891bde5cf0af4df6f2693b15586884b4a3fac7", + "0x4a8ebe10d4e6f7bb1cadf1e54b58471a6933a62fd7fd6b4750c645f87347c8bd", + "0x96f7f6c9f3b8c3c45392e1598c4ee9ff2aa0eb655bb428c3977e939a8c2cacf5", + "0x404ba635ed5cce8cbc77c4b0eb581c8383e52a7be1507d9fbb053d86fe132fd4", + "0xa680f8f19b75770eee3435719f5731dccd057b968fabd81b40528a9b689a7b6c", + "0x78fe6adcb23cf69e7533e4a3d0558fdc6f0bf13384e85c7679b6d054b05b34ed", + "0xbab879d3c26f5d5e3816a4ce99f35a6ac8139c8df8053608bea4a76951b17e0d", + "0x15b1fc08779715ad26f61b07d0665a82f118104391b56863bd54e6bbe3ec0ff0", + "0xbe7a61521ebadab96f18fdce4dbcfed777f7799c1a02400052ee9dd838ff1ad4", + "0x5894e79a333e76f3e367a65aaad4cc2ca21650c4a532ce89b28009b0d35ca075", + "0xd597d21fed5e65b2a6de1c6fe70dfdb2df43ab5495a5c0a01c915e60c14c6edb", + "0xf99292f2fccc3f4fa8cef73512bd5f21a46214d922dfed8e8a65f763c13dfb72" + ]), + ("0x61ad82d4466437d4cc250a0ceffbcbd7e07b8f96", [ # stake cat + "0xc863e03646d118cf51af3581cacc457f166134a78b3f4253b219e7f694becc50", + "0x52b3bb9a9105a40e8270cd7e6687f3b010213bd9297748d90b7f90dad779defd", + "0x82e0aec8e35aa0c9b8732a77dc5470b13f3d9d36870acec8568ce73807674a15", + "0x096a86c63fccf92230d8d445d7df591d20f9d71ed5c77141e4bb85a47acbb2e3", + "0x4b875dfece281e9d8ab00c0b8544fa7431dc99661c44e0e6cbaad66f942e5c62", + "0x0590fd2e84b7f5a152881a0d17a6fe0732be6ffd020ada4e91693f8e94696cd8", + "0x1f99300883319c93920319ed5159329a98f2efc356165d9587c316abd6d4cbac", + "0x516c84f2139897f30531bd6e08f3372c0a06bdccd9f17ce91bd2565c79b1afca", + "0x5b698237e78d7b2ef3227a5bc652d030bba9bfa8f21aec555eee0b4f65a24b40", + "0x0a125fd7e859f5e8a67214923c80caaa3e48da3ea985ab0d346ed36a0a92989a", + "0xefb4a879db517af0fb7e4f0731a12d8360bc6a155fcfc7546ace79b55cdafa52", + "0xd2af30f01b69d3f2d1d94e5b401418ffa90b566b1450d7b3310a097701ac694a", + "0x769a53742322902c2080251b628f262577d620d70831c142a59b77910c464a63", + "0xf99292f2fccc3f4fa8cef73512bd5f21a46214d922dfed8e8a65f763c13dfb72"]) ) - return csm.getNodeOperatorsCount() - 1 - -def csm_add_ics_node_operator(csm, vetted_gate, accounting, node_operator, proof, keys_count=5, curve_id=2): +def csm_add_node_operator(csm, accounting, node_operator, proof, keys_count=5, curve_id=0): pubkeys_batch = random_pubkeys_batch(keys_count) signatures_batch = random_signatures_batch(keys_count) - value = accounting.getBondAmountByKeysCount(keys_count, curve_id) + value = accounting.getBondAmountByKeysCount['uint256,uint256'](keys_count, curve_id) set_balance_in_wei(node_operator, value + ETH(10)) - vetted_gate.addNodeOperatorETH( + csm.addNodeOperatorETH( keys_count, pubkeys_batch, signatures_batch, @@ -119,9 +162,8 @@ def csm_upload_keys(csm, accounting, no_id, keys_count=5): pubkeys_batch = random_pubkeys_batch(keys_batch) signatures_batch = random_signatures_batch(keys_batch) value = accounting.getRequiredBondForNextKeys(no_id, keys_count) - address = csm.getNodeOperator(no_id)["managerAddress"] - csm.addValidatorKeysETH(address, no_id, keys_batch, pubkeys_batch, signatures_batch, { - "from": address, + csm.addValidatorKeysETH(no_id, keys_batch, pubkeys_batch, signatures_batch, { + "from": csm.getNodeOperator(no_id)["managerAddress"], "value": value }) remaining_keys -= keys_batch @@ -137,7 +179,7 @@ def fill_csm_operators_with_keys(target_operators_count, keys_count): assert contracts.csm.getNodeOperator(no_id)["depositableValidatorsCount"] == keys_count while csm_node_operators_before + added_operators_count < target_operators_count: node_operator = f"0xbb{str(added_operators_count).zfill(38)}" - csm_add_node_operator(contracts.csm, contracts.cs_permissionless_gate, contracts.cs_accounting, node_operator, - keys_count=keys_count) + csm_add_node_operator(contracts.csm, contracts.cs_accounting, node_operator, [], keys_count=keys_count) added_operators_count += 1 return csm_node_operators_before, added_operators_count + diff --git a/utils/test/event_validators/dual_governance.py b/utils/test/event_validators/dual_governance.py index 661354e3d..11d2d5f44 100644 --- a/utils/test/event_validators/dual_governance.py +++ b/utils/test/event_validators/dual_governance.py @@ -24,15 +24,15 @@ def validate_dual_governance_submit_event( if proposal_calls: assert len(event["ProposalSubmitted"][0]["calls"]) == len(proposal_calls), "Wrong callsCount" for i in range(0, len(proposal_calls)): - assert event["ProposalSubmitted"][0]["calls"][i][0] == proposal_calls[i]["target"], f"Wrong target {i}: {event['ProposalSubmitted'][0]['calls'][i][0]} : {proposal_calls[i]['target']}" - assert event["ProposalSubmitted"][0]["calls"][i][1] == proposal_calls[i]["value"], f"Wrong value {i}" - assert event["ProposalSubmitted"][0]["calls"][i][2] == proposal_calls[i]["data"], f'Wrong data {i}' + assert event["ProposalSubmitted"][0]["calls"][i][0] == proposal_calls[i]["target"], "Wrong target" + assert event["ProposalSubmitted"][0]["calls"][i][1] == proposal_calls[i]["value"], "Wrong value" + assert event["ProposalSubmitted"][0]["calls"][i][2] == proposal_calls[i]["data"], "Wrong data" assert event["ProposalSubmitted"][1]["proposalId"] == proposal_id, "Wrong proposalId" assert event["ProposalSubmitted"][1]["proposerAccount"] == proposer, "Wrong proposer" if metadata: - assert event["ProposalSubmitted"][1]["metadata"] == metadata, f"Wrong metadata {event['ProposalSubmitted'][1]['metadata']}" + assert event["ProposalSubmitted"][1]["metadata"] == metadata, "Wrong metadata" if emitted_by is not None: assert len(event["ProposalSubmitted"]) == len(emitted_by), "Wrong emitted_by count" diff --git a/utils/test/extra_data.py b/utils/test/extra_data.py index ea7245784..c2c51227e 100644 --- a/utils/test/extra_data.py +++ b/utils/test/extra_data.py @@ -14,6 +14,7 @@ class ItemType(Enum): + EXTRA_DATA_TYPE_STUCK_VALIDATORS = 1 EXTRA_DATA_TYPE_EXITED_VALIDATORS = 2 UNSUPPORTED = 3 @@ -60,8 +61,8 @@ class ItemPayload: node_operator_ids: Sequence[int] vals_counts: Sequence[int] - class ExtraDataLengths: + NEXT_HASH = 32 ITEM_INDEX = 3 ITEM_TYPE = 2 MODULE_ID = 3 @@ -69,7 +70,6 @@ class ExtraDataLengths: NODE_OPERATOR_IDS = 8 STUCK_OR_EXITED_VALS_COUNT = 16 - class ExtraDataService: """ Service that encodes extra data into bytes in correct order. @@ -88,12 +88,14 @@ class ExtraDataService: @classmethod def collect( cls, + stuck_validators: dict[NodeOperatorGlobalIndex, int], exited_validators: dict[NodeOperatorGlobalIndex, int], max_items_count: int, max_no_in_payload_count: int, ) -> ExtraData: + stuck_payloads = cls.build_validators_payloads(stuck_validators, max_no_in_payload_count) exited_payloads = cls.build_validators_payloads(exited_validators, max_no_in_payload_count) - items_count, txs = cls.build_extra_transactions_data(exited_payloads, max_items_count) + items_count, txs = cls.build_extra_transactions_data(stuck_payloads, exited_payloads, max_items_count) extra_data_hash_list, hashed_txs = cls.add_hashes_to_transactions(txs) if items_count: @@ -140,10 +142,12 @@ def build_validators_payloads( @classmethod def build_extra_transactions_data( cls, + stuck_payloads: list[ItemPayload], exited_payloads: list[ItemPayload], max_items_count: int, ) -> tuple[int, list[bytes]]: all_payloads = [ + *[(ItemType.EXTRA_DATA_TYPE_STUCK_VALIDATORS, payload) for payload in stuck_payloads], *[(ItemType.EXTRA_DATA_TYPE_EXITED_VALIDATORS, payload) for payload in exited_payloads], ] diff --git a/utils/test/oracle_report_helpers.py b/utils/test/oracle_report_helpers.py index ee7df2ef6..7ace0ca5e 100644 --- a/utils/test/oracle_report_helpers.py +++ b/utils/test/oracle_report_helpers.py @@ -127,9 +127,6 @@ def prepare_csm_report(node_operators_rewards: dict, ref_slot): str(tree_cid), str(log_cid), sum(shares.values()), - 0, # rebate - HexBytes(ZERO_HASH), # strikesTreeRoot - "", # strikesTreeCid ) report_data = encode_data_from_abi(report, contracts.cs_fee_oracle.abi, "submitReportData") report_hash = web3.keccak(report_data) diff --git a/utils/test/staking_router_helpers.py b/utils/test/staking_router_helpers.py index ff76859ce..c91d50cab 100644 --- a/utils/test/staking_router_helpers.py +++ b/utils/test/staking_router_helpers.py @@ -2,15 +2,11 @@ from utils.config import contracts from enum import IntEnum -TOTAL_BASIS_POINTS = 10_000 - - class StakingModuleStatus(IntEnum): Active = 0 DepositsPaused = 1 Stopped = 2 - def set_staking_module_status(module_id, staking_module_status: StakingModuleStatus): contracts.staking_router.setStakingModuleStatus(module_id, staking_module_status, {"from": contracts.agent}) @@ -20,8 +16,8 @@ def increase_staking_module_share(module_id, share_multiplier): contracts.staking_router.updateStakingModule( module_id, - min(module["stakeShareLimit"] * share_multiplier, TOTAL_BASIS_POINTS), - min(module["priorityExitShareThreshold"] * share_multiplier, TOTAL_BASIS_POINTS), + module["stakeShareLimit"] * share_multiplier, + module["priorityExitShareThreshold"] * share_multiplier, module["stakingModuleFee"], module["treasuryFee"], module["maxDepositsPerBlock"], diff --git a/yarn.lock b/yarn.lock index 6e2a1deb0..8ac5bb2a8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1,4103 +1,2500 @@ -# This file is generated by running "yarn install" inside your project. -# Manual changes might be lost - proceed with caution! - -__metadata: - version: 8 - cacheKey: 10c0 - -"@adraffy/ens-normalize@npm:^1.8.8": - version: 1.11.0 - resolution: "@adraffy/ens-normalize@npm:1.11.0" - checksum: 10c0/5111d0f1a273468cb5661ed3cf46ee58de8f32f84e2ebc2365652e66c1ead82649df94c736804e2b9cfa831d30ef24e1cc3575d970dbda583416d3a98d8870a6 - languageName: node - linkType: hard - -"@esbuild/aix-ppc64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/aix-ppc64@npm:0.25.5" - conditions: os=aix & cpu=ppc64 - languageName: node - linkType: hard - -"@esbuild/android-arm64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/android-arm64@npm:0.25.5" - conditions: os=android & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/android-arm@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/android-arm@npm:0.25.5" - conditions: os=android & cpu=arm - languageName: node - linkType: hard - -"@esbuild/android-x64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/android-x64@npm:0.25.5" - conditions: os=android & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/darwin-arm64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/darwin-arm64@npm:0.25.5" - conditions: os=darwin & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/darwin-x64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/darwin-x64@npm:0.25.5" - conditions: os=darwin & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/freebsd-arm64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/freebsd-arm64@npm:0.25.5" - conditions: os=freebsd & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/freebsd-x64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/freebsd-x64@npm:0.25.5" - conditions: os=freebsd & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/linux-arm64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/linux-arm64@npm:0.25.5" - conditions: os=linux & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/linux-arm@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/linux-arm@npm:0.25.5" - conditions: os=linux & cpu=arm - languageName: node - linkType: hard - -"@esbuild/linux-ia32@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/linux-ia32@npm:0.25.5" - conditions: os=linux & cpu=ia32 - languageName: node - linkType: hard - -"@esbuild/linux-loong64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/linux-loong64@npm:0.25.5" - conditions: os=linux & cpu=loong64 - languageName: node - linkType: hard - -"@esbuild/linux-mips64el@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/linux-mips64el@npm:0.25.5" - conditions: os=linux & cpu=mips64el - languageName: node - linkType: hard - -"@esbuild/linux-ppc64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/linux-ppc64@npm:0.25.5" - conditions: os=linux & cpu=ppc64 - languageName: node - linkType: hard - -"@esbuild/linux-riscv64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/linux-riscv64@npm:0.25.5" - conditions: os=linux & cpu=riscv64 - languageName: node - linkType: hard - -"@esbuild/linux-s390x@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/linux-s390x@npm:0.25.5" - conditions: os=linux & cpu=s390x - languageName: node - linkType: hard - -"@esbuild/linux-x64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/linux-x64@npm:0.25.5" - conditions: os=linux & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/netbsd-arm64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/netbsd-arm64@npm:0.25.5" - conditions: os=netbsd & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/netbsd-x64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/netbsd-x64@npm:0.25.5" - conditions: os=netbsd & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/openbsd-arm64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/openbsd-arm64@npm:0.25.5" - conditions: os=openbsd & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/openbsd-x64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/openbsd-x64@npm:0.25.5" - conditions: os=openbsd & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/sunos-x64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/sunos-x64@npm:0.25.5" - conditions: os=sunos & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/win32-arm64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/win32-arm64@npm:0.25.5" - conditions: os=win32 & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/win32-ia32@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/win32-ia32@npm:0.25.5" - conditions: os=win32 & cpu=ia32 - languageName: node - linkType: hard - -"@esbuild/win32-x64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/win32-x64@npm:0.25.5" - conditions: os=win32 & cpu=x64 - languageName: node - linkType: hard - -"@ethereumjs/rlp@npm:^4.0.1": - version: 4.0.1 - resolution: "@ethereumjs/rlp@npm:4.0.1" - bin: - rlp: bin/rlp - checksum: 10c0/78379f288e9d88c584c2159c725c4a667a9742981d638bad760ed908263e0e36bdbd822c0a902003e0701195fd1cbde7adad621cd97fdfbf552c45e835ce022c - languageName: node - linkType: hard - -"@ethereumjs/rlp@npm:^5.0.2": - version: 5.0.2 - resolution: "@ethereumjs/rlp@npm:5.0.2" - bin: - rlp: bin/rlp.cjs - checksum: 10c0/56162eaee96dd429f0528a9e51b453398546d57f26057b3e188f2aa09efe8bd430502971c54238ca9cc42af41b0a3f137cf67b9e020d52bc83caca043d64911b - languageName: node - linkType: hard - -"@ethereumjs/util@npm:^9.1.0": - version: 9.1.0 - resolution: "@ethereumjs/util@npm:9.1.0" - dependencies: - "@ethereumjs/rlp": "npm:^5.0.2" - ethereum-cryptography: "npm:^2.2.1" - checksum: 10c0/7b55c79d90e55da873037b8283c37b61164f1712b194e2783bdb0a3401ff0999dc9d1404c7051589f71fb79e8aeb6952ec43ede21dd0028d7d9b1c07abcfff27 - languageName: node - linkType: hard - -"@ethersproject/abi@npm:^5.1.2": - version: 5.8.0 - resolution: "@ethersproject/abi@npm:5.8.0" - dependencies: - "@ethersproject/address": "npm:^5.8.0" - "@ethersproject/bignumber": "npm:^5.8.0" - "@ethersproject/bytes": "npm:^5.8.0" - "@ethersproject/constants": "npm:^5.8.0" - "@ethersproject/hash": "npm:^5.8.0" - "@ethersproject/keccak256": "npm:^5.8.0" - "@ethersproject/logger": "npm:^5.8.0" - "@ethersproject/properties": "npm:^5.8.0" - "@ethersproject/strings": "npm:^5.8.0" - checksum: 10c0/6b759247a2f43ecc1548647d0447d08de1e946dfc7e71bfb014fa2f749c1b76b742a1d37394660ebab02ff8565674b3593fdfa011e16a5adcfc87ca4d85af39c - languageName: node - linkType: hard - -"@ethersproject/abstract-provider@npm:^5.8.0": - version: 5.8.0 - resolution: "@ethersproject/abstract-provider@npm:5.8.0" - dependencies: - "@ethersproject/bignumber": "npm:^5.8.0" - "@ethersproject/bytes": "npm:^5.8.0" - "@ethersproject/logger": "npm:^5.8.0" - "@ethersproject/networks": "npm:^5.8.0" - "@ethersproject/properties": "npm:^5.8.0" - "@ethersproject/transactions": "npm:^5.8.0" - "@ethersproject/web": "npm:^5.8.0" - checksum: 10c0/9c183da1d037b272ff2b03002c3d801088d0534f88985f4983efc5f3ebd59b05f04bc05db97792fe29ddf87eeba3c73416e5699615f183126f85f877ea6c8637 - languageName: node - linkType: hard - -"@ethersproject/abstract-signer@npm:^5.8.0": - version: 5.8.0 - resolution: "@ethersproject/abstract-signer@npm:5.8.0" - dependencies: - "@ethersproject/abstract-provider": "npm:^5.8.0" - "@ethersproject/bignumber": "npm:^5.8.0" - "@ethersproject/bytes": "npm:^5.8.0" - "@ethersproject/logger": "npm:^5.8.0" - "@ethersproject/properties": "npm:^5.8.0" - checksum: 10c0/143f32d7cb0bc7064e45674d4a9dffdb90d6171425d20e8de9dc95765be960534bae7246ead400e6f52346624b66569d9585d790eedd34b0b6b7f481ec331cc2 - languageName: node - linkType: hard - -"@ethersproject/address@npm:^5.8.0": - version: 5.8.0 - resolution: "@ethersproject/address@npm:5.8.0" - dependencies: - "@ethersproject/bignumber": "npm:^5.8.0" - "@ethersproject/bytes": "npm:^5.8.0" - "@ethersproject/keccak256": "npm:^5.8.0" - "@ethersproject/logger": "npm:^5.8.0" - "@ethersproject/rlp": "npm:^5.8.0" - checksum: 10c0/8bac8a4b567c75c1abc00eeca08c200de1a2d5cf76d595dc04fa4d7bff9ffa5530b2cdfc5e8656cfa8f6fa046de54be47620a092fb429830a8ddde410b9d50bc - languageName: node - linkType: hard - -"@ethersproject/base64@npm:^5.8.0": - version: 5.8.0 - resolution: "@ethersproject/base64@npm:5.8.0" - dependencies: - "@ethersproject/bytes": "npm:^5.8.0" - checksum: 10c0/60ae6d1e2367d70f4090b717852efe62075442ae59aeac9bb1054fe8306a2de8ef0b0561e7fb4666ecb1f8efa1655d683dd240675c3a25d6fa867245525a63ca - languageName: node - linkType: hard - -"@ethersproject/bignumber@npm:^5.8.0": - version: 5.8.0 - resolution: "@ethersproject/bignumber@npm:5.8.0" - dependencies: - "@ethersproject/bytes": "npm:^5.8.0" - "@ethersproject/logger": "npm:^5.8.0" - bn.js: "npm:^5.2.1" - checksum: 10c0/8e87fa96999d59d0ab4c814c79e3a8354d2ba914dfa78cf9ee688f53110473cec0df0db2aaf9d447e84ab2dbbfca39979abac4f2dac69fef4d080f4cc3e29613 - languageName: node - linkType: hard - -"@ethersproject/bytes@npm:^5.8.0": - version: 5.8.0 - resolution: "@ethersproject/bytes@npm:5.8.0" - dependencies: - "@ethersproject/logger": "npm:^5.8.0" - checksum: 10c0/47ef798f3ab43b95dc74097b2c92365c919308ecabc3e34d9f8bf7f886fa4b99837ba5cf4dc8921baaaafe6899982f96b0e723b3fc49132c061f83d1ca3fed8b - languageName: node - linkType: hard - -"@ethersproject/constants@npm:^5.8.0": - version: 5.8.0 - resolution: "@ethersproject/constants@npm:5.8.0" - dependencies: - "@ethersproject/bignumber": "npm:^5.8.0" - checksum: 10c0/374b3c2c6da24f8fef62e2316eae96faa462826c0774ef588cd7313ae7ddac8eb1bb85a28dad80123148be2ba0821c217c14ecfc18e2e683c72adc734b6248c9 - languageName: node - linkType: hard - -"@ethersproject/hash@npm:^5.8.0": - version: 5.8.0 - resolution: "@ethersproject/hash@npm:5.8.0" - dependencies: - "@ethersproject/abstract-signer": "npm:^5.8.0" - "@ethersproject/address": "npm:^5.8.0" - "@ethersproject/base64": "npm:^5.8.0" - "@ethersproject/bignumber": "npm:^5.8.0" - "@ethersproject/bytes": "npm:^5.8.0" - "@ethersproject/keccak256": "npm:^5.8.0" - "@ethersproject/logger": "npm:^5.8.0" - "@ethersproject/properties": "npm:^5.8.0" - "@ethersproject/strings": "npm:^5.8.0" - checksum: 10c0/72a287d4d70fae716827587339ffb449b8c23ef8728db6f8a661f359f7cb1e5ffba5b693c55e09d4e7162bf56af4a0e98a334784e0706d98102d1a5786241537 - languageName: node - linkType: hard - -"@ethersproject/keccak256@npm:^5.8.0": - version: 5.8.0 - resolution: "@ethersproject/keccak256@npm:5.8.0" - dependencies: - "@ethersproject/bytes": "npm:^5.8.0" - js-sha3: "npm:0.8.0" - checksum: 10c0/cd93ac6a5baf842313cde7de5e6e2c41feeea800db9e82955f96e7f3462d2ac6a6a29282b1c9e93b84ce7c91eec02347043c249fd037d6051214275bfc7fe99f - languageName: node - linkType: hard - -"@ethersproject/logger@npm:^5.8.0": - version: 5.8.0 - resolution: "@ethersproject/logger@npm:5.8.0" - checksum: 10c0/7f39f33e8f254ee681d4778bb71ce3c5de248e1547666f85c43bfbc1c18996c49a31f969f056b66d23012f2420f2d39173107284bc41eb98d0482ace1d06403e - languageName: node - linkType: hard - -"@ethersproject/networks@npm:^5.8.0": - version: 5.8.0 - resolution: "@ethersproject/networks@npm:5.8.0" - dependencies: - "@ethersproject/logger": "npm:^5.8.0" - checksum: 10c0/3f23bcc4c3843cc9b7e4b9f34df0a1f230b24dc87d51cdad84552302159a84d7899cd80c8a3d2cf8007b09ac373a5b10407007adde23d4c4881a4d6ee6bc4b9c - languageName: node - linkType: hard - -"@ethersproject/properties@npm:^5.8.0": - version: 5.8.0 - resolution: "@ethersproject/properties@npm:5.8.0" - dependencies: - "@ethersproject/logger": "npm:^5.8.0" - checksum: 10c0/20256d7eed65478a38dabdea4c3980c6591b7b75f8c45089722b032ceb0e1cd3dd6dd60c436cfe259337e6909c28d99528c172d06fc74bbd61be8eb9e68be2e6 - languageName: node - linkType: hard - -"@ethersproject/rlp@npm:^5.8.0": - version: 5.8.0 - resolution: "@ethersproject/rlp@npm:5.8.0" - dependencies: - "@ethersproject/bytes": "npm:^5.8.0" - "@ethersproject/logger": "npm:^5.8.0" - checksum: 10c0/db742ec9c1566d6441242cc2c2ae34c1e5304d48e1fe62bc4e53b1791f219df211e330d2de331e0e4f74482664e205c2e4220e76138bd71f1ec07884e7f5221b - languageName: node - linkType: hard - -"@ethersproject/signing-key@npm:^5.8.0": - version: 5.8.0 - resolution: "@ethersproject/signing-key@npm:5.8.0" - dependencies: - "@ethersproject/bytes": "npm:^5.8.0" - "@ethersproject/logger": "npm:^5.8.0" - "@ethersproject/properties": "npm:^5.8.0" - bn.js: "npm:^5.2.1" - elliptic: "npm:6.6.1" - hash.js: "npm:1.1.7" - checksum: 10c0/a7ff6cd344b0609737a496b6d5b902cf5528ed5a7ce2c0db5e7b69dc491d1810d1d0cd51dddf9dc74dd562ab4961d76e982f1750359b834c53c202e85e4c8502 - languageName: node - linkType: hard - -"@ethersproject/strings@npm:^5.8.0": - version: 5.8.0 - resolution: "@ethersproject/strings@npm:5.8.0" - dependencies: - "@ethersproject/bytes": "npm:^5.8.0" - "@ethersproject/constants": "npm:^5.8.0" - "@ethersproject/logger": "npm:^5.8.0" - checksum: 10c0/6db39503c4be130110612b6d593a381c62657e41eebf4f553247ebe394fda32cdf74ff645daee7b7860d209fd02c7e909a95b1f39a2f001c662669b9dfe81d00 - languageName: node - linkType: hard - -"@ethersproject/transactions@npm:^5.8.0": - version: 5.8.0 - resolution: "@ethersproject/transactions@npm:5.8.0" - dependencies: - "@ethersproject/address": "npm:^5.8.0" - "@ethersproject/bignumber": "npm:^5.8.0" - "@ethersproject/bytes": "npm:^5.8.0" - "@ethersproject/constants": "npm:^5.8.0" - "@ethersproject/keccak256": "npm:^5.8.0" - "@ethersproject/logger": "npm:^5.8.0" - "@ethersproject/properties": "npm:^5.8.0" - "@ethersproject/rlp": "npm:^5.8.0" - "@ethersproject/signing-key": "npm:^5.8.0" - checksum: 10c0/dd32f090df5945313aafa8430ce76834479750d6655cb786c3b65ec841c94596b14d3c8c59ee93eed7b4f32f27d321a9b8b43bc6bb51f7e1c6694f82639ffe68 - languageName: node - linkType: hard - -"@ethersproject/web@npm:^5.8.0": - version: 5.8.0 - resolution: "@ethersproject/web@npm:5.8.0" - dependencies: - "@ethersproject/base64": "npm:^5.8.0" - "@ethersproject/bytes": "npm:^5.8.0" - "@ethersproject/logger": "npm:^5.8.0" - "@ethersproject/properties": "npm:^5.8.0" - "@ethersproject/strings": "npm:^5.8.0" - checksum: 10c0/e3cd547225638db6e94fcd890001c778d77adb0d4f11a7f8c447e961041678f3fbfaffe77a962c7aa3f6597504232442e7015f2335b1788508a108708a30308a - languageName: node - linkType: hard - -"@fastify/busboy@npm:^2.0.0": - version: 2.1.1 - resolution: "@fastify/busboy@npm:2.1.1" - checksum: 10c0/6f8027a8cba7f8f7b736718b013f5a38c0476eea67034c94a0d3c375e2b114366ad4419e6a6fa7ffc2ef9c6d3e0435d76dd584a7a1cbac23962fda7650b579e3 - languageName: node - linkType: hard - -"@isaacs/cliui@npm:^8.0.2": - version: 8.0.2 - resolution: "@isaacs/cliui@npm:8.0.2" - dependencies: - string-width: "npm:^5.1.2" - string-width-cjs: "npm:string-width@^4.2.0" - strip-ansi: "npm:^7.0.1" - strip-ansi-cjs: "npm:strip-ansi@^6.0.1" - wrap-ansi: "npm:^8.1.0" - wrap-ansi-cjs: "npm:wrap-ansi@^7.0.0" - checksum: 10c0/b1bf42535d49f11dc137f18d5e4e63a28c5569de438a221c369483731e9dac9fb797af554e8bf02b6192d1e5eba6e6402cf93900c3d0ac86391d00d04876789e - languageName: node - linkType: hard - -"@isaacs/fs-minipass@npm:^4.0.0": - version: 4.0.1 - resolution: "@isaacs/fs-minipass@npm:4.0.1" - dependencies: - minipass: "npm:^7.0.4" - checksum: 10c0/c25b6dc1598790d5b55c0947a9b7d111cfa92594db5296c3b907e2f533c033666f692a3939eadac17b1c7c40d362d0b0635dc874cbfe3e70db7c2b07cc97a5d2 - languageName: node - linkType: hard - -"@lido-js/ganache@npm:=7.9.2-lido": - version: 7.9.2-lido - resolution: "@lido-js/ganache@npm:7.9.2-lido" - dependencies: - "@trufflesuite/bigint-buffer": "npm:1.1.10" - "@trufflesuite/uws-js-unofficial": "npm:20.30.0-unofficial.0" - "@types/bn.js": "npm:^5.1.0" - "@types/lru-cache": "npm:5.1.1" - "@types/seedrandom": "npm:3.0.1" - abstract-level: "npm:1.0.3" - abstract-leveldown: "npm:7.2.0" - async-eventemitter: "npm:0.2.4" - bufferutil: "npm:4.0.5" - emittery: "npm:0.10.0" - keccak: "npm:3.0.2" - leveldown: "npm:6.1.0" - secp256k1: "npm:4.0.3" - utf-8-validate: "npm:5.0.7" - dependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - bin: - ganache: dist/node/cli.js - ganache-cli: dist/node/cli.js - checksum: 10c0/503800d45b4ed962cae9c6e77de26e2531c9986cb703cc89f99fbf7b05a4d00961ef2e8961c7f71cb7303c30e477fc51d9e99cbde32f3eb2f322f3c49505366a - languageName: node - linkType: hard - -"@noble/curves@npm:1.4.2, @noble/curves@npm:~1.4.0": - version: 1.4.2 - resolution: "@noble/curves@npm:1.4.2" - dependencies: - "@noble/hashes": "npm:1.4.0" - checksum: 10c0/65620c895b15d46e8087939db6657b46a1a15cd4e0e4de5cd84b97a0dfe0af85f33a431bb21ac88267e3dc508618245d4cb564213959d66a84d690fe18a63419 - languageName: node - linkType: hard - -"@noble/curves@npm:~1.8.1": - version: 1.8.2 - resolution: "@noble/curves@npm:1.8.2" - dependencies: - "@noble/hashes": "npm:1.7.2" - checksum: 10c0/e7ef119b114681d6b7530b29a21f9bbea6fa6973bc369167da2158d05054cc6e6dbfb636ba89fad7707abacc150de30188b33192f94513911b24bdb87af50bbd - languageName: node - linkType: hard - -"@noble/hashes@npm:1.2.0, @noble/hashes@npm:~1.2.0": - version: 1.2.0 - resolution: "@noble/hashes@npm:1.2.0" - checksum: 10c0/8bd3edb7bb6a9068f806a9a5a208cc2144e42940a21c049d8e9a0c23db08bef5cf1cfd844a7e35489b5ab52c6fa6299352075319e7f531e0996d459c38cfe26a - languageName: node - linkType: hard - -"@noble/hashes@npm:1.4.0, @noble/hashes@npm:~1.4.0": - version: 1.4.0 - resolution: "@noble/hashes@npm:1.4.0" - checksum: 10c0/8c3f005ee72e7b8f9cff756dfae1241485187254e3f743873e22073d63906863df5d4f13d441b7530ea614b7a093f0d889309f28b59850f33b66cb26a779a4a5 - languageName: node - linkType: hard - -"@noble/hashes@npm:1.7.2, @noble/hashes@npm:~1.7.1": - version: 1.7.2 - resolution: "@noble/hashes@npm:1.7.2" - checksum: 10c0/b1411eab3c0b6691d847e9394fe7f1fcd45eeb037547c8f97e7d03c5068a499b4aef188e8e717eee67389dca4fee17d69d7e0f58af6c092567b0b76359b114b2 - languageName: node - linkType: hard - -"@noble/secp256k1@npm:1.7.1, @noble/secp256k1@npm:~1.7.0": - version: 1.7.1 - resolution: "@noble/secp256k1@npm:1.7.1" - checksum: 10c0/48091801d39daba75520012027d0ff0b1719338d96033890cfe0d287ad75af00d82769c0194a06e7e4fbd816ae3f204f4a59c9e26f0ad16b429f7e9b5403ccd5 - languageName: node - linkType: hard - -"@nomicfoundation/edr-darwin-arm64@npm:0.11.0": - version: 0.11.0 - resolution: "@nomicfoundation/edr-darwin-arm64@npm:0.11.0" - checksum: 10c0/bf4abf4a4c84b4cbe6077dc05421e72aeadde719b4a33825c994126c8b3c5bb2a6296941ab18ad9f54945becf9dee692a8cbb77e7448be246dfcdde19ac2b967 - languageName: node - linkType: hard - -"@nomicfoundation/edr-darwin-x64@npm:0.11.0": - version: 0.11.0 - resolution: "@nomicfoundation/edr-darwin-x64@npm:0.11.0" - checksum: 10c0/aff56bb9c247f7fc435e208dc7bc17bea8f7f27e8d63797dadd2565db6641c684f16d77685375f7d5194238da648415085b9a71243e5e4e7743c37edff2e64c5 - languageName: node - linkType: hard - -"@nomicfoundation/edr-linux-arm64-gnu@npm:0.11.0": - version: 0.11.0 - resolution: "@nomicfoundation/edr-linux-arm64-gnu@npm:0.11.0" - checksum: 10c0/454fe2c7a1be6add79527b3372671483e5012949bc022a0ddf63773d79b5c8920375b25385594d05f26d553b10ca273df4c4084c30515788a2ab6aa25440aa0c - languageName: node - linkType: hard - -"@nomicfoundation/edr-linux-arm64-musl@npm:0.11.0": - version: 0.11.0 - resolution: "@nomicfoundation/edr-linux-arm64-musl@npm:0.11.0" - checksum: 10c0/8737fb029d7572ae09ca2c02ec5bd4f15d541d361e8adbacb8dd26448b1a6e1e0f2af3883aad983309217d9a0104488c15e6427563bad3d754f25427571b6077 - languageName: node - linkType: hard - -"@nomicfoundation/edr-linux-x64-gnu@npm:0.11.0": - version: 0.11.0 - resolution: "@nomicfoundation/edr-linux-x64-gnu@npm:0.11.0" - checksum: 10c0/21902281cd923bff6e0057cc79e81fde68376caf4db6b0798ccefd6eb2583899ee23f0ccd24c90a8180c6d8426fbf7876bf5d3e61546bd3dfc586a5b69f32f9c - languageName: node - linkType: hard - -"@nomicfoundation/edr-linux-x64-musl@npm:0.11.0": - version: 0.11.0 - resolution: "@nomicfoundation/edr-linux-x64-musl@npm:0.11.0" - checksum: 10c0/0cc2cb5756228946734811e9aa3abc291e96ece5357895ff2a004888aef8bc6c85d53266cf2a3b2ae0ff08e81516676a7117fe9bf4478156b0b957cea10a68f1 - languageName: node - linkType: hard - -"@nomicfoundation/edr-win32-x64-msvc@npm:0.11.0": - version: 0.11.0 - resolution: "@nomicfoundation/edr-win32-x64-msvc@npm:0.11.0" - checksum: 10c0/716cdb10470a4cfab1f3d9cfed85adea457914c18121e6b30e4c8ae3a3c1d5cd291650feffceb09e4794cf7b6f7f31897710cd836235ea9c9e4159a14405335d - languageName: node - linkType: hard - -"@nomicfoundation/edr@npm:^0.11.0": - version: 0.11.0 - resolution: "@nomicfoundation/edr@npm:0.11.0" - dependencies: - "@nomicfoundation/edr-darwin-arm64": "npm:0.11.0" - "@nomicfoundation/edr-darwin-x64": "npm:0.11.0" - "@nomicfoundation/edr-linux-arm64-gnu": "npm:0.11.0" - "@nomicfoundation/edr-linux-arm64-musl": "npm:0.11.0" - "@nomicfoundation/edr-linux-x64-gnu": "npm:0.11.0" - "@nomicfoundation/edr-linux-x64-musl": "npm:0.11.0" - "@nomicfoundation/edr-win32-x64-msvc": "npm:0.11.0" - checksum: 10c0/446203e8ebc98742d913ad9d1f89774fac4f1fb69f04c170787d7ff9fcfe06eeb1a9e1e0649980fca6d3e5c36099e784fc5a6b4380da8e59dd016cb6575adb63 - languageName: node - linkType: hard - -"@nomicfoundation/solidity-analyzer-darwin-arm64@npm:0.1.2": - version: 0.1.2 - resolution: "@nomicfoundation/solidity-analyzer-darwin-arm64@npm:0.1.2" - checksum: 10c0/ef3b13bb2133fea6621db98f991036a3a84d2b240160edec50beafa6ce821fe2f0f5cd4aa61adb9685aff60cd0425982ffd15e0b868b7c768e90e26b8135b825 - languageName: node - linkType: hard - -"@nomicfoundation/solidity-analyzer-darwin-x64@npm:0.1.2": - version: 0.1.2 - resolution: "@nomicfoundation/solidity-analyzer-darwin-x64@npm:0.1.2" - checksum: 10c0/3cb6a00cd200b94efd6f59ed626c705c6f773b92ccf8b90471285cd0e81b35f01edb30c1aa5a4633393c2adb8f20fd34e90c51990dc4e30658e8a67c026d16c9 - languageName: node - linkType: hard - -"@nomicfoundation/solidity-analyzer-linux-arm64-gnu@npm:0.1.2": - version: 0.1.2 - resolution: "@nomicfoundation/solidity-analyzer-linux-arm64-gnu@npm:0.1.2" - checksum: 10c0/cb9725e7bdc3ba9c1feaef96dbf831c1a59c700ca633a9929fd97debdcb5ce06b5d7b4e6dbc076279978707214d01e2cd126d8e3f4cabc5c16525c031a47b95c - languageName: node - linkType: hard - -"@nomicfoundation/solidity-analyzer-linux-arm64-musl@npm:0.1.2": - version: 0.1.2 - resolution: "@nomicfoundation/solidity-analyzer-linux-arm64-musl@npm:0.1.2" - checksum: 10c0/82a90b1d09ad266ddc510ece2e397f51fdaf29abf7263d2a3a85accddcba2ac24cceb670a3120800611cdcc552eed04919d071e259fdda7564818359ed541f5d - languageName: node - linkType: hard - -"@nomicfoundation/solidity-analyzer-linux-x64-gnu@npm:0.1.2": - version: 0.1.2 - resolution: "@nomicfoundation/solidity-analyzer-linux-x64-gnu@npm:0.1.2" - checksum: 10c0/d1f20d4d55683bd041ead957e5461b2e43a39e959f905e8866de1d65f8d96118e9b861e994604d9002cb7f056be0844e36c241a6bb531c336b399609977c0998 - languageName: node - linkType: hard - -"@nomicfoundation/solidity-analyzer-linux-x64-musl@npm:0.1.2": - version: 0.1.2 - resolution: "@nomicfoundation/solidity-analyzer-linux-x64-musl@npm:0.1.2" - checksum: 10c0/6c17f9af3aaf184c0a217cf723076051c502d85e731dbc97f34b838f9ae1b597577abac54a2af49b3fd986b09131c52fa21fd5393b22d05e1ec7fee96a8249c2 - languageName: node - linkType: hard - -"@nomicfoundation/solidity-analyzer-win32-x64-msvc@npm:0.1.2": - version: 0.1.2 - resolution: "@nomicfoundation/solidity-analyzer-win32-x64-msvc@npm:0.1.2" - checksum: 10c0/da198464f5ee0d19b6decdfaa65ee0df3097b8960b8483bb7080931968815a5d60f27191229d47a198955784d763d5996f0b92bfde3551612ad972c160b0b000 - languageName: node - linkType: hard - -"@nomicfoundation/solidity-analyzer@npm:^0.1.0": - version: 0.1.2 - resolution: "@nomicfoundation/solidity-analyzer@npm:0.1.2" - dependencies: - "@nomicfoundation/solidity-analyzer-darwin-arm64": "npm:0.1.2" - "@nomicfoundation/solidity-analyzer-darwin-x64": "npm:0.1.2" - "@nomicfoundation/solidity-analyzer-linux-arm64-gnu": "npm:0.1.2" - "@nomicfoundation/solidity-analyzer-linux-arm64-musl": "npm:0.1.2" - "@nomicfoundation/solidity-analyzer-linux-x64-gnu": "npm:0.1.2" - "@nomicfoundation/solidity-analyzer-linux-x64-musl": "npm:0.1.2" - "@nomicfoundation/solidity-analyzer-win32-x64-msvc": "npm:0.1.2" - dependenciesMeta: - "@nomicfoundation/solidity-analyzer-darwin-arm64": - optional: true - "@nomicfoundation/solidity-analyzer-darwin-x64": - optional: true - "@nomicfoundation/solidity-analyzer-linux-arm64-gnu": - optional: true - "@nomicfoundation/solidity-analyzer-linux-arm64-musl": - optional: true - "@nomicfoundation/solidity-analyzer-linux-x64-gnu": - optional: true - "@nomicfoundation/solidity-analyzer-linux-x64-musl": - optional: true - "@nomicfoundation/solidity-analyzer-win32-x64-msvc": - optional: true - checksum: 10c0/e4f503e9287e18967535af669ca7e26e2682203c45a34ea85da53122da1dee1278f2b8c76c20c67fadd7c1b1a98eeecffd2cbc136860665e3afa133817c0de54 - languageName: node - linkType: hard - -"@npmcli/agent@npm:^3.0.0": - version: 3.0.0 - resolution: "@npmcli/agent@npm:3.0.0" - dependencies: - agent-base: "npm:^7.1.0" - http-proxy-agent: "npm:^7.0.0" - https-proxy-agent: "npm:^7.0.1" - lru-cache: "npm:^10.0.1" - socks-proxy-agent: "npm:^8.0.3" - checksum: 10c0/efe37b982f30740ee77696a80c196912c274ecd2cb243bc6ae7053a50c733ce0f6c09fda085145f33ecf453be19654acca74b69e81eaad4c90f00ccffe2f9271 - languageName: node - linkType: hard - -"@npmcli/fs@npm:^4.0.0": - version: 4.0.0 - resolution: "@npmcli/fs@npm:4.0.0" - dependencies: - semver: "npm:^7.3.5" - checksum: 10c0/c90935d5ce670c87b6b14fab04a965a3b8137e585f8b2a6257263bd7f97756dd736cb165bb470e5156a9e718ecd99413dccc54b1138c1a46d6ec7cf325982fe5 - languageName: node - linkType: hard - -"@pkgjs/parseargs@npm:^0.11.0": - version: 0.11.0 - resolution: "@pkgjs/parseargs@npm:0.11.0" - checksum: 10c0/5bd7576bb1b38a47a7fc7b51ac9f38748e772beebc56200450c4a817d712232b8f1d3ef70532c80840243c657d491cf6a6be1e3a214cff907645819fdc34aadd - languageName: node - linkType: hard - -"@scure/base@npm:~1.1.0, @scure/base@npm:~1.1.6": - version: 1.1.9 - resolution: "@scure/base@npm:1.1.9" - checksum: 10c0/77a06b9a2db8144d22d9bf198338893d77367c51b58c72b99df990c0a11f7cadd066d4102abb15e3ca6798d1529e3765f55c4355742465e49aed7a0c01fe76e8 - languageName: node - linkType: hard - -"@scure/base@npm:~1.2.5": - version: 1.2.6 - resolution: "@scure/base@npm:1.2.6" - checksum: 10c0/49bd5293371c4e062cb6ba689c8fe3ea3981b7bb9c000400dc4eafa29f56814cdcdd27c04311c2fec34de26bc373c593a1d6ca6d754398a488d587943b7c128a - languageName: node - linkType: hard - -"@scure/bip32@npm:1.1.5": - version: 1.1.5 - resolution: "@scure/bip32@npm:1.1.5" - dependencies: - "@noble/hashes": "npm:~1.2.0" - "@noble/secp256k1": "npm:~1.7.0" - "@scure/base": "npm:~1.1.0" - checksum: 10c0/d0521f6de28278e06f2d517307b4de6c9bcb3dbdf9a5844bb57a6e4916a180e4136129ccab295c27bd1196ef77757608255afcd7cf927e03baec4479b3df74fc - languageName: node - linkType: hard - -"@scure/bip32@npm:1.4.0": - version: 1.4.0 - resolution: "@scure/bip32@npm:1.4.0" - dependencies: - "@noble/curves": "npm:~1.4.0" - "@noble/hashes": "npm:~1.4.0" - "@scure/base": "npm:~1.1.6" - checksum: 10c0/6849690d49a3bf1d0ffde9452eb16ab83478c1bc0da7b914f873e2930cd5acf972ee81320e3df1963eb247cf57e76d2d975b5f97093d37c0e3f7326581bf41bd - languageName: node - linkType: hard - -"@scure/bip39@npm:1.1.1": - version: 1.1.1 - resolution: "@scure/bip39@npm:1.1.1" - dependencies: - "@noble/hashes": "npm:~1.2.0" - "@scure/base": "npm:~1.1.0" - checksum: 10c0/821dc9d5be8362a32277390526db064860c2216a079ba51d63def9289c2b290599e93681ebbeebf0e93540799eec35784c1dfcf5167d0b280ef148e5023ce01b - languageName: node - linkType: hard - -"@scure/bip39@npm:1.3.0": - version: 1.3.0 - resolution: "@scure/bip39@npm:1.3.0" - dependencies: - "@noble/hashes": "npm:~1.4.0" - "@scure/base": "npm:~1.1.6" - checksum: 10c0/1ae1545a7384a4d9e33e12d9e9f8824f29b0279eb175b0f0657c0a782c217920054f9a1d28eb316a417dfc6c4e0b700d6fbdc6da160670107426d52fcbe017a8 - languageName: node - linkType: hard - -"@sentry/core@npm:5.30.0": - version: 5.30.0 - resolution: "@sentry/core@npm:5.30.0" - dependencies: - "@sentry/hub": "npm:5.30.0" - "@sentry/minimal": "npm:5.30.0" - "@sentry/types": "npm:5.30.0" - "@sentry/utils": "npm:5.30.0" - tslib: "npm:^1.9.3" - checksum: 10c0/6407b9c2a6a56f90c198f5714b3257df24d89d1b4ca6726bd44760d0adabc25798b69fef2c88ccea461c7e79e3c78861aaebfd51fd3cb892aee656c3f7e11801 - languageName: node - linkType: hard - -"@sentry/hub@npm:5.30.0": - version: 5.30.0 - resolution: "@sentry/hub@npm:5.30.0" - dependencies: - "@sentry/types": "npm:5.30.0" - "@sentry/utils": "npm:5.30.0" - tslib: "npm:^1.9.3" - checksum: 10c0/386c91d06aa44be0465fc11330d748a113e464d41cd562a9e1d222a682cbcb14e697a3e640953e7a0239997ad8a02b223a0df3d9e1d8816cb823fd3613be3e2f - languageName: node - linkType: hard - -"@sentry/minimal@npm:5.30.0": - version: 5.30.0 - resolution: "@sentry/minimal@npm:5.30.0" - dependencies: - "@sentry/hub": "npm:5.30.0" - "@sentry/types": "npm:5.30.0" - tslib: "npm:^1.9.3" - checksum: 10c0/34ec05503de46d01f98c94701475d5d89cc044892c86ccce30e01f62f28344eb23b718e7cf573815e46f30a4ac9da3129bed9b3d20c822938acfb40cbe72437b - languageName: node - linkType: hard - -"@sentry/node@npm:^5.18.1": - version: 5.30.0 - resolution: "@sentry/node@npm:5.30.0" - dependencies: - "@sentry/core": "npm:5.30.0" - "@sentry/hub": "npm:5.30.0" - "@sentry/tracing": "npm:5.30.0" - "@sentry/types": "npm:5.30.0" - "@sentry/utils": "npm:5.30.0" - cookie: "npm:^0.4.1" - https-proxy-agent: "npm:^5.0.0" - lru_map: "npm:^0.3.3" - tslib: "npm:^1.9.3" - checksum: 10c0/c50db7c81ace57cac17692245c2ab3c84a6149183f81d5f2dfd157eaa7b66eb4d6a727dd13a754bb129c96711389eec2944cd94126722ee1d8b11f2b627b830d - languageName: node - linkType: hard - -"@sentry/tracing@npm:5.30.0": - version: 5.30.0 - resolution: "@sentry/tracing@npm:5.30.0" - dependencies: - "@sentry/hub": "npm:5.30.0" - "@sentry/minimal": "npm:5.30.0" - "@sentry/types": "npm:5.30.0" - "@sentry/utils": "npm:5.30.0" - tslib: "npm:^1.9.3" - checksum: 10c0/46830265bc54a3203d7d9f0d8d9f2f7d9d2c6a977e07ccdae317fa3ea29c388b904b3bef28f7a0ba9c074845d67feab63c6d3c0ddce9aeb275b6c966253fb415 - languageName: node - linkType: hard - -"@sentry/types@npm:5.30.0": - version: 5.30.0 - resolution: "@sentry/types@npm:5.30.0" - checksum: 10c0/99c6e55c0a82c8ca95be2e9dbb35f581b29e4ff7af74b23bc62b690de4e35febfa15868184a2303480ef86babd4fea5273cf3b5ddf4a27685b841a72f13a0c88 - languageName: node - linkType: hard - -"@sentry/utils@npm:5.30.0": - version: 5.30.0 - resolution: "@sentry/utils@npm:5.30.0" - dependencies: - "@sentry/types": "npm:5.30.0" - tslib: "npm:^1.9.3" - checksum: 10c0/ca8eebfea7ac7db6d16f6c0b8a66ac62587df12a79ce9d0d8393f4d69880bb8d40d438f9810f7fb107a9880fe0d68bbf797b89cbafd113e89a0829eb06b205f8 - languageName: node - linkType: hard - -"@trufflesuite/bigint-buffer@npm:1.1.10": - version: 1.1.10 - resolution: "@trufflesuite/bigint-buffer@npm:1.1.10" - dependencies: - node-gyp: "npm:latest" - node-gyp-build: "npm:4.4.0" - checksum: 10c0/5761201f32d05f1513f6591c38026ce00ff87462e26a2640e458be23fb57fa83b5fddef433220253ee3f98d0010959b7720db0a094d048d1c825978fd7a96938 - languageName: node - linkType: hard - -"@trufflesuite/uws-js-unofficial@npm:20.30.0-unofficial.0": - version: 20.30.0-unofficial.0 - resolution: "@trufflesuite/uws-js-unofficial@npm:20.30.0-unofficial.0" - dependencies: - bufferutil: "npm:4.0.7" - utf-8-validate: "npm:6.0.3" - ws: "npm:8.13.0" - dependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - checksum: 10c0/92f6997409add8b27c9106d3b27ba7d62dc763bff3baa4940bf7db890c12f32bdf88ba163fdb52787c78ed2d4def2f19c912891045914ffc0913d409aaa3b144 - languageName: node - linkType: hard - -"@types/bn.js@npm:^5.1.0": - version: 5.1.5 - resolution: "@types/bn.js@npm:5.1.5" - dependencies: - "@types/node": "npm:*" - checksum: 10c0/e9f375b43d8119ed82aed2090f83d4cda8afbb63ba13223afb02fa7550258ff90acd76d65cd7186838644048f085241cd98a3a512d8d187aa497c6039c746ac8 - languageName: node - linkType: hard - -"@types/lru-cache@npm:5.1.1, @types/lru-cache@npm:^5.1.0": - version: 5.1.1 - resolution: "@types/lru-cache@npm:5.1.1" - checksum: 10c0/1f17ec9b202c01a89337cc5528198a690be6b61a6688242125fbfb7fa17770e453e00e4685021abf5ae605860ca0722209faac5c254b780d0104730bb0b9e354 - languageName: node - linkType: hard - -"@types/node@npm:*": - version: 20.11.16 - resolution: "@types/node@npm:20.11.16" - dependencies: - undici-types: "npm:~5.26.4" - checksum: 10c0/4886b90278e9c877a84efd3edd4667cd990e032d77268d2a798b99ebc1901ea336fa7dfbe9eaf4ad6ad1da9ce2ec31baf300038a3905838692362eb19904ebde - languageName: node - linkType: hard - -"@types/seedrandom@npm:3.0.1": - version: 3.0.1 - resolution: "@types/seedrandom@npm:3.0.1" - checksum: 10c0/b9be192c99b25d7d5d93928e6106f1baff86a4ced33c7b9f94609c659c5d8cb657b70683c74798f83e12caf75af072d3e4f2608ab57a01c897c512fe991f6c9a - languageName: node - linkType: hard - -"@types/ws@npm:8.5.3": - version: 8.5.3 - resolution: "@types/ws@npm:8.5.3" - dependencies: - "@types/node": "npm:*" - checksum: 10c0/af36857b804e6df615b401bacf34e9312f073ed9dbeda35be16ee3352d18a4449f27066169893166a6ec17ae51557c3adf8d232ac4a4a0226aafb3267e1f1b39 - languageName: node - linkType: hard - -"abbrev@npm:^3.0.0": - version: 3.0.1 - resolution: "abbrev@npm:3.0.1" - checksum: 10c0/21ba8f574ea57a3106d6d35623f2c4a9111d9ee3e9a5be47baed46ec2457d2eac46e07a5c4a60186f88cb98abbe3e24f2d4cca70bc2b12f1692523e2209a9ccf - languageName: node - linkType: hard - -"abitype@npm:0.7.1": - version: 0.7.1 - resolution: "abitype@npm:0.7.1" - peerDependencies: - typescript: ">=4.9.4" - zod: ^3 >=3.19.1 - peerDependenciesMeta: - zod: - optional: true - checksum: 10c0/c95386afc8438b29d09fcb6d7bc3a457958ab0a472483a363bdb9bf9f42e1b90ab5b05a16f04b653ad0bf79f4451233fe35fc6c7a04b66cb4eba9df7d8e49f12 - languageName: node - linkType: hard - -"abstract-level@npm:1.0.3": - version: 1.0.3 - resolution: "abstract-level@npm:1.0.3" - dependencies: - buffer: "npm:^6.0.3" - catering: "npm:^2.1.0" - is-buffer: "npm:^2.0.5" - level-supports: "npm:^4.0.0" - level-transcoder: "npm:^1.0.1" - module-error: "npm:^1.0.1" - queue-microtask: "npm:^1.2.3" - checksum: 10c0/ead09e2aebd45a6aa06175dbda19f08c3fbe2b3fb7637cc15f7c165969fb5ef25a04b743f7e1835fd7cb7f8757ba41a9f43f27b092ab78cab5506f250effc966 - languageName: node - linkType: hard - -"abstract-leveldown@npm:7.2.0, abstract-leveldown@npm:^7.2.0": - version: 7.2.0 - resolution: "abstract-leveldown@npm:7.2.0" - dependencies: - buffer: "npm:^6.0.3" - catering: "npm:^2.0.0" - is-buffer: "npm:^2.0.5" - level-concat-iterator: "npm:^3.0.0" - level-supports: "npm:^2.0.1" - queue-microtask: "npm:^1.2.3" - checksum: 10c0/c81765642fc2100499fadc3254470a338ba7c0ba2e597b15cd13d91f333a54619b4d5c4137765e0835817142cd23e8eb7bf01b6a217e13c492f4872c164184dc - languageName: node - linkType: hard - -"adm-zip@npm:^0.4.16": - version: 0.4.16 - resolution: "adm-zip@npm:0.4.16" - checksum: 10c0/c56c6e138fd19006155fc716acae14d54e07c267ae19d78c8a8cdca04762bf20170a71a41aa8d8bad2f13b70d4f3e9a191009bafa5280e05a440ee506f871a55 - languageName: node - linkType: hard - -"agent-base@npm:6": - version: 6.0.2 - resolution: "agent-base@npm:6.0.2" - dependencies: - debug: "npm:4" - checksum: 10c0/dc4f757e40b5f3e3d674bc9beb4f1048f4ee83af189bae39be99f57bf1f48dde166a8b0a5342a84b5944ee8e6ed1e5a9d801858f4ad44764e84957122fe46261 - languageName: node - linkType: hard - -"agent-base@npm:^7.1.0, agent-base@npm:^7.1.2": - version: 7.1.4 - resolution: "agent-base@npm:7.1.4" - checksum: 10c0/c2c9ab7599692d594b6a161559ada307b7a624fa4c7b03e3afdb5a5e31cd0e53269115b620fcab024c5ac6a6f37fa5eb2e004f076ad30f5f7e6b8b671f7b35fe - languageName: node - linkType: hard - -"aggregate-error@npm:^3.0.0": - version: 3.1.0 - resolution: "aggregate-error@npm:3.1.0" - dependencies: - clean-stack: "npm:^2.0.0" - indent-string: "npm:^4.0.0" - checksum: 10c0/a42f67faa79e3e6687a4923050e7c9807db3848a037076f791d10e092677d65c1d2d863b7848560699f40fc0502c19f40963fb1cd1fb3d338a7423df8e45e039 - languageName: node - linkType: hard - -"ansi-align@npm:^3.0.0": - version: 3.0.1 - resolution: "ansi-align@npm:3.0.1" - dependencies: - string-width: "npm:^4.1.0" - checksum: 10c0/ad8b755a253a1bc8234eb341e0cec68a857ab18bf97ba2bda529e86f6e30460416523e0ec58c32e5c21f0ca470d779503244892873a5895dbd0c39c788e82467 - languageName: node - linkType: hard - -"ansi-colors@npm:^4.1.1, ansi-colors@npm:^4.1.3": - version: 4.1.3 - resolution: "ansi-colors@npm:4.1.3" - checksum: 10c0/ec87a2f59902f74e61eada7f6e6fe20094a628dab765cfdbd03c3477599368768cffccdb5d3bb19a1b6c99126783a143b1fee31aab729b31ffe5836c7e5e28b9 - languageName: node - linkType: hard - -"ansi-escapes@npm:^4.3.0": - version: 4.3.2 - resolution: "ansi-escapes@npm:4.3.2" - dependencies: - type-fest: "npm:^0.21.3" - checksum: 10c0/da917be01871525a3dfcf925ae2977bc59e8c513d4423368645634bf5d4ceba5401574eb705c1e92b79f7292af5a656f78c5725a4b0e1cec97c4b413705c1d50 - languageName: node - linkType: hard - -"ansi-regex@npm:^5.0.1": - version: 5.0.1 - resolution: "ansi-regex@npm:5.0.1" - checksum: 10c0/9a64bb8627b434ba9327b60c027742e5d17ac69277960d041898596271d992d4d52ba7267a63ca10232e29f6107fc8a835f6ce8d719b88c5f8493f8254813737 - languageName: node - linkType: hard - -"ansi-regex@npm:^6.0.1": - version: 6.2.2 - resolution: "ansi-regex@npm:6.2.2" - checksum: 10c0/05d4acb1d2f59ab2cf4b794339c7b168890d44dda4bf0ce01152a8da0213aca207802f930442ce8cd22d7a92f44907664aac6508904e75e038fa944d2601b30f - languageName: node - linkType: hard - -"ansi-styles@npm:^4.0.0, ansi-styles@npm:^4.1.0": - version: 4.3.0 - resolution: "ansi-styles@npm:4.3.0" - dependencies: - color-convert: "npm:^2.0.1" - checksum: 10c0/895a23929da416f2bd3de7e9cb4eabd340949328ab85ddd6e484a637d8f6820d485f53933446f5291c3b760cbc488beb8e88573dd0f9c7daf83dccc8fe81b041 - languageName: node - linkType: hard - -"ansi-styles@npm:^6.1.0": - version: 6.2.3 - resolution: "ansi-styles@npm:6.2.3" - checksum: 10c0/23b8a4ce14e18fb854693b95351e286b771d23d8844057ed2e7d083cd3e708376c3323707ec6a24365f7d7eda3ca00327fe04092e29e551499ec4c8b7bfac868 - languageName: node - linkType: hard - -"anymatch@npm:~3.1.2": - version: 3.1.3 - resolution: "anymatch@npm:3.1.3" - dependencies: - normalize-path: "npm:^3.0.0" - picomatch: "npm:^2.0.4" - checksum: 10c0/57b06ae984bc32a0d22592c87384cd88fe4511b1dd7581497831c56d41939c8a001b28e7b853e1450f2bf61992dfcaa8ae2d0d161a0a90c4fb631ef07098fbac - languageName: node - linkType: hard - -"argparse@npm:^2.0.1": - version: 2.0.1 - resolution: "argparse@npm:2.0.1" - checksum: 10c0/c5640c2d89045371c7cedd6a70212a04e360fd34d6edeae32f6952c63949e3525ea77dbec0289d8213a99bbaeab5abfa860b5c12cf88a2e6cf8106e90dd27a7e - languageName: node - linkType: hard - -"async-eventemitter@npm:0.2.4": - version: 0.2.4 - resolution: "async-eventemitter@npm:0.2.4" - dependencies: - async: "npm:^2.4.0" - checksum: 10c0/ce761d1837d454efb456bd2bd5b0db0e100f600d66d9a07a9f7772e0cfd5ad3029bb07385310bd1c7d65603735b755ba457a2f8ed47fb1314a6fe275dd69a322 - languageName: node - linkType: hard - -"async@npm:^2.4.0": - version: 2.6.4 - resolution: "async@npm:2.6.4" - dependencies: - lodash: "npm:^4.17.14" - checksum: 10c0/0ebb3273ef96513389520adc88e0d3c45e523d03653cc9b66f5c46f4239444294899bfd13d2b569e7dbfde7da2235c35cf5fd3ece9524f935d41bbe4efccdad0 - languageName: node - linkType: hard - -"available-typed-arrays@npm:^1.0.7": - version: 1.0.7 - resolution: "available-typed-arrays@npm:1.0.7" - dependencies: - possible-typed-array-names: "npm:^1.0.0" - checksum: 10c0/d07226ef4f87daa01bd0fe80f8f310982e345f372926da2e5296aecc25c41cab440916bbaa4c5e1034b453af3392f67df5961124e4b586df1e99793a1374bdb2 - languageName: node - linkType: hard - -"balanced-match@npm:^1.0.0": - version: 1.0.2 - resolution: "balanced-match@npm:1.0.2" - checksum: 10c0/9308baf0a7e4838a82bbfd11e01b1cb0f0cf2893bc1676c27c2a8c0e70cbae1c59120c3268517a8ae7fb6376b4639ef81ca22582611dbee4ed28df945134aaee - languageName: node - linkType: hard - -"base64-js@npm:^1.3.1": - version: 1.5.1 - resolution: "base64-js@npm:1.5.1" - checksum: 10c0/f23823513b63173a001030fae4f2dabe283b99a9d324ade3ad3d148e218134676f1ee8568c877cd79ec1c53158dcf2d2ba527a97c606618928ba99dd930102bf - languageName: node - linkType: hard - -"bignumber.js@npm:^9.3.0": - version: 9.3.0 - resolution: "bignumber.js@npm:9.3.0" - checksum: 10c0/f54a79cd6fc98552ac0510c1cd9381650870ae443bdb20ba9b98e3548188d941506ac3c22a9f9c69b2cc60da9be5700e87d3f54d2825310a8b2ae999dfd6d99d - languageName: node - linkType: hard - -"binary-extensions@npm:^2.0.0": - version: 2.3.0 - resolution: "binary-extensions@npm:2.3.0" - checksum: 10c0/75a59cafc10fb12a11d510e77110c6c7ae3f4ca22463d52487709ca7f18f69d886aa387557cc9864fbdb10153d0bdb4caacabf11541f55e89ed6e18d12ece2b5 - languageName: node - linkType: hard - -"bn.js@npm:^4.11.9": - version: 4.12.0 - resolution: "bn.js@npm:4.12.0" - checksum: 10c0/9736aaa317421b6b3ed038ff3d4491935a01419ac2d83ddcfebc5717385295fcfcf0c57311d90fe49926d0abbd7a9dbefdd8861e6129939177f7e67ebc645b21 - languageName: node - linkType: hard - -"bn.js@npm:^5.2.1": - version: 5.2.1 - resolution: "bn.js@npm:5.2.1" - checksum: 10c0/bed3d8bd34ec89dbcf9f20f88bd7d4a49c160fda3b561c7bb227501f974d3e435a48fb9b61bc3de304acab9215a3bda0803f7017ffb4d0016a0c3a740a283caa - languageName: node - linkType: hard - -"boxen@npm:^5.1.2": - version: 5.1.2 - resolution: "boxen@npm:5.1.2" - dependencies: - ansi-align: "npm:^3.0.0" - camelcase: "npm:^6.2.0" - chalk: "npm:^4.1.0" - cli-boxes: "npm:^2.2.1" - string-width: "npm:^4.2.2" - type-fest: "npm:^0.20.2" - widest-line: "npm:^3.1.0" - wrap-ansi: "npm:^7.0.0" - checksum: 10c0/71f31c2eb3dcacd5fce524ae509e0cc90421752e0bfbd0281fd3352871d106c462a0f810c85f2fdb02f3a9fab2d7a84e9718b4999384d651b76104ebe5d2c024 - languageName: node - linkType: hard - -"brace-expansion@npm:^2.0.1": - version: 2.0.1 - resolution: "brace-expansion@npm:2.0.1" - dependencies: - balanced-match: "npm:^1.0.0" - checksum: 10c0/b358f2fe060e2d7a87aa015979ecea07f3c37d4018f8d6deb5bd4c229ad3a0384fe6029bb76cd8be63c81e516ee52d1a0673edbe2023d53a5191732ae3c3e49f - languageName: node - linkType: hard - -"braces@npm:~3.0.2": - version: 3.0.3 - resolution: "braces@npm:3.0.3" - dependencies: - fill-range: "npm:^7.1.1" - checksum: 10c0/7c6dfd30c338d2997ba77500539227b9d1f85e388a5f43220865201e407e076783d0881f2d297b9f80951b4c957fcf0b51c1d2d24227631643c3f7c284b0aa04 - languageName: node - linkType: hard - -"brorand@npm:^1.1.0": - version: 1.1.0 - resolution: "brorand@npm:1.1.0" - checksum: 10c0/6f366d7c4990f82c366e3878492ba9a372a73163c09871e80d82fb4ae0d23f9f8924cb8a662330308206e6b3b76ba1d528b4601c9ef73c2166b440b2ea3b7571 - languageName: node - linkType: hard - -"browser-stdout@npm:^1.3.1": - version: 1.3.1 - resolution: "browser-stdout@npm:1.3.1" - checksum: 10c0/c40e482fd82be872b6ea7b9f7591beafbf6f5ba522fe3dade98ba1573a1c29a11101564993e4eb44e5488be8f44510af072df9a9637c739217eb155ceb639205 - languageName: node - linkType: hard - -"buffer-from@npm:^1.0.0": - version: 1.1.2 - resolution: "buffer-from@npm:1.1.2" - checksum: 10c0/124fff9d66d691a86d3b062eff4663fe437a9d9ee4b47b1b9e97f5a5d14f6d5399345db80f796827be7c95e70a8e765dd404b7c3ff3b3324f98e9b0c8826cc34 - languageName: node - linkType: hard - -"buffer@npm:^6.0.3": - version: 6.0.3 - resolution: "buffer@npm:6.0.3" - dependencies: - base64-js: "npm:^1.3.1" - ieee754: "npm:^1.2.1" - checksum: 10c0/2a905fbbcde73cc5d8bd18d1caa23715d5f83a5935867c2329f0ac06104204ba7947be098fe1317fbd8830e26090ff8e764f08cd14fefc977bb248c3487bcbd0 - languageName: node - linkType: hard - -"bufferutil@npm:4.0.5": - version: 4.0.5 - resolution: "bufferutil@npm:4.0.5" - dependencies: - node-gyp: "npm:latest" - node-gyp-build: "npm:^4.3.0" - checksum: 10c0/307d1131dbfd01b1451585931db05bc83a5a94bb3f720f9ee2d8e1ce37d39b23251bce350b06152dba003ad4fbddc804fc94b3d5ce1f70e7871c6898ce3b4f7e - languageName: node - linkType: hard - -"bufferutil@npm:4.0.7": - version: 4.0.7 - resolution: "bufferutil@npm:4.0.7" - dependencies: - node-gyp: "npm:latest" - node-gyp-build: "npm:^4.3.0" - checksum: 10c0/48d6cf98b9c227db65f0a1062b6c80e933c43dc03e0ad5f908da0e79cc87a633c215516f4d541ca9b0e09c1fb386f1bbe1fc2de913057f0201d14798d3e0c2bb - languageName: node - linkType: hard - -"bytes@npm:3.1.2": - version: 3.1.2 - resolution: "bytes@npm:3.1.2" - checksum: 10c0/76d1c43cbd602794ad8ad2ae94095cddeb1de78c5dddaa7005c51af10b0176c69971a6d88e805a90c2b6550d76636e43c40d8427a808b8645ede885de4a0358e - languageName: node - linkType: hard - -"cacache@npm:^19.0.1": - version: 19.0.1 - resolution: "cacache@npm:19.0.1" - dependencies: - "@npmcli/fs": "npm:^4.0.0" - fs-minipass: "npm:^3.0.0" - glob: "npm:^10.2.2" - lru-cache: "npm:^10.0.1" - minipass: "npm:^7.0.3" - minipass-collect: "npm:^2.0.1" - minipass-flush: "npm:^1.0.5" - minipass-pipeline: "npm:^1.2.4" - p-map: "npm:^7.0.2" - ssri: "npm:^12.0.0" - tar: "npm:^7.4.3" - unique-filename: "npm:^4.0.0" - checksum: 10c0/01f2134e1bd7d3ab68be851df96c8d63b492b1853b67f2eecb2c37bb682d37cb70bb858a16f2f0554d3c0071be6dfe21456a1ff6fa4b7eed996570d6a25ffe9c - languageName: node - linkType: hard - -"call-bind-apply-helpers@npm:^1.0.0, call-bind-apply-helpers@npm:^1.0.1, call-bind-apply-helpers@npm:^1.0.2": - version: 1.0.2 - resolution: "call-bind-apply-helpers@npm:1.0.2" - dependencies: - es-errors: "npm:^1.3.0" - function-bind: "npm:^1.1.2" - checksum: 10c0/47bd9901d57b857590431243fea704ff18078b16890a6b3e021e12d279bbf211d039155e27d7566b374d49ee1f8189344bac9833dec7a20cdec370506361c938 - languageName: node - linkType: hard - -"call-bind@npm:^1.0.8": - version: 1.0.8 - resolution: "call-bind@npm:1.0.8" - dependencies: - call-bind-apply-helpers: "npm:^1.0.0" - es-define-property: "npm:^1.0.0" - get-intrinsic: "npm:^1.2.4" - set-function-length: "npm:^1.2.2" - checksum: 10c0/a13819be0681d915144467741b69875ae5f4eba8961eb0bf322aab63ec87f8250eb6d6b0dcbb2e1349876412a56129ca338592b3829ef4343527f5f18a0752d4 - languageName: node - linkType: hard - -"call-bound@npm:^1.0.2, call-bound@npm:^1.0.3, call-bound@npm:^1.0.4": - version: 1.0.4 - resolution: "call-bound@npm:1.0.4" - dependencies: - call-bind-apply-helpers: "npm:^1.0.2" - get-intrinsic: "npm:^1.3.0" - checksum: 10c0/f4796a6a0941e71c766aea672f63b72bc61234c4f4964dc6d7606e3664c307e7d77845328a8f3359ce39ddb377fed67318f9ee203dea1d47e46165dcf2917644 - languageName: node - linkType: hard - -"camelcase@npm:^6.0.0, camelcase@npm:^6.2.0": - version: 6.3.0 - resolution: "camelcase@npm:6.3.0" - checksum: 10c0/0d701658219bd3116d12da3eab31acddb3f9440790c0792e0d398f0a520a6a4058018e546862b6fba89d7ae990efaeb97da71e1913e9ebf5a8b5621a3d55c710 - languageName: node - linkType: hard - -"catering@npm:^2.0.0, catering@npm:^2.1.0": - version: 2.1.1 - resolution: "catering@npm:2.1.1" - checksum: 10c0/a69f946f82cba85509abcb399759ed4c39d2cc9e33ba35674f242130c1b3c56673da3c3e85804db6898dfd966c395aa128ba484b31c7b906cc2faca6a581e133 - languageName: node - linkType: hard - -"chalk@npm:^4.1.0": - version: 4.1.2 - resolution: "chalk@npm:4.1.2" - dependencies: - ansi-styles: "npm:^4.1.0" - supports-color: "npm:^7.1.0" - checksum: 10c0/4a3fef5cc34975c898ffe77141450f679721df9dde00f6c304353fa9c8b571929123b26a0e4617bde5018977eb655b31970c297b91b63ee83bb82aeb04666880 - languageName: node - linkType: hard - -"chokidar@npm:^3.5.3": - version: 3.6.0 - resolution: "chokidar@npm:3.6.0" - dependencies: - anymatch: "npm:~3.1.2" - braces: "npm:~3.0.2" - fsevents: "npm:~2.3.2" - glob-parent: "npm:~5.1.2" - is-binary-path: "npm:~2.1.0" - is-glob: "npm:~4.0.1" - normalize-path: "npm:~3.0.0" - readdirp: "npm:~3.6.0" - dependenciesMeta: - fsevents: - optional: true - checksum: 10c0/8361dcd013f2ddbe260eacb1f3cb2f2c6f2b0ad118708a343a5ed8158941a39cb8fb1d272e0f389712e74ee90ce8ba864eece9e0e62b9705cb468a2f6d917462 - languageName: node - linkType: hard - -"chokidar@npm:^4.0.0": - version: 4.0.3 - resolution: "chokidar@npm:4.0.3" - dependencies: - readdirp: "npm:^4.0.1" - checksum: 10c0/a58b9df05bb452f7d105d9e7229ac82fa873741c0c40ddcc7bb82f8a909fbe3f7814c9ebe9bc9a2bef9b737c0ec6e2d699d179048ef06ad3ec46315df0ebe6ad - languageName: node - linkType: hard - -"chownr@npm:^3.0.0": - version: 3.0.0 - resolution: "chownr@npm:3.0.0" - checksum: 10c0/43925b87700f7e3893296c8e9c56cc58f926411cce3a6e5898136daaf08f08b9a8eb76d37d3267e707d0dcc17aed2e2ebdf5848c0c3ce95cf910a919935c1b10 - languageName: node - linkType: hard - -"ci-info@npm:^2.0.0": - version: 2.0.0 - resolution: "ci-info@npm:2.0.0" - checksum: 10c0/8c5fa3830a2bcee2b53c2e5018226f0141db9ec9f7b1e27a5c57db5512332cde8a0beb769bcbaf0d8775a78afbf2bb841928feca4ea6219638a5b088f9884b46 - languageName: node - linkType: hard - -"clean-stack@npm:^2.0.0": - version: 2.2.0 - resolution: "clean-stack@npm:2.2.0" - checksum: 10c0/1f90262d5f6230a17e27d0c190b09d47ebe7efdd76a03b5a1127863f7b3c9aec4c3e6c8bb3a7bbf81d553d56a1fd35728f5a8ef4c63f867ac8d690109742a8c1 - languageName: node - linkType: hard - -"cli-boxes@npm:^2.2.1": - version: 2.2.1 - resolution: "cli-boxes@npm:2.2.1" - checksum: 10c0/6111352edbb2f62dbc7bfd58f2d534de507afed7f189f13fa894ce5a48badd94b2aa502fda28f1d7dd5f1eb456e7d4033d09a76660013ef50c7f66e7a034f050 - languageName: node - linkType: hard - -"cliui@npm:^7.0.2": - version: 7.0.4 - resolution: "cliui@npm:7.0.4" - dependencies: - string-width: "npm:^4.2.0" - strip-ansi: "npm:^6.0.0" - wrap-ansi: "npm:^7.0.0" - checksum: 10c0/6035f5daf7383470cef82b3d3db00bec70afb3423538c50394386ffbbab135e26c3689c41791f911fa71b62d13d3863c712fdd70f0fbdffd938a1e6fd09aac00 - languageName: node - linkType: hard - -"color-convert@npm:^2.0.1": - version: 2.0.1 - resolution: "color-convert@npm:2.0.1" - dependencies: - color-name: "npm:~1.1.4" - checksum: 10c0/37e1150172f2e311fe1b2df62c6293a342ee7380da7b9cfdba67ea539909afbd74da27033208d01d6d5cfc65ee7868a22e18d7e7648e004425441c0f8a15a7d7 - languageName: node - linkType: hard - -"color-name@npm:~1.1.4": - version: 1.1.4 - resolution: "color-name@npm:1.1.4" - checksum: 10c0/a1a3f914156960902f46f7f56bc62effc6c94e84b2cae157a526b1c1f74b677a47ec602bf68a61abfa2b42d15b7c5651c6dbe72a43af720bc588dff885b10f95 - languageName: node - linkType: hard - -"command-exists@npm:^1.2.8": - version: 1.2.9 - resolution: "command-exists@npm:1.2.9" - checksum: 10c0/75040240062de46cd6cd43e6b3032a8b0494525c89d3962e280dde665103f8cc304a8b313a5aa541b91da2f5a9af75c5959dc3a77893a2726407a5e9a0234c16 - languageName: node - linkType: hard - -"commander@npm:^8.1.0": - version: 8.3.0 - resolution: "commander@npm:8.3.0" - checksum: 10c0/8b043bb8322ea1c39664a1598a95e0495bfe4ca2fad0d84a92d7d1d8d213e2a155b441d2470c8e08de7c4a28cf2bc6e169211c49e1b21d9f7edc6ae4d9356060 - languageName: node - linkType: hard - -"cookie@npm:^0.4.1": - version: 0.4.2 - resolution: "cookie@npm:0.4.2" - checksum: 10c0/beab41fbd7c20175e3a2799ba948c1dcc71ef69f23fe14eeeff59fc09f50c517b0f77098db87dbb4c55da802f9d86ee86cdc1cd3efd87760341551838d53fca2 - languageName: node - linkType: hard - -"crc-32@npm:^1.2.2": - version: 1.2.2 - resolution: "crc-32@npm:1.2.2" - bin: - crc32: bin/crc32.njs - checksum: 10c0/11dcf4a2e77ee793835d49f2c028838eae58b44f50d1ff08394a610bfd817523f105d6ae4d9b5bef0aad45510f633eb23c903e9902e4409bed1ce70cb82b9bf0 - languageName: node - linkType: hard - -"cross-fetch@npm:^4.0.0": - version: 4.1.0 - resolution: "cross-fetch@npm:4.1.0" - dependencies: - node-fetch: "npm:^2.7.0" - checksum: 10c0/628b134ea27cfcada67025afe6ef1419813fffc5d63d175553efa75a2334522d450300a0f3f0719029700da80e96327930709d5551cf6deb39bb62f1d536642e - languageName: node - linkType: hard - -"cross-spawn@npm:^7.0.6": - version: 7.0.6 - resolution: "cross-spawn@npm:7.0.6" - dependencies: - path-key: "npm:^3.1.0" - shebang-command: "npm:^2.0.0" - which: "npm:^2.0.1" - checksum: 10c0/053ea8b2135caff68a9e81470e845613e374e7309a47731e81639de3eaeb90c3d01af0e0b44d2ab9d50b43467223b88567dfeb3262db942dc063b9976718ffc1 - languageName: node - linkType: hard - -"debug@npm:4, debug@npm:^4.1.1, debug@npm:^4.3.5": - version: 4.4.0 - resolution: "debug@npm:4.4.0" - dependencies: - ms: "npm:^2.1.3" - peerDependenciesMeta: - supports-color: - optional: true - checksum: 10c0/db94f1a182bf886f57b4755f85b3a74c39b5114b9377b7ab375dc2cfa3454f09490cc6c30f829df3fc8042bc8b8995f6567ce5cd96f3bc3688bd24027197d9de - languageName: node - linkType: hard - -"debug@npm:^4.3.4": - version: 4.4.3 - resolution: "debug@npm:4.4.3" - dependencies: - ms: "npm:^2.1.3" - peerDependenciesMeta: - supports-color: - optional: true - checksum: 10c0/d79136ec6c83ecbefd0f6a5593da6a9c91ec4d7ddc4b54c883d6e71ec9accb5f67a1a5e96d00a328196b5b5c86d365e98d8a3a70856aaf16b4e7b1985e67f5a6 - languageName: node - linkType: hard - -"decamelize@npm:^4.0.0": - version: 4.0.0 - resolution: "decamelize@npm:4.0.0" - checksum: 10c0/e06da03fc05333e8cd2778c1487da67ffbea5b84e03ca80449519b8fa61f888714bbc6f459ea963d5641b4aa98832130eb5cd193d90ae9f0a27eee14be8e278d - languageName: node - linkType: hard - -"define-data-property@npm:^1.1.4": - version: 1.1.4 - resolution: "define-data-property@npm:1.1.4" - dependencies: - es-define-property: "npm:^1.0.0" - es-errors: "npm:^1.3.0" - gopd: "npm:^1.0.1" - checksum: 10c0/dea0606d1483eb9db8d930d4eac62ca0fa16738b0b3e07046cddfacf7d8c868bbe13fa0cb263eb91c7d0d527960dc3f2f2471a69ed7816210307f6744fe62e37 - languageName: node - linkType: hard - -"depd@npm:2.0.0": - version: 2.0.0 - resolution: "depd@npm:2.0.0" - checksum: 10c0/58bd06ec20e19529b06f7ad07ddab60e504d9e0faca4bd23079fac2d279c3594334d736508dc350e06e510aba5e22e4594483b3a6562ce7c17dd797f4cc4ad2c - languageName: node - linkType: hard - -"diff@npm:^5.2.0": - version: 5.2.0 - resolution: "diff@npm:5.2.0" - checksum: 10c0/aed0941f206fe261ecb258dc8d0ceea8abbde3ace5827518ff8d302f0fc9cc81ce116c4d8f379151171336caf0516b79e01abdc1ed1201b6440d895a66689eb4 - languageName: node - linkType: hard - -"dunder-proto@npm:^1.0.1": - version: 1.0.1 - resolution: "dunder-proto@npm:1.0.1" - dependencies: - call-bind-apply-helpers: "npm:^1.0.1" - es-errors: "npm:^1.3.0" - gopd: "npm:^1.2.0" - checksum: 10c0/199f2a0c1c16593ca0a145dbf76a962f8033ce3129f01284d48c45ed4e14fea9bbacd7b3610b6cdc33486cef20385ac054948fefc6272fcce645c09468f93031 - languageName: node - linkType: hard - -"eastasianwidth@npm:^0.2.0": - version: 0.2.0 - resolution: "eastasianwidth@npm:0.2.0" - checksum: 10c0/26f364ebcdb6395f95124fda411f63137a4bfb5d3a06453f7f23dfe52502905bd84e0488172e0f9ec295fdc45f05c23d5d91baf16bd26f0fe9acd777a188dc39 - languageName: node - linkType: hard - -"elliptic@npm:6.6.1": - version: 6.6.1 - resolution: "elliptic@npm:6.6.1" - dependencies: - bn.js: "npm:^4.11.9" - brorand: "npm:^1.1.0" - hash.js: "npm:^1.0.0" - hmac-drbg: "npm:^1.0.1" - inherits: "npm:^2.0.4" - minimalistic-assert: "npm:^1.0.1" - minimalistic-crypto-utils: "npm:^1.0.1" - checksum: 10c0/8b24ef782eec8b472053793ea1e91ae6bee41afffdfcb78a81c0a53b191e715cbe1292aa07165958a9bbe675bd0955142560b1a007ffce7d6c765bcaf951a867 - languageName: node - linkType: hard - -"elliptic@npm:^6.5.4": - version: 6.5.4 - resolution: "elliptic@npm:6.5.4" - dependencies: - bn.js: "npm:^4.11.9" - brorand: "npm:^1.1.0" - hash.js: "npm:^1.0.0" - hmac-drbg: "npm:^1.0.1" - inherits: "npm:^2.0.4" - minimalistic-assert: "npm:^1.0.1" - minimalistic-crypto-utils: "npm:^1.0.1" - checksum: 10c0/5f361270292c3b27cf0843e84526d11dec31652f03c2763c6c2b8178548175ff5eba95341dd62baff92b2265d1af076526915d8af6cc9cb7559c44a62f8ca6e2 - languageName: node - linkType: hard - -"emittery@npm:0.10.0": - version: 0.10.0 - resolution: "emittery@npm:0.10.0" - checksum: 10c0/c2ad40e5bab53094070f7cb9d1b9a26fbbba6ab4b952cf5f33b8f64032356767c80c5aec2523aa7e44940c1cdb4f125d06a9cffd489a9be65103bb8a16ce173b - languageName: node - linkType: hard - -"emoji-regex@npm:^8.0.0": - version: 8.0.0 - resolution: "emoji-regex@npm:8.0.0" - checksum: 10c0/b6053ad39951c4cf338f9092d7bfba448cdfd46fe6a2a034700b149ac9ffbc137e361cbd3c442297f86bed2e5f7576c1b54cc0a6bf8ef5106cc62f496af35010 - languageName: node - linkType: hard - -"emoji-regex@npm:^9.2.2": - version: 9.2.2 - resolution: "emoji-regex@npm:9.2.2" - checksum: 10c0/af014e759a72064cf66e6e694a7fc6b0ed3d8db680427b021a89727689671cefe9d04151b2cad51dbaf85d5ba790d061cd167f1cf32eb7b281f6368b3c181639 - languageName: node - linkType: hard - -"encoding@npm:^0.1.13": - version: 0.1.13 - resolution: "encoding@npm:0.1.13" - dependencies: - iconv-lite: "npm:^0.6.2" - checksum: 10c0/36d938712ff00fe1f4bac88b43bcffb5930c1efa57bbcdca9d67e1d9d6c57cfb1200fb01efe0f3109b2ce99b231f90779532814a81370a1bd3274a0f58585039 - languageName: node - linkType: hard - -"enquirer@npm:^2.3.0": - version: 2.4.1 - resolution: "enquirer@npm:2.4.1" - dependencies: - ansi-colors: "npm:^4.1.1" - strip-ansi: "npm:^6.0.1" - checksum: 10c0/43850479d7a51d36a9c924b518dcdc6373b5a8ae3401097d336b7b7e258324749d0ad37a1fcaa5706f04799baa05585cd7af19ebdf7667673e7694435fcea918 - languageName: node - linkType: hard - -"env-paths@npm:^2.2.0": - version: 2.2.1 - resolution: "env-paths@npm:2.2.1" - checksum: 10c0/285325677bf00e30845e330eec32894f5105529db97496ee3f598478e50f008c5352a41a30e5e72ec9de8a542b5a570b85699cd63bd2bc646dbcb9f311d83bc4 - languageName: node - linkType: hard - -"err-code@npm:^2.0.2": - version: 2.0.3 - resolution: "err-code@npm:2.0.3" - checksum: 10c0/b642f7b4dd4a376e954947550a3065a9ece6733ab8e51ad80db727aaae0817c2e99b02a97a3d6cecc648a97848305e728289cf312d09af395403a90c9d4d8a66 - languageName: node - linkType: hard - -"es-define-property@npm:^1.0.0, es-define-property@npm:^1.0.1": - version: 1.0.1 - resolution: "es-define-property@npm:1.0.1" - checksum: 10c0/3f54eb49c16c18707949ff25a1456728c883e81259f045003499efba399c08bad00deebf65cccde8c0e07908c1a225c9d472b7107e558f2a48e28d530e34527c - languageName: node - linkType: hard - -"es-errors@npm:^1.3.0": - version: 1.3.0 - resolution: "es-errors@npm:1.3.0" - checksum: 10c0/0a61325670072f98d8ae3b914edab3559b6caa980f08054a3b872052640d91da01d38df55df797fcc916389d77fc92b8d5906cf028f4db46d7e3003abecbca85 - languageName: node - linkType: hard - -"es-object-atoms@npm:^1.0.0, es-object-atoms@npm:^1.1.1": - version: 1.1.1 - resolution: "es-object-atoms@npm:1.1.1" - dependencies: - es-errors: "npm:^1.3.0" - checksum: 10c0/65364812ca4daf48eb76e2a3b7a89b3f6a2e62a1c420766ce9f692665a29d94fe41fe88b65f24106f449859549711e4b40d9fb8002d862dfd7eb1c512d10be0c - languageName: node - linkType: hard - -"esbuild@npm:~0.25.0": - version: 0.25.5 - resolution: "esbuild@npm:0.25.5" - dependencies: - "@esbuild/aix-ppc64": "npm:0.25.5" - "@esbuild/android-arm": "npm:0.25.5" - "@esbuild/android-arm64": "npm:0.25.5" - "@esbuild/android-x64": "npm:0.25.5" - "@esbuild/darwin-arm64": "npm:0.25.5" - "@esbuild/darwin-x64": "npm:0.25.5" - "@esbuild/freebsd-arm64": "npm:0.25.5" - "@esbuild/freebsd-x64": "npm:0.25.5" - "@esbuild/linux-arm": "npm:0.25.5" - "@esbuild/linux-arm64": "npm:0.25.5" - "@esbuild/linux-ia32": "npm:0.25.5" - "@esbuild/linux-loong64": "npm:0.25.5" - "@esbuild/linux-mips64el": "npm:0.25.5" - "@esbuild/linux-ppc64": "npm:0.25.5" - "@esbuild/linux-riscv64": "npm:0.25.5" - "@esbuild/linux-s390x": "npm:0.25.5" - "@esbuild/linux-x64": "npm:0.25.5" - "@esbuild/netbsd-arm64": "npm:0.25.5" - "@esbuild/netbsd-x64": "npm:0.25.5" - "@esbuild/openbsd-arm64": "npm:0.25.5" - "@esbuild/openbsd-x64": "npm:0.25.5" - "@esbuild/sunos-x64": "npm:0.25.5" - "@esbuild/win32-arm64": "npm:0.25.5" - "@esbuild/win32-ia32": "npm:0.25.5" - "@esbuild/win32-x64": "npm:0.25.5" - dependenciesMeta: - "@esbuild/aix-ppc64": - optional: true - "@esbuild/android-arm": - optional: true - "@esbuild/android-arm64": - optional: true - "@esbuild/android-x64": - optional: true - "@esbuild/darwin-arm64": - optional: true - "@esbuild/darwin-x64": - optional: true - "@esbuild/freebsd-arm64": - optional: true - "@esbuild/freebsd-x64": - optional: true - "@esbuild/linux-arm": - optional: true - "@esbuild/linux-arm64": - optional: true - "@esbuild/linux-ia32": - optional: true - "@esbuild/linux-loong64": - optional: true - "@esbuild/linux-mips64el": - optional: true - "@esbuild/linux-ppc64": - optional: true - "@esbuild/linux-riscv64": - optional: true - "@esbuild/linux-s390x": - optional: true - "@esbuild/linux-x64": - optional: true - "@esbuild/netbsd-arm64": - optional: true - "@esbuild/netbsd-x64": - optional: true - "@esbuild/openbsd-arm64": - optional: true - "@esbuild/openbsd-x64": - optional: true - "@esbuild/sunos-x64": - optional: true - "@esbuild/win32-arm64": - optional: true - "@esbuild/win32-ia32": - optional: true - "@esbuild/win32-x64": - optional: true - bin: - esbuild: bin/esbuild - checksum: 10c0/aba8cbc11927fa77562722ed5e95541ce2853f67ad7bdc40382b558abc2e0ec57d92ffb820f082ba2047b4ef9f3bc3da068cdebe30dfd3850cfa3827a78d604e - languageName: node - linkType: hard - -"escalade@npm:^3.1.1": - version: 3.2.0 - resolution: "escalade@npm:3.2.0" - checksum: 10c0/ced4dd3a78e15897ed3be74e635110bbf3b08877b0a41be50dcb325ee0e0b5f65fc2d50e9845194d7c4633f327e2e1c6cce00a71b617c5673df0374201d67f65 - languageName: node - linkType: hard - -"escape-string-regexp@npm:^4.0.0": - version: 4.0.0 - resolution: "escape-string-regexp@npm:4.0.0" - checksum: 10c0/9497d4dd307d845bd7f75180d8188bb17ea8c151c1edbf6b6717c100e104d629dc2dfb687686181b0f4b7d732c7dfdc4d5e7a8ff72de1b0ca283a75bbb3a9cd9 - languageName: node - linkType: hard - -"ethereum-cryptography@npm:^1.0.3": - version: 1.2.0 - resolution: "ethereum-cryptography@npm:1.2.0" - dependencies: - "@noble/hashes": "npm:1.2.0" - "@noble/secp256k1": "npm:1.7.1" - "@scure/bip32": "npm:1.1.5" - "@scure/bip39": "npm:1.1.1" - checksum: 10c0/93e486a4a8b266dc2f274b69252e751345ef47551163371939b01231afb7b519133e2572b5975bb9cb4cc77ac54ccd36002c7c759a72488abeeaf216e4d55b46 - languageName: node - linkType: hard - -"ethereum-cryptography@npm:^2.0.0, ethereum-cryptography@npm:^2.2.1": - version: 2.2.1 - resolution: "ethereum-cryptography@npm:2.2.1" - dependencies: - "@noble/curves": "npm:1.4.2" - "@noble/hashes": "npm:1.4.0" - "@scure/bip32": "npm:1.4.0" - "@scure/bip39": "npm:1.3.0" - checksum: 10c0/c6c7626d393980577b57f709878b2eb91f270fe56116044b1d7afb70d5c519cddc0c072e8c05e4a335e05342eb64d9c3ab39d52f78bb75f76ad70817da9645ef - languageName: node - linkType: hard - -"eventemitter3@npm:^5.0.1": - version: 5.0.1 - resolution: "eventemitter3@npm:5.0.1" - checksum: 10c0/4ba5c00c506e6c786b4d6262cfbce90ddc14c10d4667e5c83ae993c9de88aa856033994dd2b35b83e8dc1170e224e66a319fa80adc4c32adcd2379bbc75da814 - languageName: node - linkType: hard - -"exponential-backoff@npm:^3.1.1": - version: 3.1.2 - resolution: "exponential-backoff@npm:3.1.2" - checksum: 10c0/d9d3e1eafa21b78464297df91f1776f7fbaa3d5e3f7f0995648ca5b89c069d17055033817348d9f4a43d1c20b0eab84f75af6991751e839df53e4dfd6f22e844 - languageName: node - linkType: hard - -"fdir@npm:^6.4.3": - version: 6.4.3 - resolution: "fdir@npm:6.4.3" - peerDependencies: - picomatch: ^3 || ^4 - peerDependenciesMeta: - picomatch: - optional: true - checksum: 10c0/d13c10120e9625adf21d8d80481586200759928c19405a816b77dd28eaeb80e7c59c5def3e2941508045eb06d34eb47fad865ccc8bf98e6ab988bb0ed160fb6f - languageName: node - linkType: hard - -"fdir@npm:^6.5.0": - version: 6.5.0 - resolution: "fdir@npm:6.5.0" - peerDependencies: - picomatch: ^3 || ^4 - peerDependenciesMeta: - picomatch: - optional: true - checksum: 10c0/e345083c4306b3aed6cb8ec551e26c36bab5c511e99ea4576a16750ddc8d3240e63826cc624f5ae17ad4dc82e68a253213b60d556c11bfad064b7607847ed07f - languageName: node - linkType: hard - -"fill-range@npm:^7.1.1": - version: 7.1.1 - resolution: "fill-range@npm:7.1.1" - dependencies: - to-regex-range: "npm:^5.0.1" - checksum: 10c0/b75b691bbe065472f38824f694c2f7449d7f5004aa950426a2c28f0306c60db9b880c0b0e4ed819997ffb882d1da02cfcfc819bddc94d71627f5269682edf018 - languageName: node - linkType: hard - -"find-up@npm:^5.0.0": - version: 5.0.0 - resolution: "find-up@npm:5.0.0" - dependencies: - locate-path: "npm:^6.0.0" - path-exists: "npm:^4.0.0" - checksum: 10c0/062c5a83a9c02f53cdd6d175a37ecf8f87ea5bbff1fdfb828f04bfa021441bc7583e8ebc0872a4c1baab96221fb8a8a275a19809fb93fbc40bd69ec35634069a - languageName: node - linkType: hard - -"flat@npm:^5.0.2": - version: 5.0.2 - resolution: "flat@npm:5.0.2" - bin: - flat: cli.js - checksum: 10c0/f178b13482f0cd80c7fede05f4d10585b1f2fdebf26e12edc138e32d3150c6ea6482b7f12813a1091143bad52bb6d3596bca51a162257a21163c0ff438baa5fe - languageName: node - linkType: hard - -"follow-redirects@npm:^1.12.1": - version: 1.15.9 - resolution: "follow-redirects@npm:1.15.9" - peerDependenciesMeta: - debug: - optional: true - checksum: 10c0/5829165bd112c3c0e82be6c15b1a58fa9dcfaede3b3c54697a82fe4a62dd5ae5e8222956b448d2f98e331525f05d00404aba7d696de9e761ef6e42fdc780244f - languageName: node - linkType: hard - -"for-each@npm:^0.3.5": - version: 0.3.5 - resolution: "for-each@npm:0.3.5" - dependencies: - is-callable: "npm:^1.2.7" - checksum: 10c0/0e0b50f6a843a282637d43674d1fb278dda1dd85f4f99b640024cfb10b85058aac0cc781bf689d5fe50b4b7f638e91e548560723a4e76e04fe96ae35ef039cee - languageName: node - linkType: hard - -"foreground-child@npm:^3.1.0": - version: 3.3.1 - resolution: "foreground-child@npm:3.3.1" - dependencies: - cross-spawn: "npm:^7.0.6" - signal-exit: "npm:^4.0.1" - checksum: 10c0/8986e4af2430896e65bc2788d6679067294d6aee9545daefc84923a0a4b399ad9c7a3ea7bd8c0b2b80fdf4a92de4c69df3f628233ff3224260e9c1541a9e9ed3 - languageName: node - linkType: hard - -"fp-ts@npm:1.19.3": - version: 1.19.3 - resolution: "fp-ts@npm:1.19.3" - checksum: 10c0/a016cfc98ad5e61564ab2d53a5379bbb8254642b66df13ced47e8c1d8d507abf4588d8bb43530198dfe1907211d8bae8f112cab52ba0ac6ab055da9168a6e260 - languageName: node - linkType: hard - -"fp-ts@npm:^1.0.0": - version: 1.19.5 - resolution: "fp-ts@npm:1.19.5" - checksum: 10c0/2a330fa1779561307740c26a7255fdffeb1ca2d0c7448d4dc094b477b772b0c8f7da1dfc88569b6f13f6958169b63b5df7361e514535b46b2e215bbf03a3722d - languageName: node - linkType: hard - -"fs-extra@npm:^7.0.1": - version: 7.0.1 - resolution: "fs-extra@npm:7.0.1" - dependencies: - graceful-fs: "npm:^4.1.2" - jsonfile: "npm:^4.0.0" - universalify: "npm:^0.1.0" - checksum: 10c0/1943bb2150007e3739921b8d13d4109abdc3cc481e53b97b7ea7f77eda1c3c642e27ae49eac3af074e3496ea02fde30f411ef410c760c70a38b92e656e5da784 - languageName: node - linkType: hard - -"fs-minipass@npm:^3.0.0": - version: 3.0.3 - resolution: "fs-minipass@npm:3.0.3" - dependencies: - minipass: "npm:^7.0.3" - checksum: 10c0/63e80da2ff9b621e2cb1596abcb9207f1cf82b968b116ccd7b959e3323144cce7fb141462200971c38bbf2ecca51695069db45265705bed09a7cd93ae5b89f94 - languageName: node - linkType: hard - -"fs.realpath@npm:^1.0.0": - version: 1.0.0 - resolution: "fs.realpath@npm:1.0.0" - checksum: 10c0/444cf1291d997165dfd4c0d58b69f0e4782bfd9149fd72faa4fe299e68e0e93d6db941660b37dd29153bf7186672ececa3b50b7e7249477b03fdf850f287c948 - languageName: node - linkType: hard - -"fsevents@npm:~2.3.2, fsevents@npm:~2.3.3": - version: 2.3.3 - resolution: "fsevents@npm:2.3.3" - dependencies: - node-gyp: "npm:latest" - checksum: 10c0/a1f0c44595123ed717febbc478aa952e47adfc28e2092be66b8ab1635147254ca6cfe1df792a8997f22716d4cbafc73309899ff7bfac2ac3ad8cf2e4ecc3ec60 - conditions: os=darwin - languageName: node - linkType: hard - -"fsevents@patch:fsevents@npm%3A~2.3.2#optional!builtin, fsevents@patch:fsevents@npm%3A~2.3.3#optional!builtin": - version: 2.3.3 - resolution: "fsevents@patch:fsevents@npm%3A2.3.3#optional!builtin::version=2.3.3&hash=df0bf1" - dependencies: - node-gyp: "npm:latest" - conditions: os=darwin - languageName: node - linkType: hard - -"function-bind@npm:^1.1.2": - version: 1.1.2 - resolution: "function-bind@npm:1.1.2" - checksum: 10c0/d8680ee1e5fcd4c197e4ac33b2b4dce03c71f4d91717292785703db200f5c21f977c568d28061226f9b5900cbcd2c84463646134fd5337e7925e0942bc3f46d5 - languageName: node - linkType: hard - -"get-caller-file@npm:^2.0.5": - version: 2.0.5 - resolution: "get-caller-file@npm:2.0.5" - checksum: 10c0/c6c7b60271931fa752aeb92f2b47e355eac1af3a2673f47c9589e8f8a41adc74d45551c1bc57b5e66a80609f10ffb72b6f575e4370d61cc3f7f3aaff01757cde - languageName: node - linkType: hard - -"get-intrinsic@npm:^1.2.4, get-intrinsic@npm:^1.3.0": - version: 1.3.0 - resolution: "get-intrinsic@npm:1.3.0" - dependencies: - call-bind-apply-helpers: "npm:^1.0.2" - es-define-property: "npm:^1.0.1" - es-errors: "npm:^1.3.0" - es-object-atoms: "npm:^1.1.1" - function-bind: "npm:^1.1.2" - get-proto: "npm:^1.0.1" - gopd: "npm:^1.2.0" - has-symbols: "npm:^1.1.0" - hasown: "npm:^2.0.2" - math-intrinsics: "npm:^1.1.0" - checksum: 10c0/52c81808af9a8130f581e6a6a83e1ba4a9f703359e7a438d1369a5267a25412322f03dcbd7c549edaef0b6214a0630a28511d7df0130c93cfd380f4fa0b5b66a - languageName: node - linkType: hard - -"get-proto@npm:^1.0.0, get-proto@npm:^1.0.1": - version: 1.0.1 - resolution: "get-proto@npm:1.0.1" - dependencies: - dunder-proto: "npm:^1.0.1" - es-object-atoms: "npm:^1.0.0" - checksum: 10c0/9224acb44603c5526955e83510b9da41baf6ae73f7398875fba50edc5e944223a89c4a72b070fcd78beb5f7bdda58ecb6294adc28f7acfc0da05f76a2399643c - languageName: node - linkType: hard - -"get-tsconfig@npm:^4.7.5": - version: 4.10.1 - resolution: "get-tsconfig@npm:4.10.1" - dependencies: - resolve-pkg-maps: "npm:^1.0.0" - checksum: 10c0/7f8e3dabc6a49b747920a800fb88e1952fef871cdf51b79e98db48275a5de6cdaf499c55ee67df5fa6fe7ce65f0063e26de0f2e53049b408c585aa74d39ffa21 - languageName: node - linkType: hard - -"glob-parent@npm:~5.1.2": - version: 5.1.2 - resolution: "glob-parent@npm:5.1.2" - dependencies: - is-glob: "npm:^4.0.1" - checksum: 10c0/cab87638e2112bee3f839ef5f6e0765057163d39c66be8ec1602f3823da4692297ad4e972de876ea17c44d652978638d2fd583c6713d0eb6591706825020c9ee - languageName: node - linkType: hard - -"glob@npm:^10.2.2": - version: 10.4.5 - resolution: "glob@npm:10.4.5" - dependencies: - foreground-child: "npm:^3.1.0" - jackspeak: "npm:^3.1.2" - minimatch: "npm:^9.0.4" - minipass: "npm:^7.1.2" - package-json-from-dist: "npm:^1.0.0" - path-scurry: "npm:^1.11.1" - bin: - glob: dist/esm/bin.mjs - checksum: 10c0/19a9759ea77b8e3ca0a43c2f07ecddc2ad46216b786bb8f993c445aee80d345925a21e5280c7b7c6c59e860a0154b84e4b2b60321fea92cd3c56b4a7489f160e - languageName: node - linkType: hard - -"glob@npm:^8.1.0": - version: 8.1.0 - resolution: "glob@npm:8.1.0" - dependencies: - fs.realpath: "npm:^1.0.0" - inflight: "npm:^1.0.4" - inherits: "npm:2" - minimatch: "npm:^5.0.1" - once: "npm:^1.3.0" - checksum: 10c0/cb0b5cab17a59c57299376abe5646c7070f8acb89df5595b492dba3bfb43d301a46c01e5695f01154e6553168207cb60d4eaf07d3be4bc3eb9b0457c5c561d0f - languageName: node - linkType: hard - -"gopd@npm:^1.0.1, gopd@npm:^1.2.0": - version: 1.2.0 - resolution: "gopd@npm:1.2.0" - checksum: 10c0/50fff1e04ba2b7737c097358534eacadad1e68d24cccee3272e04e007bed008e68d2614f3987788428fd192a5ae3889d08fb2331417e4fc4a9ab366b2043cead - languageName: node - linkType: hard - -"graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.6": - version: 4.2.11 - resolution: "graceful-fs@npm:4.2.11" - checksum: 10c0/386d011a553e02bc594ac2ca0bd6d9e4c22d7fa8cfbfc448a6d148c59ea881b092db9dbe3547ae4b88e55f1b01f7c4a2ecc53b310c042793e63aa44cf6c257f2 - languageName: node - linkType: hard - -"hardhat@npm:^2.24.1": - version: 2.24.1 - resolution: "hardhat@npm:2.24.1" - dependencies: - "@ethereumjs/util": "npm:^9.1.0" - "@ethersproject/abi": "npm:^5.1.2" - "@nomicfoundation/edr": "npm:^0.11.0" - "@nomicfoundation/solidity-analyzer": "npm:^0.1.0" - "@sentry/node": "npm:^5.18.1" - "@types/bn.js": "npm:^5.1.0" - "@types/lru-cache": "npm:^5.1.0" - adm-zip: "npm:^0.4.16" - aggregate-error: "npm:^3.0.0" - ansi-escapes: "npm:^4.3.0" - boxen: "npm:^5.1.2" - chokidar: "npm:^4.0.0" - ci-info: "npm:^2.0.0" - debug: "npm:^4.1.1" - enquirer: "npm:^2.3.0" - env-paths: "npm:^2.2.0" - ethereum-cryptography: "npm:^1.0.3" - find-up: "npm:^5.0.0" - fp-ts: "npm:1.19.3" - fs-extra: "npm:^7.0.1" - immutable: "npm:^4.0.0-rc.12" - io-ts: "npm:1.10.4" - json-stream-stringify: "npm:^3.1.4" - keccak: "npm:^3.0.2" - lodash: "npm:^4.17.11" - micro-eth-signer: "npm:^0.14.0" - mnemonist: "npm:^0.38.0" - mocha: "npm:^10.0.0" - p-map: "npm:^4.0.0" - picocolors: "npm:^1.1.0" - raw-body: "npm:^2.4.1" - resolve: "npm:1.17.0" - semver: "npm:^6.3.0" - solc: "npm:0.8.26" - source-map-support: "npm:^0.5.13" - stacktrace-parser: "npm:^0.1.10" - tinyglobby: "npm:^0.2.6" - tsort: "npm:0.0.1" - undici: "npm:^5.14.0" - uuid: "npm:^8.3.2" - ws: "npm:^7.4.6" - peerDependencies: - ts-node: "*" - typescript: "*" - peerDependenciesMeta: - ts-node: - optional: true - typescript: - optional: true - bin: - hardhat: internal/cli/bootstrap.js - checksum: 10c0/1dc09dbfd4566c059fea04786379a981d9a86c9d6caf3c3597aaa94a0f00ecda35f01462ce2edd5e6713366858bb9080c970c65a9e6011943fbd133961446d39 - languageName: node - linkType: hard - -"has-flag@npm:^4.0.0": - version: 4.0.0 - resolution: "has-flag@npm:4.0.0" - checksum: 10c0/2e789c61b7888d66993e14e8331449e525ef42aac53c627cc53d1c3334e768bcb6abdc4f5f0de1478a25beec6f0bd62c7549058b7ac53e924040d4f301f02fd1 - languageName: node - linkType: hard - -"has-property-descriptors@npm:^1.0.2": - version: 1.0.2 - resolution: "has-property-descriptors@npm:1.0.2" - dependencies: - es-define-property: "npm:^1.0.0" - checksum: 10c0/253c1f59e80bb476cf0dde8ff5284505d90c3bdb762983c3514d36414290475fe3fd6f574929d84de2a8eec00d35cf07cb6776205ff32efd7c50719125f00236 - languageName: node - linkType: hard - -"has-symbols@npm:^1.0.3, has-symbols@npm:^1.1.0": - version: 1.1.0 - resolution: "has-symbols@npm:1.1.0" - checksum: 10c0/dde0a734b17ae51e84b10986e651c664379018d10b91b6b0e9b293eddb32f0f069688c841fb40f19e9611546130153e0a2a48fd7f512891fb000ddfa36f5a20e - languageName: node - linkType: hard - -"has-tostringtag@npm:^1.0.2": - version: 1.0.2 - resolution: "has-tostringtag@npm:1.0.2" - dependencies: - has-symbols: "npm:^1.0.3" - checksum: 10c0/a8b166462192bafe3d9b6e420a1d581d93dd867adb61be223a17a8d6dad147aa77a8be32c961bb2f27b3ef893cae8d36f564ab651f5e9b7938ae86f74027c48c - languageName: node - linkType: hard - -"hash.js@npm:1.1.7, hash.js@npm:^1.0.0, hash.js@npm:^1.0.3": - version: 1.1.7 - resolution: "hash.js@npm:1.1.7" - dependencies: - inherits: "npm:^2.0.3" - minimalistic-assert: "npm:^1.0.1" - checksum: 10c0/41ada59494eac5332cfc1ce6b7ebdd7b88a3864a6d6b08a3ea8ef261332ed60f37f10877e0c825aaa4bddebf164fbffa618286aeeec5296675e2671cbfa746c4 - languageName: node - linkType: hard - -"hasown@npm:^2.0.2": - version: 2.0.2 - resolution: "hasown@npm:2.0.2" - dependencies: - function-bind: "npm:^1.1.2" - checksum: 10c0/3769d434703b8ac66b209a4cca0737519925bbdb61dd887f93a16372b14694c63ff4e797686d87c90f08168e81082248b9b028bad60d4da9e0d1148766f56eb9 - languageName: node - linkType: hard - -"he@npm:^1.2.0": - version: 1.2.0 - resolution: "he@npm:1.2.0" - bin: - he: bin/he - checksum: 10c0/a27d478befe3c8192f006cdd0639a66798979dfa6e2125c6ac582a19a5ebfec62ad83e8382e6036170d873f46e4536a7e795bf8b95bf7c247f4cc0825ccc8c17 - languageName: node - linkType: hard - -"hmac-drbg@npm:^1.0.1": - version: 1.0.1 - resolution: "hmac-drbg@npm:1.0.1" - dependencies: - hash.js: "npm:^1.0.3" - minimalistic-assert: "npm:^1.0.0" - minimalistic-crypto-utils: "npm:^1.0.1" - checksum: 10c0/f3d9ba31b40257a573f162176ac5930109816036c59a09f901eb2ffd7e5e705c6832bedfff507957125f2086a0ab8f853c0df225642a88bf1fcaea945f20600d - languageName: node - linkType: hard - -"http-cache-semantics@npm:^4.1.1": - version: 4.2.0 - resolution: "http-cache-semantics@npm:4.2.0" - checksum: 10c0/45b66a945cf13ec2d1f29432277201313babf4a01d9e52f44b31ca923434083afeca03f18417f599c9ab3d0e7b618ceb21257542338b57c54b710463b4a53e37 - languageName: node - linkType: hard - -"http-errors@npm:2.0.0": - version: 2.0.0 - resolution: "http-errors@npm:2.0.0" - dependencies: - depd: "npm:2.0.0" - inherits: "npm:2.0.4" - setprototypeof: "npm:1.2.0" - statuses: "npm:2.0.1" - toidentifier: "npm:1.0.1" - checksum: 10c0/fc6f2715fe188d091274b5ffc8b3657bd85c63e969daa68ccb77afb05b071a4b62841acb7a21e417b5539014dff2ebf9550f0b14a9ff126f2734a7c1387f8e19 - languageName: node - linkType: hard - -"http-proxy-agent@npm:^7.0.0": - version: 7.0.2 - resolution: "http-proxy-agent@npm:7.0.2" - dependencies: - agent-base: "npm:^7.1.0" - debug: "npm:^4.3.4" - checksum: 10c0/4207b06a4580fb85dd6dff521f0abf6db517489e70863dca1a0291daa7f2d3d2d6015a57bd702af068ea5cf9f1f6ff72314f5f5b4228d299c0904135d2aef921 - languageName: node - linkType: hard - -"https-proxy-agent@npm:^5.0.0": - version: 5.0.1 - resolution: "https-proxy-agent@npm:5.0.1" - dependencies: - agent-base: "npm:6" - debug: "npm:4" - checksum: 10c0/6dd639f03434003577c62b27cafdb864784ef19b2de430d8ae2a1d45e31c4fd60719e5637b44db1a88a046934307da7089e03d6089ec3ddacc1189d8de8897d1 - languageName: node - linkType: hard - -"https-proxy-agent@npm:^7.0.1": - version: 7.0.6 - resolution: "https-proxy-agent@npm:7.0.6" - dependencies: - agent-base: "npm:^7.1.2" - debug: "npm:4" - checksum: 10c0/f729219bc735edb621fa30e6e84e60ee5d00802b8247aac0d7b79b0bd6d4b3294737a337b93b86a0bd9e68099d031858a39260c976dc14cdbba238ba1f8779ac - languageName: node - linkType: hard - -"iconv-lite@npm:0.4.24": - version: 0.4.24 - resolution: "iconv-lite@npm:0.4.24" - dependencies: - safer-buffer: "npm:>= 2.1.2 < 3" - checksum: 10c0/c6886a24cc00f2a059767440ec1bc00d334a89f250db8e0f7feb4961c8727118457e27c495ba94d082e51d3baca378726cd110aaf7ded8b9bbfd6a44760cf1d4 - languageName: node - linkType: hard - -"iconv-lite@npm:^0.6.2": - version: 0.6.3 - resolution: "iconv-lite@npm:0.6.3" - dependencies: - safer-buffer: "npm:>= 2.1.2 < 3.0.0" - checksum: 10c0/98102bc66b33fcf5ac044099d1257ba0b7ad5e3ccd3221f34dd508ab4070edff183276221684e1e0555b145fce0850c9f7d2b60a9fcac50fbb4ea0d6e845a3b1 - languageName: node - linkType: hard - -"ieee754@npm:^1.2.1": - version: 1.2.1 - resolution: "ieee754@npm:1.2.1" - checksum: 10c0/b0782ef5e0935b9f12883a2e2aa37baa75da6e66ce6515c168697b42160807d9330de9a32ec1ed73149aea02e0d822e572bca6f1e22bdcbd2149e13b050b17bb - languageName: node - linkType: hard - -"immutable@npm:^4.0.0-rc.12": - version: 4.3.7 - resolution: "immutable@npm:4.3.7" - checksum: 10c0/9b099197081b22f6433003e34929da8ecddbbdc1474cdc8aa3b7669dee4adda349c06143de22def36016d1b6de5322b043eccd7a11db1dad2ca85dad4fff5435 - languageName: node - linkType: hard - -"imurmurhash@npm:^0.1.4": - version: 0.1.4 - resolution: "imurmurhash@npm:0.1.4" - checksum: 10c0/8b51313850dd33605c6c9d3fd9638b714f4c4c40250cff658209f30d40da60f78992fb2df5dabee4acf589a6a82bbc79ad5486550754bd9ec4e3fc0d4a57d6a6 - languageName: node - linkType: hard - -"indent-string@npm:^4.0.0": - version: 4.0.0 - resolution: "indent-string@npm:4.0.0" - checksum: 10c0/1e1904ddb0cb3d6cce7cd09e27a90184908b7a5d5c21b92e232c93579d314f0b83c246ffb035493d0504b1e9147ba2c9b21df0030f48673fba0496ecd698161f - languageName: node - linkType: hard - -"inflight@npm:^1.0.4": - version: 1.0.6 - resolution: "inflight@npm:1.0.6" - dependencies: - once: "npm:^1.3.0" - wrappy: "npm:1" - checksum: 10c0/7faca22584600a9dc5b9fca2cd5feb7135ac8c935449837b315676b4c90aa4f391ec4f42240178244b5a34e8bede1948627fda392ca3191522fc46b34e985ab2 - languageName: node - linkType: hard - -"inherits@npm:2, inherits@npm:2.0.4, inherits@npm:^2.0.3, inherits@npm:^2.0.4": - version: 2.0.4 - resolution: "inherits@npm:2.0.4" - checksum: 10c0/4e531f648b29039fb7426fb94075e6545faa1eb9fe83c29f0b6d9e7263aceb4289d2d4557db0d428188eeb449cc7c5e77b0a0b2c4e248ff2a65933a0dee49ef2 - languageName: node - linkType: hard - -"io-ts@npm:1.10.4": - version: 1.10.4 - resolution: "io-ts@npm:1.10.4" - dependencies: - fp-ts: "npm:^1.0.0" - checksum: 10c0/9370988a7e17fc23c194115808168ccd1ccf7b7ebe92c39c1cc2fd91c1dc641552a5428bb04fe28c01c826fa4f230e856eb4f7d27c774a1400af3fecf2936ab5 - languageName: node - linkType: hard - -"ip-address@npm:^10.0.1": - version: 10.0.1 - resolution: "ip-address@npm:10.0.1" - checksum: 10c0/1634d79dae18394004775cb6d699dc46b7c23df6d2083164025a2b15240c1164fccde53d0e08bd5ee4fc53913d033ab6b5e395a809ad4b956a940c446e948843 - languageName: node - linkType: hard - -"is-arguments@npm:^1.0.4": - version: 1.2.0 - resolution: "is-arguments@npm:1.2.0" - dependencies: - call-bound: "npm:^1.0.2" - has-tostringtag: "npm:^1.0.2" - checksum: 10c0/6377344b31e9fcb707c6751ee89b11f132f32338e6a782ec2eac9393b0cbd32235dad93052998cda778ee058754860738341d8114910d50ada5615912bb929fc - languageName: node - linkType: hard - -"is-binary-path@npm:~2.1.0": - version: 2.1.0 - resolution: "is-binary-path@npm:2.1.0" - dependencies: - binary-extensions: "npm:^2.0.0" - checksum: 10c0/a16eaee59ae2b315ba36fad5c5dcaf8e49c3e27318f8ab8fa3cdb8772bf559c8d1ba750a589c2ccb096113bb64497084361a25960899cb6172a6925ab6123d38 - languageName: node - linkType: hard - -"is-buffer@npm:^2.0.5": - version: 2.0.5 - resolution: "is-buffer@npm:2.0.5" - checksum: 10c0/e603f6fced83cf94c53399cff3bda1a9f08e391b872b64a73793b0928be3e5f047f2bcece230edb7632eaea2acdbfcb56c23b33d8a20c820023b230f1485679a - languageName: node - linkType: hard - -"is-callable@npm:^1.2.7": - version: 1.2.7 - resolution: "is-callable@npm:1.2.7" - checksum: 10c0/ceebaeb9d92e8adee604076971dd6000d38d6afc40bb843ea8e45c5579b57671c3f3b50d7f04869618242c6cee08d1b67806a8cb8edaaaf7c0748b3720d6066f - languageName: node - linkType: hard - -"is-extglob@npm:^2.1.1": - version: 2.1.1 - resolution: "is-extglob@npm:2.1.1" - checksum: 10c0/5487da35691fbc339700bbb2730430b07777a3c21b9ebaecb3072512dfd7b4ba78ac2381a87e8d78d20ea08affb3f1971b4af629173a6bf435ff8a4c47747912 - languageName: node - linkType: hard - -"is-fullwidth-code-point@npm:^3.0.0": - version: 3.0.0 - resolution: "is-fullwidth-code-point@npm:3.0.0" - checksum: 10c0/bb11d825e049f38e04c06373a8d72782eee0205bda9d908cc550ccb3c59b99d750ff9537982e01733c1c94a58e35400661f57042158ff5e8f3e90cf936daf0fc - languageName: node - linkType: hard - -"is-generator-function@npm:^1.0.7": - version: 1.1.0 - resolution: "is-generator-function@npm:1.1.0" - dependencies: - call-bound: "npm:^1.0.3" - get-proto: "npm:^1.0.0" - has-tostringtag: "npm:^1.0.2" - safe-regex-test: "npm:^1.1.0" - checksum: 10c0/fdfa96c8087bf36fc4cd514b474ba2ff404219a4dd4cfa6cf5426404a1eed259bdcdb98f082a71029a48d01f27733e3436ecc6690129a7ec09cb0434bee03a2a - languageName: node - linkType: hard - -"is-glob@npm:^4.0.1, is-glob@npm:~4.0.1": - version: 4.0.3 - resolution: "is-glob@npm:4.0.3" - dependencies: - is-extglob: "npm:^2.1.1" - checksum: 10c0/17fb4014e22be3bbecea9b2e3a76e9e34ff645466be702f1693e8f1ee1adac84710d0be0bd9f967d6354036fd51ab7c2741d954d6e91dae6bb69714de92c197a - languageName: node - linkType: hard - -"is-number@npm:^7.0.0": - version: 7.0.0 - resolution: "is-number@npm:7.0.0" - checksum: 10c0/b4686d0d3053146095ccd45346461bc8e53b80aeb7671cc52a4de02dbbf7dc0d1d2a986e2fe4ae206984b4d34ef37e8b795ebc4f4295c978373e6575e295d811 - languageName: node - linkType: hard - -"is-plain-obj@npm:^2.1.0": - version: 2.1.0 - resolution: "is-plain-obj@npm:2.1.0" - checksum: 10c0/e5c9814cdaa627a9ad0a0964ded0e0491bfd9ace405c49a5d63c88b30a162f1512c069d5b80997893c4d0181eadc3fed02b4ab4b81059aba5620bfcdfdeb9c53 - languageName: node - linkType: hard - -"is-regex@npm:^1.2.1": - version: 1.2.1 - resolution: "is-regex@npm:1.2.1" - dependencies: - call-bound: "npm:^1.0.2" - gopd: "npm:^1.2.0" - has-tostringtag: "npm:^1.0.2" - hasown: "npm:^2.0.2" - checksum: 10c0/1d3715d2b7889932349241680032e85d0b492cfcb045acb75ffc2c3085e8d561184f1f7e84b6f8321935b4aea39bc9c6ba74ed595b57ce4881a51dfdbc214e04 - languageName: node - linkType: hard - -"is-typed-array@npm:^1.1.3": - version: 1.1.15 - resolution: "is-typed-array@npm:1.1.15" - dependencies: - which-typed-array: "npm:^1.1.16" - checksum: 10c0/415511da3669e36e002820584e264997ffe277ff136643a3126cc949197e6ca3334d0f12d084e83b1994af2e9c8141275c741cf2b7da5a2ff62dd0cac26f76c4 - languageName: node - linkType: hard - -"is-unicode-supported@npm:^0.1.0": - version: 0.1.0 - resolution: "is-unicode-supported@npm:0.1.0" - checksum: 10c0/00cbe3455c3756be68d2542c416cab888aebd5012781d6819749fefb15162ff23e38501fe681b3d751c73e8ff561ac09a5293eba6f58fdf0178462ce6dcb3453 - languageName: node - linkType: hard - -"isexe@npm:^2.0.0": - version: 2.0.0 - resolution: "isexe@npm:2.0.0" - checksum: 10c0/228cfa503fadc2c31596ab06ed6aa82c9976eec2bfd83397e7eaf06d0ccf42cd1dfd6743bf9aeb01aebd4156d009994c5f76ea898d2832c1fe342da923ca457d - languageName: node - linkType: hard - -"isexe@npm:^3.1.1": - version: 3.1.1 - resolution: "isexe@npm:3.1.1" - checksum: 10c0/9ec257654093443eb0a528a9c8cbba9c0ca7616ccb40abd6dde7202734d96bb86e4ac0d764f0f8cd965856aacbff2f4ce23e730dc19dfb41e3b0d865ca6fdcc7 - languageName: node - linkType: hard - -"isomorphic-ws@npm:^5.0.0": - version: 5.0.0 - resolution: "isomorphic-ws@npm:5.0.0" - peerDependencies: - ws: "*" - checksum: 10c0/a058ac8b5e6efe9e46252cb0bc67fd325005d7216451d1a51238bc62d7da8486f828ef017df54ddf742e0fffcbe4b1bcc2a66cc115b027ed0180334cd18df252 - languageName: node - linkType: hard - -"jackspeak@npm:^3.1.2": - version: 3.4.3 - resolution: "jackspeak@npm:3.4.3" - dependencies: - "@isaacs/cliui": "npm:^8.0.2" - "@pkgjs/parseargs": "npm:^0.11.0" - dependenciesMeta: - "@pkgjs/parseargs": - optional: true - checksum: 10c0/6acc10d139eaefdbe04d2f679e6191b3abf073f111edf10b1de5302c97ec93fffeb2fdd8681ed17f16268aa9dd4f8c588ed9d1d3bffbbfa6e8bf897cbb3149b9 - languageName: node - linkType: hard - -"js-sha3@npm:0.8.0": - version: 0.8.0 - resolution: "js-sha3@npm:0.8.0" - checksum: 10c0/43a21dc7967c871bd2c46cb1c2ae97441a97169f324e509f382d43330d8f75cf2c96dba7c806ab08a425765a9c847efdd4bffbac2d99c3a4f3de6c0218f40533 - languageName: node - linkType: hard - -"js-yaml@npm:^4.1.0": - version: 4.1.0 - resolution: "js-yaml@npm:4.1.0" - dependencies: - argparse: "npm:^2.0.1" - bin: - js-yaml: bin/js-yaml.js - checksum: 10c0/184a24b4eaacfce40ad9074c64fd42ac83cf74d8c8cd137718d456ced75051229e5061b8633c3366b8aada17945a7a356b337828c19da92b51ae62126575018f - languageName: node - linkType: hard - -"json-stream-stringify@npm:^3.1.4": - version: 3.1.6 - resolution: "json-stream-stringify@npm:3.1.6" - checksum: 10c0/cb45e65143f4634ebb2dc0732410a942eaf86f88a7938b2f6397f4c6b96a7ba936e74d4d17db48c9221f669153996362b2ff50fe8c7fed8a7548646f98ae1f58 - languageName: node - linkType: hard - -"jsonfile@npm:^4.0.0": - version: 4.0.0 - resolution: "jsonfile@npm:4.0.0" - dependencies: - graceful-fs: "npm:^4.1.6" - dependenciesMeta: - graceful-fs: - optional: true - checksum: 10c0/7dc94b628d57a66b71fb1b79510d460d662eb975b5f876d723f81549c2e9cd316d58a2ddf742b2b93a4fa6b17b2accaf1a738a0e2ea114bdfb13a32e5377e480 - languageName: node - linkType: hard - -"keccak@npm:3.0.2": - version: 3.0.2 - resolution: "keccak@npm:3.0.2" - dependencies: - node-addon-api: "npm:^2.0.0" - node-gyp: "npm:latest" - node-gyp-build: "npm:^4.2.0" - readable-stream: "npm:^3.6.0" - checksum: 10c0/f1673e0f9bab4eb8a5bd232227916c592716d3b961e14e6ab3fabcf703c896c83fdbcd230f7b4a44f076d50fb0931ec1b093a98e4b0e74680b56be123a4a93f6 - languageName: node - linkType: hard - -"keccak@npm:^3.0.2": - version: 3.0.4 - resolution: "keccak@npm:3.0.4" - dependencies: - node-addon-api: "npm:^2.0.0" - node-gyp: "npm:latest" - node-gyp-build: "npm:^4.2.0" - readable-stream: "npm:^3.6.0" - checksum: 10c0/153525c1c1f770beadb8f8897dec2f1d2dcbee11d063fe5f61957a5b236bfd3d2a111ae2727e443aa6a848df5edb98b9ef237c78d56df49087b0ca8a232ca9cd - languageName: node - linkType: hard - -"level-concat-iterator@npm:^3.0.0": - version: 3.1.0 - resolution: "level-concat-iterator@npm:3.1.0" - dependencies: - catering: "npm:^2.1.0" - checksum: 10c0/7bb1b8e991a179de2fecfd38d2c34544a139e1228cb730f3024ef11dcbd514cc89be30b02a2a81ef4e16b0c1553f604378f67302ea23868d98f055f9fa241ae4 - languageName: node - linkType: hard - -"level-supports@npm:^2.0.1": - version: 2.1.0 - resolution: "level-supports@npm:2.1.0" - checksum: 10c0/60481dd403234c64e2c01ed2aafdc75250ddd49d770f75ebef3f92a2a5b2271bf774858bfd8c47cfae3955855f9ff9dd536683d6cffb7c085cd0e57245c4c039 - languageName: node - linkType: hard - -"level-supports@npm:^4.0.0": - version: 4.0.1 - resolution: "level-supports@npm:4.0.1" - checksum: 10c0/a94aa591786845d17c9c62ad075ae33e0fce5be714baa6e16305ed14e2d3638d09e724247fa3f63951e36de57ffd168d63e159e79d03944ee648054b8c7c1684 - languageName: node - linkType: hard - -"level-transcoder@npm:^1.0.1": - version: 1.0.1 - resolution: "level-transcoder@npm:1.0.1" - dependencies: - buffer: "npm:^6.0.3" - module-error: "npm:^1.0.1" - checksum: 10c0/25936330676325f22c5143aff5c7fe3f1db156db99f9efb07a2642045c2c6ee565fcbfccbadc0600b3abf8bbe595632cacc3dd334009214069d1857daa57987e - languageName: node - linkType: hard - -"leveldown@npm:6.1.0": - version: 6.1.0 - resolution: "leveldown@npm:6.1.0" - dependencies: - abstract-leveldown: "npm:^7.2.0" - napi-macros: "npm:~2.0.0" - node-gyp: "npm:latest" - node-gyp-build: "npm:^4.3.0" - checksum: 10c0/5af0a9596baf44187a5cce5095d78b7c085d8c5a94d652ed42e7a40c60f057135d17b52ae473f9719c674e93db3941831406206f469c4e9f62987ceed92c33e1 - languageName: node - linkType: hard - -"locate-path@npm:^6.0.0": - version: 6.0.0 - resolution: "locate-path@npm:6.0.0" - dependencies: - p-locate: "npm:^5.0.0" - checksum: 10c0/d3972ab70dfe58ce620e64265f90162d247e87159b6126b01314dd67be43d50e96a50b517bce2d9452a79409c7614054c277b5232377de50416564a77ac7aad3 - languageName: node - linkType: hard - -"lodash@npm:^4.17.11, lodash@npm:^4.17.14": - version: 4.17.21 - resolution: "lodash@npm:4.17.21" - checksum: 10c0/d8cbea072bb08655bb4c989da418994b073a608dffa608b09ac04b43a791b12aeae7cd7ad919aa4c925f33b48490b5cfe6c1f71d827956071dae2e7bb3a6b74c - languageName: node - linkType: hard - -"log-symbols@npm:^4.1.0": - version: 4.1.0 - resolution: "log-symbols@npm:4.1.0" - dependencies: - chalk: "npm:^4.1.0" - is-unicode-supported: "npm:^0.1.0" - checksum: 10c0/67f445a9ffa76db1989d0fa98586e5bc2fd5247260dafb8ad93d9f0ccd5896d53fb830b0e54dade5ad838b9de2006c826831a3c528913093af20dff8bd24aca6 - languageName: node - linkType: hard - -"lru-cache@npm:^10.0.1, lru-cache@npm:^10.2.0": - version: 10.4.3 - resolution: "lru-cache@npm:10.4.3" - checksum: 10c0/ebd04fbca961e6c1d6c0af3799adcc966a1babe798f685bb84e6599266599cd95d94630b10262f5424539bc4640107e8a33aa28585374abf561d30d16f4b39fb - languageName: node - linkType: hard - -"lru_map@npm:^0.3.3": - version: 0.3.3 - resolution: "lru_map@npm:0.3.3" - checksum: 10c0/d861f14a142a4a74ebf8d3ad57f2e768a5b820db4100ae53eed1a64eb6350912332e6ebc87cb7415ad6d0cd8f3ce6d20beab9a5e6042ccb5996ea0067a220448 - languageName: node - linkType: hard - -"make-fetch-happen@npm:^14.0.3": - version: 14.0.3 - resolution: "make-fetch-happen@npm:14.0.3" - dependencies: - "@npmcli/agent": "npm:^3.0.0" - cacache: "npm:^19.0.1" - http-cache-semantics: "npm:^4.1.1" - minipass: "npm:^7.0.2" - minipass-fetch: "npm:^4.0.0" - minipass-flush: "npm:^1.0.5" - minipass-pipeline: "npm:^1.2.4" - negotiator: "npm:^1.0.0" - proc-log: "npm:^5.0.0" - promise-retry: "npm:^2.0.1" - ssri: "npm:^12.0.0" - checksum: 10c0/c40efb5e5296e7feb8e37155bde8eb70bc57d731b1f7d90e35a092fde403d7697c56fb49334d92d330d6f1ca29a98142036d6480a12681133a0a1453164cb2f0 - languageName: node - linkType: hard - -"math-intrinsics@npm:^1.1.0": - version: 1.1.0 - resolution: "math-intrinsics@npm:1.1.0" - checksum: 10c0/7579ff94e899e2f76ab64491d76cf606274c874d8f2af4a442c016bd85688927fcfca157ba6bf74b08e9439dc010b248ce05b96cc7c126a354c3bae7fcb48b7f - languageName: node - linkType: hard - -"memorystream@npm:^0.3.1": - version: 0.3.1 - resolution: "memorystream@npm:0.3.1" - checksum: 10c0/4bd164657711d9747ff5edb0508b2944414da3464b7fe21ac5c67cf35bba975c4b446a0124bd0f9a8be54cfc18faf92e92bd77563a20328b1ccf2ff04e9f39b9 - languageName: node - linkType: hard - -"micro-eth-signer@npm:^0.14.0": - version: 0.14.0 - resolution: "micro-eth-signer@npm:0.14.0" - dependencies: - "@noble/curves": "npm:~1.8.1" - "@noble/hashes": "npm:~1.7.1" - micro-packed: "npm:~0.7.2" - checksum: 10c0/62c90d54d2b97cb4eaf713c69bc4ceb5903012d0237c26f0966076cfb89c4527de68b395e1bc29e6f237152ce08f7b551fb57b332003518a1331c2c0890fb164 - languageName: node - linkType: hard - -"micro-packed@npm:~0.7.2": - version: 0.7.3 - resolution: "micro-packed@npm:0.7.3" - dependencies: - "@scure/base": "npm:~1.2.5" - checksum: 10c0/1fde48a96d8d5606d3298ff36717bf7483d6d59e2d96f50cb88727379127a4d52881f48e7e1ce0d4906b2711b1902fb04d2128576326ce4d07e171ac022a4c2d - languageName: node - linkType: hard - -"minimalistic-assert@npm:^1.0.0, minimalistic-assert@npm:^1.0.1": - version: 1.0.1 - resolution: "minimalistic-assert@npm:1.0.1" - checksum: 10c0/96730e5601cd31457f81a296f521eb56036e6f69133c0b18c13fe941109d53ad23a4204d946a0d638d7f3099482a0cec8c9bb6d642604612ce43ee536be3dddd - languageName: node - linkType: hard - -"minimalistic-crypto-utils@npm:^1.0.1": - version: 1.0.1 - resolution: "minimalistic-crypto-utils@npm:1.0.1" - checksum: 10c0/790ecec8c5c73973a4fbf2c663d911033e8494d5fb0960a4500634766ab05d6107d20af896ca2132e7031741f19888154d44b2408ada0852446705441383e9f8 - languageName: node - linkType: hard - -"minimatch@npm:^5.0.1, minimatch@npm:^5.1.6": - version: 5.1.6 - resolution: "minimatch@npm:5.1.6" - dependencies: - brace-expansion: "npm:^2.0.1" - checksum: 10c0/3defdfd230914f22a8da203747c42ee3c405c39d4d37ffda284dac5e45b7e1f6c49aa8be606509002898e73091ff2a3bbfc59c2c6c71d4660609f63aa92f98e3 - languageName: node - linkType: hard - -"minimatch@npm:^9.0.4": - version: 9.0.5 - resolution: "minimatch@npm:9.0.5" - dependencies: - brace-expansion: "npm:^2.0.1" - checksum: 10c0/de96cf5e35bdf0eab3e2c853522f98ffbe9a36c37797778d2665231ec1f20a9447a7e567cb640901f89e4daaa95ae5d70c65a9e8aa2bb0019b6facbc3c0575ed - languageName: node - linkType: hard - -"minipass-collect@npm:^2.0.1": - version: 2.0.1 - resolution: "minipass-collect@npm:2.0.1" - dependencies: - minipass: "npm:^7.0.3" - checksum: 10c0/5167e73f62bb74cc5019594709c77e6a742051a647fe9499abf03c71dca75515b7959d67a764bdc4f8b361cf897fbf25e2d9869ee039203ed45240f48b9aa06e - languageName: node - linkType: hard - -"minipass-fetch@npm:^4.0.0": - version: 4.0.1 - resolution: "minipass-fetch@npm:4.0.1" - dependencies: - encoding: "npm:^0.1.13" - minipass: "npm:^7.0.3" - minipass-sized: "npm:^1.0.3" - minizlib: "npm:^3.0.1" - dependenciesMeta: - encoding: - optional: true - checksum: 10c0/a3147b2efe8e078c9bf9d024a0059339c5a09c5b1dded6900a219c218cc8b1b78510b62dae556b507304af226b18c3f1aeb1d48660283602d5b6586c399eed5c - languageName: node - linkType: hard - -"minipass-flush@npm:^1.0.5": - version: 1.0.5 - resolution: "minipass-flush@npm:1.0.5" - dependencies: - minipass: "npm:^3.0.0" - checksum: 10c0/2a51b63feb799d2bb34669205eee7c0eaf9dce01883261a5b77410c9408aa447e478efd191b4de6fc1101e796ff5892f8443ef20d9544385819093dbb32d36bd - languageName: node - linkType: hard - -"minipass-pipeline@npm:^1.2.4": - version: 1.2.4 - resolution: "minipass-pipeline@npm:1.2.4" - dependencies: - minipass: "npm:^3.0.0" - checksum: 10c0/cbda57cea20b140b797505dc2cac71581a70b3247b84480c1fed5ca5ba46c25ecc25f68bfc9e6dcb1a6e9017dab5c7ada5eab73ad4f0a49d84e35093e0c643f2 - languageName: node - linkType: hard - -"minipass-sized@npm:^1.0.3": - version: 1.0.3 - resolution: "minipass-sized@npm:1.0.3" - dependencies: - minipass: "npm:^3.0.0" - checksum: 10c0/298f124753efdc745cfe0f2bdfdd81ba25b9f4e753ca4a2066eb17c821f25d48acea607dfc997633ee5bf7b6dfffb4eee4f2051eb168663f0b99fad2fa4829cb - languageName: node - linkType: hard - -"minipass@npm:^3.0.0": - version: 3.3.6 - resolution: "minipass@npm:3.3.6" - dependencies: - yallist: "npm:^4.0.0" - checksum: 10c0/a114746943afa1dbbca8249e706d1d38b85ed1298b530f5808ce51f8e9e941962e2a5ad2e00eae7dd21d8a4aae6586a66d4216d1a259385e9d0358f0c1eba16c - languageName: node - linkType: hard - -"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.0.4, minipass@npm:^7.1.2": - version: 7.1.2 - resolution: "minipass@npm:7.1.2" - checksum: 10c0/b0fd20bb9fb56e5fa9a8bfac539e8915ae07430a619e4b86ff71f5fc757ef3924b23b2c4230393af1eda647ed3d75739e4e0acb250a6b1eb277cf7f8fe449557 - languageName: node - linkType: hard - -"minizlib@npm:^3.0.1": - version: 3.0.2 - resolution: "minizlib@npm:3.0.2" - dependencies: - minipass: "npm:^7.1.2" - checksum: 10c0/9f3bd35e41d40d02469cb30470c55ccc21cae0db40e08d1d0b1dff01cc8cc89a6f78e9c5d2b7c844e485ec0a8abc2238111213fdc5b2038e6d1012eacf316f78 - languageName: node - linkType: hard - -"mkdirp@npm:^3.0.1": - version: 3.0.1 - resolution: "mkdirp@npm:3.0.1" - bin: - mkdirp: dist/cjs/src/bin.js - checksum: 10c0/9f2b975e9246351f5e3a40dcfac99fcd0baa31fbfab615fe059fb11e51f10e4803c63de1f384c54d656e4db31d000e4767e9ef076a22e12a641357602e31d57d - languageName: node - linkType: hard - -"mnemonist@npm:^0.38.0": - version: 0.38.5 - resolution: "mnemonist@npm:0.38.5" - dependencies: - obliterator: "npm:^2.0.0" - checksum: 10c0/a73a2718f88cd12c3b108ecc530619a1b0f2783d479c7f98e7367375102cc3a28811bab384e17eb731553dc8d7ee9d60283d694a9f676af5f306104e75027d4f - languageName: node - linkType: hard - -"mocha@npm:^10.0.0": - version: 10.8.2 - resolution: "mocha@npm:10.8.2" - dependencies: - ansi-colors: "npm:^4.1.3" - browser-stdout: "npm:^1.3.1" - chokidar: "npm:^3.5.3" - debug: "npm:^4.3.5" - diff: "npm:^5.2.0" - escape-string-regexp: "npm:^4.0.0" - find-up: "npm:^5.0.0" - glob: "npm:^8.1.0" - he: "npm:^1.2.0" - js-yaml: "npm:^4.1.0" - log-symbols: "npm:^4.1.0" - minimatch: "npm:^5.1.6" - ms: "npm:^2.1.3" - serialize-javascript: "npm:^6.0.2" - strip-json-comments: "npm:^3.1.1" - supports-color: "npm:^8.1.1" - workerpool: "npm:^6.5.1" - yargs: "npm:^16.2.0" - yargs-parser: "npm:^20.2.9" - yargs-unparser: "npm:^2.0.0" - bin: - _mocha: bin/_mocha - mocha: bin/mocha.js - checksum: 10c0/1f786290a32a1c234f66afe2bfcc68aa50fe9c7356506bd39cca267efb0b4714a63a0cb333815578d63785ba2fba058bf576c2512db73997c0cae0d659a88beb - languageName: node - linkType: hard - -"module-error@npm:^1.0.1": - version: 1.0.2 - resolution: "module-error@npm:1.0.2" - checksum: 10c0/584a43a1bb2720c6c6c771e257a308af4f042a17c17b1472a2c855130a1ad93ba516a82ae7ac2ce2d03062e521cc53c03ec0ce153795d895312d7747fb3bb99b - languageName: node - linkType: hard - -"ms@npm:^2.1.3": - version: 2.1.3 - resolution: "ms@npm:2.1.3" - checksum: 10c0/d924b57e7312b3b63ad21fc5b3dc0af5e78d61a1fc7cfb5457edaf26326bf62be5307cc87ffb6862ef1c2b33b0233cdb5d4f01c4c958cc0d660948b65a287a48 - languageName: node - linkType: hard - -"napi-macros@npm:~2.0.0": - version: 2.0.0 - resolution: "napi-macros@npm:2.0.0" - checksum: 10c0/583ef5084b43e49a12488cdcd4c5142f11e114e249b359161579b64f06776ed523c209d96e4ee2689e2e824c92445d0f529d817cc153f7cec549210296ec4be6 - languageName: node - linkType: hard - -"negotiator@npm:^1.0.0": - version: 1.0.0 - resolution: "negotiator@npm:1.0.0" - checksum: 10c0/4c559dd52669ea48e1914f9d634227c561221dd54734070791f999c52ed0ff36e437b2e07d5c1f6e32909fc625fe46491c16e4a8f0572567d4dd15c3a4fda04b - languageName: node - linkType: hard - -"node-addon-api@npm:^2.0.0": - version: 2.0.2 - resolution: "node-addon-api@npm:2.0.2" - dependencies: - node-gyp: "npm:latest" - checksum: 10c0/ade6c097ba829fa4aee1ca340117bb7f8f29fdae7b777e343a9d5cbd548481d1f0894b7b907d23ce615c70d932e8f96154caed95c3fa935cfe8cf87546510f64 - languageName: node - linkType: hard - -"node-fetch@npm:^2.7.0": - version: 2.7.0 - resolution: "node-fetch@npm:2.7.0" - dependencies: - whatwg-url: "npm:^5.0.0" - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true - checksum: 10c0/b55786b6028208e6fbe594ccccc213cab67a72899c9234eb59dba51062a299ea853210fcf526998eaa2867b0963ad72338824450905679ff0fa304b8c5093ae8 - languageName: node - linkType: hard - -"node-gyp-build@npm:4.4.0": - version: 4.4.0 - resolution: "node-gyp-build@npm:4.4.0" - bin: - node-gyp-build: bin.js - node-gyp-build-optional: optional.js - node-gyp-build-test: build-test.js - checksum: 10c0/11bbec933352004c6a754c9d2e3ac7ad02a09750cd06800fdcfdf111638bd897767ab94b7ed386ceaa155bb195ca8404037d7e79c2cbe7e9cd38ec74e5f5b5d2 - languageName: node - linkType: hard - -"node-gyp-build@npm:^4.2.0, node-gyp-build@npm:^4.3.0": - version: 4.8.0 - resolution: "node-gyp-build@npm:4.8.0" - bin: - node-gyp-build: bin.js - node-gyp-build-optional: optional.js - node-gyp-build-test: build-test.js - checksum: 10c0/85324be16f81f0235cbbc42e3eceaeb1b5ab94c8d8f5236755e1435b4908338c65a4e75f66ee343cbcb44ddf9b52a428755bec16dcd983295be4458d95c8e1ad - languageName: node - linkType: hard - -"node-gyp@npm:latest": - version: 11.4.2 - resolution: "node-gyp@npm:11.4.2" - dependencies: - env-paths: "npm:^2.2.0" - exponential-backoff: "npm:^3.1.1" - graceful-fs: "npm:^4.2.6" - make-fetch-happen: "npm:^14.0.3" - nopt: "npm:^8.0.0" - proc-log: "npm:^5.0.0" - semver: "npm:^7.3.5" - tar: "npm:^7.4.3" - tinyglobby: "npm:^0.2.12" - which: "npm:^5.0.0" - bin: - node-gyp: bin/node-gyp.js - checksum: 10c0/0bfd3e96770ed70f07798d881dd37b4267708966d868a0e585986baac487d9cf5831285579fd629a83dc4e434f53e6416ce301097f2ee464cb74d377e4d8bdbe - languageName: node - linkType: hard - -"nopt@npm:^8.0.0": - version: 8.1.0 - resolution: "nopt@npm:8.1.0" - dependencies: - abbrev: "npm:^3.0.0" - bin: - nopt: bin/nopt.js - checksum: 10c0/62e9ea70c7a3eb91d162d2c706b6606c041e4e7b547cbbb48f8b3695af457dd6479904d7ace600856bf923dd8d1ed0696f06195c8c20f02ac87c1da0e1d315ef - languageName: node - linkType: hard - -"normalize-path@npm:^3.0.0, normalize-path@npm:~3.0.0": - version: 3.0.0 - resolution: "normalize-path@npm:3.0.0" - checksum: 10c0/e008c8142bcc335b5e38cf0d63cfd39d6cf2d97480af9abdbe9a439221fd4d749763bab492a8ee708ce7a194bb00c9da6d0a115018672310850489137b3da046 - languageName: node - linkType: hard - -"obliterator@npm:^2.0.0": - version: 2.0.5 - resolution: "obliterator@npm:2.0.5" - checksum: 10c0/36e67d88271c51aa6412a7d449d6c60ae6387176f94dbc557eea67456bf6ccedbcbcecdb1e56438aa4f4694f68f531b3bf2be87b019e2f69961b144bec124e70 - languageName: node - linkType: hard - -"once@npm:^1.3.0": - version: 1.4.0 - resolution: "once@npm:1.4.0" - dependencies: - wrappy: "npm:1" - checksum: 10c0/5d48aca287dfefabd756621c5dfce5c91a549a93e9fdb7b8246bc4c4790aa2ec17b34a260530474635147aeb631a2dcc8b32c613df0675f96041cbb8244517d0 - languageName: node - linkType: hard - -"os-tmpdir@npm:~1.0.2": - version: 1.0.2 - resolution: "os-tmpdir@npm:1.0.2" - checksum: 10c0/f438450224f8e2687605a8dd318f0db694b6293c5d835ae509a69e97c8de38b6994645337e5577f5001115470414638978cc49da1cdcc25106dad8738dc69990 - languageName: node - linkType: hard - -"p-limit@npm:^3.0.2": - version: 3.1.0 - resolution: "p-limit@npm:3.1.0" - dependencies: - yocto-queue: "npm:^0.1.0" - checksum: 10c0/9db675949dbdc9c3763c89e748d0ef8bdad0afbb24d49ceaf4c46c02c77d30db4e0652ed36d0a0a7a95154335fab810d95c86153105bb73b3a90448e2bb14e1a - languageName: node - linkType: hard - -"p-locate@npm:^5.0.0": - version: 5.0.0 - resolution: "p-locate@npm:5.0.0" - dependencies: - p-limit: "npm:^3.0.2" - checksum: 10c0/2290d627ab7903b8b70d11d384fee714b797f6040d9278932754a6860845c4d3190603a0772a663c8cb5a7b21d1b16acb3a6487ebcafa9773094edc3dfe6009a - languageName: node - linkType: hard - -"p-map@npm:^4.0.0": - version: 4.0.0 - resolution: "p-map@npm:4.0.0" - dependencies: - aggregate-error: "npm:^3.0.0" - checksum: 10c0/592c05bd6262c466ce269ff172bb8de7c6975afca9b50c975135b974e9bdaafbfe80e61aaaf5be6d1200ba08b30ead04b88cfa7e25ff1e3b93ab28c9f62a2c75 - languageName: node - linkType: hard - -"p-map@npm:^7.0.2": - version: 7.0.3 - resolution: "p-map@npm:7.0.3" - checksum: 10c0/46091610da2b38ce47bcd1d8b4835a6fa4e832848a6682cf1652bc93915770f4617afc844c10a77d1b3e56d2472bb2d5622353fa3ead01a7f42b04fc8e744a5c - languageName: node - linkType: hard - -"package-json-from-dist@npm:^1.0.0": - version: 1.0.1 - resolution: "package-json-from-dist@npm:1.0.1" - checksum: 10c0/62ba2785eb655fec084a257af34dbe24292ab74516d6aecef97ef72d4897310bc6898f6c85b5cd22770eaa1ce60d55a0230e150fb6a966e3ecd6c511e23d164b - languageName: node - linkType: hard - -"path-exists@npm:^4.0.0": - version: 4.0.0 - resolution: "path-exists@npm:4.0.0" - checksum: 10c0/8c0bd3f5238188197dc78dced15207a4716c51cc4e3624c44fc97acf69558f5ebb9a2afff486fe1b4ee148e0c133e96c5e11a9aa5c48a3006e3467da070e5e1b - languageName: node - linkType: hard - -"path-key@npm:^3.1.0": - version: 3.1.1 - resolution: "path-key@npm:3.1.1" - checksum: 10c0/748c43efd5a569c039d7a00a03b58eecd1d75f3999f5a28303d75f521288df4823bc057d8784eb72358b2895a05f29a070bc9f1f17d28226cc4e62494cc58c4c - languageName: node - linkType: hard - -"path-parse@npm:^1.0.6": - version: 1.0.7 - resolution: "path-parse@npm:1.0.7" - checksum: 10c0/11ce261f9d294cc7a58d6a574b7f1b935842355ec66fba3c3fd79e0f036462eaf07d0aa95bb74ff432f9afef97ce1926c720988c6a7451d8a584930ae7de86e1 - languageName: node - linkType: hard - -"path-scurry@npm:^1.11.1": - version: 1.11.1 - resolution: "path-scurry@npm:1.11.1" - dependencies: - lru-cache: "npm:^10.2.0" - minipass: "npm:^5.0.0 || ^6.0.2 || ^7.0.0" - checksum: 10c0/32a13711a2a505616ae1cc1b5076801e453e7aae6ac40ab55b388bb91b9d0547a52f5aaceff710ea400205f18691120d4431e520afbe4266b836fadede15872d - languageName: node - linkType: hard - -"picocolors@npm:^1.1.0": - version: 1.1.1 - resolution: "picocolors@npm:1.1.1" - checksum: 10c0/e2e3e8170ab9d7c7421969adaa7e1b31434f789afb9b3f115f6b96d91945041ac3ceb02e9ec6fe6510ff036bcc0bf91e69a1772edc0b707e12b19c0f2d6bcf58 - languageName: node - linkType: hard - -"picomatch@npm:^2.0.4, picomatch@npm:^2.2.1": - version: 2.3.1 - resolution: "picomatch@npm:2.3.1" - checksum: 10c0/26c02b8d06f03206fc2ab8d16f19960f2ff9e81a658f831ecb656d8f17d9edc799e8364b1f4a7873e89d9702dff96204be0fa26fe4181f6843f040f819dac4be - languageName: node - linkType: hard - -"picomatch@npm:^4.0.2": - version: 4.0.2 - resolution: "picomatch@npm:4.0.2" - checksum: 10c0/7c51f3ad2bb42c776f49ebf964c644958158be30d0a510efd5a395e8d49cb5acfed5b82c0c5b365523ce18e6ab85013c9ebe574f60305892ec3fa8eee8304ccc - languageName: node - linkType: hard - -"picomatch@npm:^4.0.3": - version: 4.0.3 - resolution: "picomatch@npm:4.0.3" - checksum: 10c0/9582c951e95eebee5434f59e426cddd228a7b97a0161a375aed4be244bd3fe8e3a31b846808ea14ef2c8a2527a6eeab7b3946a67d5979e81694654f939473ae2 - languageName: node - linkType: hard - -"possible-typed-array-names@npm:^1.0.0": - version: 1.1.0 - resolution: "possible-typed-array-names@npm:1.1.0" - checksum: 10c0/c810983414142071da1d644662ce4caebce890203eb2bc7bf119f37f3fe5796226e117e6cca146b521921fa6531072674174a3325066ac66fce089a53e1e5196 - languageName: node - linkType: hard - -"proc-log@npm:^5.0.0": - version: 5.0.0 - resolution: "proc-log@npm:5.0.0" - checksum: 10c0/bbe5edb944b0ad63387a1d5b1911ae93e05ce8d0f60de1035b218cdcceedfe39dbd2c697853355b70f1a090f8f58fe90da487c85216bf9671f9499d1a897e9e3 - languageName: node - linkType: hard - -"promise-retry@npm:^2.0.1": - version: 2.0.1 - resolution: "promise-retry@npm:2.0.1" - dependencies: - err-code: "npm:^2.0.2" - retry: "npm:^0.12.0" - checksum: 10c0/9c7045a1a2928094b5b9b15336dcd2a7b1c052f674550df63cc3f36cd44028e5080448175b6f6ca32b642de81150f5e7b1a98b728f15cb069f2dd60ac2616b96 - languageName: node - linkType: hard - -"queue-microtask@npm:^1.2.3": - version: 1.2.3 - resolution: "queue-microtask@npm:1.2.3" - checksum: 10c0/900a93d3cdae3acd7d16f642c29a642aea32c2026446151f0778c62ac089d4b8e6c986811076e1ae180a694cedf077d453a11b58ff0a865629a4f82ab558e102 - languageName: node - linkType: hard - -"randombytes@npm:^2.1.0": - version: 2.1.0 - resolution: "randombytes@npm:2.1.0" - dependencies: - safe-buffer: "npm:^5.1.0" - checksum: 10c0/50395efda7a8c94f5dffab564f9ff89736064d32addf0cc7e8bf5e4166f09f8ded7a0849ca6c2d2a59478f7d90f78f20d8048bca3cdf8be09d8e8a10790388f3 - languageName: node - linkType: hard - -"raw-body@npm:^2.4.1": - version: 2.5.2 - resolution: "raw-body@npm:2.5.2" - dependencies: - bytes: "npm:3.1.2" - http-errors: "npm:2.0.0" - iconv-lite: "npm:0.4.24" - unpipe: "npm:1.0.0" - checksum: 10c0/b201c4b66049369a60e766318caff5cb3cc5a900efd89bdac431463822d976ad0670912c931fdbdcf5543207daf6f6833bca57aa116e1661d2ea91e12ca692c4 - languageName: node - linkType: hard - -"readable-stream@npm:^3.6.0": - version: 3.6.2 - resolution: "readable-stream@npm:3.6.2" - dependencies: - inherits: "npm:^2.0.3" - string_decoder: "npm:^1.1.1" - util-deprecate: "npm:^1.0.1" - checksum: 10c0/e37be5c79c376fdd088a45fa31ea2e423e5d48854be7a22a58869b4e84d25047b193f6acb54f1012331e1bcd667ffb569c01b99d36b0bd59658fb33f513511b7 - languageName: node - linkType: hard - -"readdirp@npm:^4.0.1": - version: 4.1.2 - resolution: "readdirp@npm:4.1.2" - checksum: 10c0/60a14f7619dec48c9c850255cd523e2717001b0e179dc7037cfa0895da7b9e9ab07532d324bfb118d73a710887d1e35f79c495fa91582784493e085d18c72c62 - languageName: node - linkType: hard - -"readdirp@npm:~3.6.0": - version: 3.6.0 - resolution: "readdirp@npm:3.6.0" - dependencies: - picomatch: "npm:^2.2.1" - checksum: 10c0/6fa848cf63d1b82ab4e985f4cf72bd55b7dcfd8e0a376905804e48c3634b7e749170940ba77b32804d5fe93b3cc521aa95a8d7e7d725f830da6d93f3669ce66b - languageName: node - linkType: hard - -"require-directory@npm:^2.1.1": - version: 2.1.1 - resolution: "require-directory@npm:2.1.1" - checksum: 10c0/83aa76a7bc1531f68d92c75a2ca2f54f1b01463cb566cf3fbc787d0de8be30c9dbc211d1d46be3497dac5785fe296f2dd11d531945ac29730643357978966e99 - languageName: node - linkType: hard - -"resolve-pkg-maps@npm:^1.0.0": - version: 1.0.0 - resolution: "resolve-pkg-maps@npm:1.0.0" - checksum: 10c0/fb8f7bbe2ca281a73b7ef423a1cbc786fb244bd7a95cbe5c3fba25b27d327150beca8ba02f622baea65919a57e061eb5005204daa5f93ed590d9b77463a567ab - languageName: node - linkType: hard - -"resolve@npm:1.17.0": - version: 1.17.0 - resolution: "resolve@npm:1.17.0" - dependencies: - path-parse: "npm:^1.0.6" - checksum: 10c0/4e6c76cc1a7b08bff637b092ce035d7901465067915605bc5a23ac0c10fe42ec205fc209d5d5f7a5f27f37ce71d687def7f656bbb003631cd46a8374f55ec73d - languageName: node - linkType: hard - -"resolve@patch:resolve@npm%3A1.17.0#optional!builtin": - version: 1.17.0 - resolution: "resolve@patch:resolve@npm%3A1.17.0#optional!builtin::version=1.17.0&hash=c3c19d" - dependencies: - path-parse: "npm:^1.0.6" - checksum: 10c0/e072e52be3c3dbfd086761115db4a5136753e7aefc0e665e66e7307ddcd9d6b740274516055c74aee44921625e95993f03570450aa310b8d73b1c9daa056c4cd - languageName: node - linkType: hard - -"retry@npm:^0.12.0": - version: 0.12.0 - resolution: "retry@npm:0.12.0" - checksum: 10c0/59933e8501727ba13ad73ef4a04d5280b3717fd650408460c987392efe9d7be2040778ed8ebe933c5cbd63da3dcc37919c141ef8af0a54a6e4fca5a2af177bfe - languageName: node - linkType: hard - -"safe-buffer@npm:^5.1.0, safe-buffer@npm:~5.2.0": - version: 5.2.1 - resolution: "safe-buffer@npm:5.2.1" - checksum: 10c0/6501914237c0a86e9675d4e51d89ca3c21ffd6a31642efeba25ad65720bce6921c9e7e974e5be91a786b25aa058b5303285d3c15dbabf983a919f5f630d349f3 - languageName: node - linkType: hard - -"safe-regex-test@npm:^1.1.0": - version: 1.1.0 - resolution: "safe-regex-test@npm:1.1.0" - dependencies: - call-bound: "npm:^1.0.2" - es-errors: "npm:^1.3.0" - is-regex: "npm:^1.2.1" - checksum: 10c0/f2c25281bbe5d39cddbbce7f86fca5ea9b3ce3354ea6cd7c81c31b006a5a9fff4286acc5450a3b9122c56c33eba69c56b9131ad751457b2b4a585825e6a10665 - languageName: node - linkType: hard - -"safer-buffer@npm:>= 2.1.2 < 3, safer-buffer@npm:>= 2.1.2 < 3.0.0": - version: 2.1.2 - resolution: "safer-buffer@npm:2.1.2" - checksum: 10c0/7e3c8b2e88a1841c9671094bbaeebd94448111dd90a81a1f606f3f67708a6ec57763b3b47f06da09fc6054193e0e6709e77325415dc8422b04497a8070fa02d4 - languageName: node - linkType: hard - -"scripts@workspace:.": - version: 0.0.0-use.local - resolution: "scripts@workspace:." - dependencies: - "@lido-js/ganache": "npm:=7.9.2-lido" - bignumber.js: "npm:^9.3.0" - hardhat: "npm:^2.24.1" - tsx: "npm:^4.19.4" - web3: "npm:^4.16.0" - languageName: unknown - linkType: soft - -"secp256k1@npm:4.0.3": - version: 4.0.3 - resolution: "secp256k1@npm:4.0.3" - dependencies: - elliptic: "npm:^6.5.4" - node-addon-api: "npm:^2.0.0" - node-gyp: "npm:latest" - node-gyp-build: "npm:^4.2.0" - checksum: 10c0/de0a0e525a6f8eb2daf199b338f0797dbfe5392874285a145bb005a72cabacb9d42c0197d0de129a1a0f6094d2cc4504d1f87acb6a8bbfb7770d4293f252c401 - languageName: node - linkType: hard - -"semver@npm:^5.5.0": - version: 5.7.2 - resolution: "semver@npm:5.7.2" - bin: - semver: bin/semver - checksum: 10c0/e4cf10f86f168db772ae95d86ba65b3fd6c5967c94d97c708ccb463b778c2ee53b914cd7167620950fc07faf5a564e6efe903836639e512a1aa15fbc9667fa25 - languageName: node - linkType: hard - -"semver@npm:^6.3.0": - version: 6.3.1 - resolution: "semver@npm:6.3.1" - bin: - semver: bin/semver.js - checksum: 10c0/e3d79b609071caa78bcb6ce2ad81c7966a46a7431d9d58b8800cfa9cb6a63699b3899a0e4bcce36167a284578212d9ae6942b6929ba4aa5015c079a67751d42d - languageName: node - linkType: hard - -"semver@npm:^7.3.5": - version: 7.7.2 - resolution: "semver@npm:7.7.2" - bin: - semver: bin/semver.js - checksum: 10c0/aca305edfbf2383c22571cb7714f48cadc7ac95371b4b52362fb8eeffdfbc0de0669368b82b2b15978f8848f01d7114da65697e56cd8c37b0dab8c58e543f9ea - languageName: node - linkType: hard - -"serialize-javascript@npm:^6.0.2": - version: 6.0.2 - resolution: "serialize-javascript@npm:6.0.2" - dependencies: - randombytes: "npm:^2.1.0" - checksum: 10c0/2dd09ef4b65a1289ba24a788b1423a035581bef60817bea1f01eda8e3bda623f86357665fe7ac1b50f6d4f583f97db9615b3f07b2a2e8cbcb75033965f771dd2 - languageName: node - linkType: hard - -"set-function-length@npm:^1.2.2": - version: 1.2.2 - resolution: "set-function-length@npm:1.2.2" - dependencies: - define-data-property: "npm:^1.1.4" - es-errors: "npm:^1.3.0" - function-bind: "npm:^1.1.2" - get-intrinsic: "npm:^1.2.4" - gopd: "npm:^1.0.1" - has-property-descriptors: "npm:^1.0.2" - checksum: 10c0/82850e62f412a258b71e123d4ed3873fa9377c216809551192bb6769329340176f109c2eeae8c22a8d386c76739855f78e8716515c818bcaef384b51110f0f3c - languageName: node - linkType: hard - -"setimmediate@npm:^1.0.5": - version: 1.0.5 - resolution: "setimmediate@npm:1.0.5" - checksum: 10c0/5bae81bfdbfbd0ce992893286d49c9693c82b1bcc00dcaaf3a09c8f428fdeacf4190c013598b81875dfac2b08a572422db7df779a99332d0fce186d15a3e4d49 - languageName: node - linkType: hard - -"setprototypeof@npm:1.2.0": - version: 1.2.0 - resolution: "setprototypeof@npm:1.2.0" - checksum: 10c0/68733173026766fa0d9ecaeb07f0483f4c2dc70ca376b3b7c40b7cda909f94b0918f6c5ad5ce27a9160bdfb475efaa9d5e705a11d8eaae18f9835d20976028bc - languageName: node - linkType: hard - -"shebang-command@npm:^2.0.0": - version: 2.0.0 - resolution: "shebang-command@npm:2.0.0" - dependencies: - shebang-regex: "npm:^3.0.0" - checksum: 10c0/a41692e7d89a553ef21d324a5cceb5f686d1f3c040759c50aab69688634688c5c327f26f3ecf7001ebfd78c01f3c7c0a11a7c8bfd0a8bc9f6240d4f40b224e4e - languageName: node - linkType: hard - -"shebang-regex@npm:^3.0.0": - version: 3.0.0 - resolution: "shebang-regex@npm:3.0.0" - checksum: 10c0/1dbed0726dd0e1152a92696c76c7f06084eb32a90f0528d11acd764043aacf76994b2fb30aa1291a21bd019d6699164d048286309a278855ee7bec06cf6fb690 - languageName: node - linkType: hard - -"signal-exit@npm:^4.0.1": - version: 4.1.0 - resolution: "signal-exit@npm:4.1.0" - checksum: 10c0/41602dce540e46d599edba9d9860193398d135f7ff72cab629db5171516cfae628d21e7bfccde1bbfdf11c48726bc2a6d1a8fb8701125852fbfda7cf19c6aa83 - languageName: node - linkType: hard - -"smart-buffer@npm:^4.2.0": - version: 4.2.0 - resolution: "smart-buffer@npm:4.2.0" - checksum: 10c0/a16775323e1404dd43fabafe7460be13a471e021637bc7889468eb45ce6a6b207261f454e4e530a19500cc962c4cc5348583520843b363f4193cee5c00e1e539 - languageName: node - linkType: hard - -"socks-proxy-agent@npm:^8.0.3": - version: 8.0.5 - resolution: "socks-proxy-agent@npm:8.0.5" - dependencies: - agent-base: "npm:^7.1.2" - debug: "npm:^4.3.4" - socks: "npm:^2.8.3" - checksum: 10c0/5d2c6cecba6821389aabf18728325730504bf9bb1d9e342e7987a5d13badd7a98838cc9a55b8ed3cb866ad37cc23e1086f09c4d72d93105ce9dfe76330e9d2a6 - languageName: node - linkType: hard - -"socks@npm:^2.8.3": - version: 2.8.7 - resolution: "socks@npm:2.8.7" - dependencies: - ip-address: "npm:^10.0.1" - smart-buffer: "npm:^4.2.0" - checksum: 10c0/2805a43a1c4bcf9ebf6e018268d87b32b32b06fbbc1f9282573583acc155860dc361500f89c73bfbb157caa1b4ac78059eac0ef15d1811eb0ca75e0bdadbc9d2 - languageName: node - linkType: hard - -"solc@npm:0.8.26": - version: 0.8.26 - resolution: "solc@npm:0.8.26" - dependencies: - command-exists: "npm:^1.2.8" - commander: "npm:^8.1.0" - follow-redirects: "npm:^1.12.1" - js-sha3: "npm:0.8.0" - memorystream: "npm:^0.3.1" - semver: "npm:^5.5.0" - tmp: "npm:0.0.33" - bin: - solcjs: solc.js - checksum: 10c0/1eea35da99c228d0dc1d831c29f7819e7921b67824c889a5e5f2e471a2ef5856a15fabc0b5de067f5ba994fa36fb5a563361963646fe98dad58a0e4fa17c8b2d - languageName: node - linkType: hard - -"source-map-support@npm:^0.5.13": - version: 0.5.21 - resolution: "source-map-support@npm:0.5.21" - dependencies: - buffer-from: "npm:^1.0.0" - source-map: "npm:^0.6.0" - checksum: 10c0/9ee09942f415e0f721d6daad3917ec1516af746a8120bba7bb56278707a37f1eb8642bde456e98454b8a885023af81a16e646869975f06afc1a711fb90484e7d - languageName: node - linkType: hard - -"source-map@npm:^0.6.0": - version: 0.6.1 - resolution: "source-map@npm:0.6.1" - checksum: 10c0/ab55398007c5e5532957cb0beee2368529618ac0ab372d789806f5718123cc4367d57de3904b4e6a4170eb5a0b0f41373066d02ca0735a0c4d75c7d328d3e011 - languageName: node - linkType: hard - -"ssri@npm:^12.0.0": - version: 12.0.0 - resolution: "ssri@npm:12.0.0" - dependencies: - minipass: "npm:^7.0.3" - checksum: 10c0/caddd5f544b2006e88fa6b0124d8d7b28208b83c72d7672d5ade44d794525d23b540f3396108c4eb9280dcb7c01f0bef50682f5b4b2c34291f7c5e211fd1417d - languageName: node - linkType: hard - -"stacktrace-parser@npm:^0.1.10": - version: 0.1.11 - resolution: "stacktrace-parser@npm:0.1.11" - dependencies: - type-fest: "npm:^0.7.1" - checksum: 10c0/4633d9afe8cd2f6c7fb2cebdee3cc8de7fd5f6f9736645fd08c0f66872a303061ce9cc0ccf46f4216dc94a7941b56e331012398dc0024dc25e46b5eb5d4ff018 - languageName: node - linkType: hard - -"statuses@npm:2.0.1": - version: 2.0.1 - resolution: "statuses@npm:2.0.1" - checksum: 10c0/34378b207a1620a24804ce8b5d230fea0c279f00b18a7209646d5d47e419d1cc23e7cbf33a25a1e51ac38973dc2ac2e1e9c647a8e481ef365f77668d72becfd0 - languageName: node - linkType: hard - -"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^4.0.0, string-width@npm:^4.1.0, string-width@npm:^4.2.0, string-width@npm:^4.2.2": - version: 4.2.3 - resolution: "string-width@npm:4.2.3" - dependencies: - emoji-regex: "npm:^8.0.0" - is-fullwidth-code-point: "npm:^3.0.0" - strip-ansi: "npm:^6.0.1" - checksum: 10c0/1e525e92e5eae0afd7454086eed9c818ee84374bb80328fc41217ae72ff5f065ef1c9d7f72da41de40c75fa8bb3dee63d92373fd492c84260a552c636392a47b - languageName: node - linkType: hard - -"string-width@npm:^5.0.1, string-width@npm:^5.1.2": - version: 5.1.2 - resolution: "string-width@npm:5.1.2" - dependencies: - eastasianwidth: "npm:^0.2.0" - emoji-regex: "npm:^9.2.2" - strip-ansi: "npm:^7.0.1" - checksum: 10c0/ab9c4264443d35b8b923cbdd513a089a60de339216d3b0ed3be3ba57d6880e1a192b70ae17225f764d7adbf5994e9bb8df253a944736c15a0240eff553c678ca - languageName: node - linkType: hard - -"string_decoder@npm:^1.1.1": - version: 1.3.0 - resolution: "string_decoder@npm:1.3.0" - dependencies: - safe-buffer: "npm:~5.2.0" - checksum: 10c0/810614ddb030e271cd591935dcd5956b2410dd079d64ff92a1844d6b7588bf992b3e1b69b0f4d34a3e06e0bd73046ac646b5264c1987b20d0601f81ef35d731d - languageName: node - linkType: hard - -"strip-ansi-cjs@npm:strip-ansi@^6.0.1, strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1": - version: 6.0.1 - resolution: "strip-ansi@npm:6.0.1" - dependencies: - ansi-regex: "npm:^5.0.1" - checksum: 10c0/1ae5f212a126fe5b167707f716942490e3933085a5ff6c008ab97ab2f272c8025d3aa218b7bd6ab25729ca20cc81cddb252102f8751e13482a5199e873680952 - languageName: node - linkType: hard - -"strip-ansi@npm:^7.0.1": - version: 7.1.2 - resolution: "strip-ansi@npm:7.1.2" - dependencies: - ansi-regex: "npm:^6.0.1" - checksum: 10c0/0d6d7a023de33368fd042aab0bf48f4f4077abdfd60e5393e73c7c411e85e1b3a83507c11af2e656188511475776215df9ca589b4da2295c9455cc399ce1858b - languageName: node - linkType: hard - -"strip-json-comments@npm:^3.1.1": - version: 3.1.1 - resolution: "strip-json-comments@npm:3.1.1" - checksum: 10c0/9681a6257b925a7fa0f285851c0e613cc934a50661fa7bb41ca9cbbff89686bb4a0ee366e6ecedc4daafd01e83eee0720111ab294366fe7c185e935475ebcecd - languageName: node - linkType: hard - -"supports-color@npm:^7.1.0": - version: 7.2.0 - resolution: "supports-color@npm:7.2.0" - dependencies: - has-flag: "npm:^4.0.0" - checksum: 10c0/afb4c88521b8b136b5f5f95160c98dee7243dc79d5432db7efc27efb219385bbc7d9427398e43dd6cc730a0f87d5085ce1652af7efbe391327bc0a7d0f7fc124 - languageName: node - linkType: hard - -"supports-color@npm:^8.1.1": - version: 8.1.1 - resolution: "supports-color@npm:8.1.1" - dependencies: - has-flag: "npm:^4.0.0" - checksum: 10c0/ea1d3c275dd604c974670f63943ed9bd83623edc102430c05adb8efc56ba492746b6e95386e7831b872ec3807fd89dd8eb43f735195f37b5ec343e4234cc7e89 - languageName: node - linkType: hard - -"tar@npm:^7.4.3": - version: 7.4.3 - resolution: "tar@npm:7.4.3" - dependencies: - "@isaacs/fs-minipass": "npm:^4.0.0" - chownr: "npm:^3.0.0" - minipass: "npm:^7.1.2" - minizlib: "npm:^3.0.1" - mkdirp: "npm:^3.0.1" - yallist: "npm:^5.0.0" - checksum: 10c0/d4679609bb2a9b48eeaf84632b6d844128d2412b95b6de07d53d8ee8baf4ca0857c9331dfa510390a0727b550fd543d4d1a10995ad86cdf078423fbb8d99831d - languageName: node - linkType: hard - -"tinyglobby@npm:^0.2.12": - version: 0.2.15 - resolution: "tinyglobby@npm:0.2.15" - dependencies: - fdir: "npm:^6.5.0" - picomatch: "npm:^4.0.3" - checksum: 10c0/869c31490d0d88eedb8305d178d4c75e7463e820df5a9b9d388291daf93e8b1eb5de1dad1c1e139767e4269fe75f3b10d5009b2cc14db96ff98986920a186844 - languageName: node - linkType: hard - -"tinyglobby@npm:^0.2.6": - version: 0.2.12 - resolution: "tinyglobby@npm:0.2.12" - dependencies: - fdir: "npm:^6.4.3" - picomatch: "npm:^4.0.2" - checksum: 10c0/7c9be4fd3625630e262dcb19015302aad3b4ba7fc620f269313e688f2161ea8724d6cb4444baab5ef2826eb6bed72647b169a33ec8eea37501832a2526ff540f - languageName: node - linkType: hard - -"tmp@npm:0.0.33": - version: 0.0.33 - resolution: "tmp@npm:0.0.33" - dependencies: - os-tmpdir: "npm:~1.0.2" - checksum: 10c0/69863947b8c29cabad43fe0ce65cec5bb4b481d15d4b4b21e036b060b3edbf3bc7a5541de1bacb437bb3f7c4538f669752627fdf9b4aaf034cebd172ba373408 - languageName: node - linkType: hard - -"to-regex-range@npm:^5.0.1": - version: 5.0.1 - resolution: "to-regex-range@npm:5.0.1" - dependencies: - is-number: "npm:^7.0.0" - checksum: 10c0/487988b0a19c654ff3e1961b87f471702e708fa8a8dd02a298ef16da7206692e8552a0250e8b3e8759270f62e9d8314616f6da274734d3b558b1fc7b7724e892 - languageName: node - linkType: hard - -"toidentifier@npm:1.0.1": - version: 1.0.1 - resolution: "toidentifier@npm:1.0.1" - checksum: 10c0/93937279934bd66cc3270016dd8d0afec14fb7c94a05c72dc57321f8bd1fa97e5bea6d1f7c89e728d077ca31ea125b78320a616a6c6cd0e6b9cb94cb864381c1 - languageName: node - linkType: hard - -"tr46@npm:~0.0.3": - version: 0.0.3 - resolution: "tr46@npm:0.0.3" - checksum: 10c0/047cb209a6b60c742f05c9d3ace8fa510bff609995c129a37ace03476a9b12db4dbf975e74600830ef0796e18882b2381fb5fb1f6b4f96b832c374de3ab91a11 - languageName: node - linkType: hard - -"tslib@npm:^1.9.3": - version: 1.14.1 - resolution: "tslib@npm:1.14.1" - checksum: 10c0/69ae09c49eea644bc5ebe1bca4fa4cc2c82b7b3e02f43b84bd891504edf66dbc6b2ec0eef31a957042de2269139e4acff911e6d186a258fb14069cd7f6febce2 - languageName: node - linkType: hard - -"tsort@npm:0.0.1": - version: 0.0.1 - resolution: "tsort@npm:0.0.1" - checksum: 10c0/ea3d034ab341dd9282c972710496e98539408d77f1cd476ad0551a9731f40586b65ab917b39745f902bf32037a3161eee3821405f6ab15bcd2ce4cc0a52d1da6 - languageName: node - linkType: hard - -"tsx@npm:^4.19.4": - version: 4.19.4 - resolution: "tsx@npm:4.19.4" - dependencies: - esbuild: "npm:~0.25.0" - fsevents: "npm:~2.3.3" - get-tsconfig: "npm:^4.7.5" - dependenciesMeta: - fsevents: - optional: true - bin: - tsx: dist/cli.mjs - checksum: 10c0/f7b8d44362343fbde1f2ecc9832d243a450e1168dd09702a545ebe5f699aa6912e45b431a54b885466db414cceda48e5067b36d182027c43b2c02a4f99d8721e - languageName: node - linkType: hard - -"type-fest@npm:^0.20.2": - version: 0.20.2 - resolution: "type-fest@npm:0.20.2" - checksum: 10c0/dea9df45ea1f0aaa4e2d3bed3f9a0bfe9e5b2592bddb92eb1bf06e50bcf98dbb78189668cd8bc31a0511d3fc25539b4cd5c704497e53e93e2d40ca764b10bfc3 - languageName: node - linkType: hard - -"type-fest@npm:^0.21.3": - version: 0.21.3 - resolution: "type-fest@npm:0.21.3" - checksum: 10c0/902bd57bfa30d51d4779b641c2bc403cdf1371fb9c91d3c058b0133694fcfdb817aef07a47f40faf79039eecbaa39ee9d3c532deff244f3a19ce68cea71a61e8 - languageName: node - linkType: hard - -"type-fest@npm:^0.7.1": - version: 0.7.1 - resolution: "type-fest@npm:0.7.1" - checksum: 10c0/ce6b5ef806a76bf08d0daa78d65e61f24d9a0380bd1f1df36ffb61f84d14a0985c3a921923cf4b97831278cb6fa9bf1b89c751df09407e0510b14e8c081e4e0f - languageName: node - linkType: hard - -"undici-types@npm:~5.26.4": - version: 5.26.5 - resolution: "undici-types@npm:5.26.5" - checksum: 10c0/bb673d7876c2d411b6eb6c560e0c571eef4a01c1c19925175d16e3a30c4c428181fb8d7ae802a261f283e4166a0ac435e2f505743aa9e45d893f9a3df017b501 - languageName: node - linkType: hard - -"undici@npm:^5.14.0": - version: 5.28.5 - resolution: "undici@npm:5.28.5" - dependencies: - "@fastify/busboy": "npm:^2.0.0" - checksum: 10c0/4dfaa13089fe4c0758f84ec0d34b257e58608e6be3aa540f493b9864b39e3fdcd0a1ace38e434fe79db55f833aa30bcfddd8d6cbe3e0982b0dcae8ec17b65e08 - languageName: node - linkType: hard - -"unique-filename@npm:^4.0.0": - version: 4.0.0 - resolution: "unique-filename@npm:4.0.0" - dependencies: - unique-slug: "npm:^5.0.0" - checksum: 10c0/38ae681cceb1408ea0587b6b01e29b00eee3c84baee1e41fd5c16b9ed443b80fba90c40e0ba69627e30855570a34ba8b06702d4a35035d4b5e198bf5a64c9ddc - languageName: node - linkType: hard - -"unique-slug@npm:^5.0.0": - version: 5.0.0 - resolution: "unique-slug@npm:5.0.0" - dependencies: - imurmurhash: "npm:^0.1.4" - checksum: 10c0/d324c5a44887bd7e105ce800fcf7533d43f29c48757ac410afd42975de82cc38ea2035c0483f4de82d186691bf3208ef35c644f73aa2b1b20b8e651be5afd293 - languageName: node - linkType: hard - -"universalify@npm:^0.1.0": - version: 0.1.2 - resolution: "universalify@npm:0.1.2" - checksum: 10c0/e70e0339f6b36f34c9816f6bf9662372bd241714dc77508d231d08386d94f2c4aa1ba1318614f92015f40d45aae1b9075cd30bd490efbe39387b60a76ca3f045 - languageName: node - linkType: hard - -"unpipe@npm:1.0.0": - version: 1.0.0 - resolution: "unpipe@npm:1.0.0" - checksum: 10c0/193400255bd48968e5c5383730344fbb4fa114cdedfab26e329e50dd2d81b134244bb8a72c6ac1b10ab0281a58b363d06405632c9d49ca9dfd5e90cbd7d0f32c - languageName: node - linkType: hard - -"utf-8-validate@npm:5.0.7": - version: 5.0.7 - resolution: "utf-8-validate@npm:5.0.7" - dependencies: - node-gyp: "npm:latest" - node-gyp-build: "npm:^4.3.0" - checksum: 10c0/1f343467b4509a37e4d8b06be527b78869a7a950fe039f24fad9bc5951208730227789c1f22665988124762e05a2080056a6cd68ba6bec5988c16ee30bfa9737 - languageName: node - linkType: hard - -"utf-8-validate@npm:6.0.3": - version: 6.0.3 - resolution: "utf-8-validate@npm:6.0.3" - dependencies: - node-gyp: "npm:latest" - node-gyp-build: "npm:^4.3.0" - checksum: 10c0/2ca08b07f4070540b33ff15f3f0632fa30baaee8a766fff993be47b4829b4fb30fd36fdf1270336324d03f65e0936c4608ee719d862230d75311751dcfe27a83 - languageName: node - linkType: hard - -"util-deprecate@npm:^1.0.1": - version: 1.0.2 - resolution: "util-deprecate@npm:1.0.2" - checksum: 10c0/41a5bdd214df2f6c3ecf8622745e4a366c4adced864bc3c833739791aeeeb1838119af7daed4ba36428114b5c67dcda034a79c882e97e43c03e66a4dd7389942 - languageName: node - linkType: hard - -"util@npm:^0.12.5": - version: 0.12.5 - resolution: "util@npm:0.12.5" - dependencies: - inherits: "npm:^2.0.3" - is-arguments: "npm:^1.0.4" - is-generator-function: "npm:^1.0.7" - is-typed-array: "npm:^1.1.3" - which-typed-array: "npm:^1.1.2" - checksum: 10c0/c27054de2cea2229a66c09522d0fa1415fb12d861d08523a8846bf2e4cbf0079d4c3f725f09dcb87493549bcbf05f5798dce1688b53c6c17201a45759e7253f3 - languageName: node - linkType: hard - -"uuid@npm:^8.3.2": - version: 8.3.2 - resolution: "uuid@npm:8.3.2" - bin: - uuid: dist/bin/uuid - checksum: 10c0/bcbb807a917d374a49f475fae2e87fdca7da5e5530820ef53f65ba1d12131bd81a92ecf259cc7ce317cbe0f289e7d79fdfebcef9bfa3087c8c8a2fa304c9be54 - languageName: node - linkType: hard - -"web3-core@npm:^4.4.0, web3-core@npm:^4.5.0, web3-core@npm:^4.6.0, web3-core@npm:^4.7.1": - version: 4.7.1 - resolution: "web3-core@npm:4.7.1" - dependencies: - web3-errors: "npm:^1.3.1" - web3-eth-accounts: "npm:^4.3.1" - web3-eth-iban: "npm:^4.0.7" - web3-providers-http: "npm:^4.2.0" - web3-providers-ipc: "npm:^4.0.7" - web3-providers-ws: "npm:^4.0.8" - web3-types: "npm:^1.10.0" - web3-utils: "npm:^4.3.3" - web3-validator: "npm:^2.0.6" - dependenciesMeta: - web3-providers-ipc: - optional: true - checksum: 10c0/803a55d46c21dc48c2ab478686ea5a264501b97b0b4f72fe27ba978d862ec61ac406fff5bfce0528044609a8e8fffb74fc0ff06277827a62667a66ef2ce750ac - languageName: node - linkType: hard - -"web3-errors@npm:^1.1.3, web3-errors@npm:^1.2.0, web3-errors@npm:^1.3.0, web3-errors@npm:^1.3.1": - version: 1.3.1 - resolution: "web3-errors@npm:1.3.1" - dependencies: - web3-types: "npm:^1.10.0" - checksum: 10c0/b763f0ae43c5c90f0fb72a0342a0d9227b68b363ab9d0b0c2948d586379129ec31b6da070c37393213022b34ed10374d3b16b86002c1280c637d3df4d29eed2a - languageName: node - linkType: hard - -"web3-eth-abi@npm:^4.4.1": - version: 4.4.1 - resolution: "web3-eth-abi@npm:4.4.1" - dependencies: - abitype: "npm:0.7.1" - web3-errors: "npm:^1.3.1" - web3-types: "npm:^1.10.0" - web3-utils: "npm:^4.3.3" - web3-validator: "npm:^2.0.6" - checksum: 10c0/fbaf2a6ef29dc8146a562a2d19823f20deb29f802abf0a82349863cb0ae884e564f756643fa76246717f89475088175e7d93fc813c24790911422e22e18e2fda - languageName: node - linkType: hard - -"web3-eth-accounts@npm:^4.3.1": - version: 4.3.1 - resolution: "web3-eth-accounts@npm:4.3.1" - dependencies: - "@ethereumjs/rlp": "npm:^4.0.1" - crc-32: "npm:^1.2.2" - ethereum-cryptography: "npm:^2.0.0" - web3-errors: "npm:^1.3.1" - web3-types: "npm:^1.10.0" - web3-utils: "npm:^4.3.3" - web3-validator: "npm:^2.0.6" - checksum: 10c0/efde89b171d75a212f05ce04e46c247001f7b747e2995df0d90c2459c703093ae6aa853356d62b2673735dad3eca5c81df44a1836fab5f0bfc80a64845652020 - languageName: node - linkType: hard - -"web3-eth-contract@npm:^4.5.0, web3-eth-contract@npm:^4.7.2": - version: 4.7.2 - resolution: "web3-eth-contract@npm:4.7.2" - dependencies: - "@ethereumjs/rlp": "npm:^5.0.2" - web3-core: "npm:^4.7.1" - web3-errors: "npm:^1.3.1" - web3-eth: "npm:^4.11.1" - web3-eth-abi: "npm:^4.4.1" - web3-types: "npm:^1.10.0" - web3-utils: "npm:^4.3.3" - web3-validator: "npm:^2.0.6" - checksum: 10c0/c119c7fb7dc32142e13816ace5775ecaeb33d0981edbba24e0648780e75e7fd24b855fd3096b618b9ade71514886eea9f919501ababb88cacc67136f51bcd0da - languageName: node - linkType: hard - -"web3-eth-ens@npm:^4.4.0": - version: 4.4.0 - resolution: "web3-eth-ens@npm:4.4.0" - dependencies: - "@adraffy/ens-normalize": "npm:^1.8.8" - web3-core: "npm:^4.5.0" - web3-errors: "npm:^1.2.0" - web3-eth: "npm:^4.8.0" - web3-eth-contract: "npm:^4.5.0" - web3-net: "npm:^4.1.0" - web3-types: "npm:^1.7.0" - web3-utils: "npm:^4.3.0" - web3-validator: "npm:^2.0.6" - checksum: 10c0/104f8d561dce462775a8bec529de6c91dde779f0ed0afe3116b33047352733f75240a46f7a02b39bdc66439f77ee9178fcb8812f9d614b7397dde4758787ae07 - languageName: node - linkType: hard - -"web3-eth-iban@npm:^4.0.7": - version: 4.0.7 - resolution: "web3-eth-iban@npm:4.0.7" - dependencies: - web3-errors: "npm:^1.1.3" - web3-types: "npm:^1.3.0" - web3-utils: "npm:^4.0.7" - web3-validator: "npm:^2.0.3" - checksum: 10c0/f1e74106afa40a662a9f2a8095a8d9fe76bbd011dfa00fdde5d759db6b99968771bb1d4afa810ff9bb38970db7b871c21869c786ae9bb4abaa2bf8298cfc0121 - languageName: node - linkType: hard - -"web3-eth-personal@npm:^4.1.0": - version: 4.1.0 - resolution: "web3-eth-personal@npm:4.1.0" - dependencies: - web3-core: "npm:^4.6.0" - web3-eth: "npm:^4.9.0" - web3-rpc-methods: "npm:^1.3.0" - web3-types: "npm:^1.8.0" - web3-utils: "npm:^4.3.1" - web3-validator: "npm:^2.0.6" - checksum: 10c0/203f59b33c7385d3e671a0645cbfc7f8ba56ab63bd6a0de9db42ec26e597cdc9ebf2e6a30586f3c0f27f9c09aa45d9cb77255c63c02d5905b180fb75c629cf80 - languageName: node - linkType: hard - -"web3-eth@npm:^4.11.1, web3-eth@npm:^4.8.0, web3-eth@npm:^4.9.0": - version: 4.11.1 - resolution: "web3-eth@npm:4.11.1" - dependencies: - setimmediate: "npm:^1.0.5" - web3-core: "npm:^4.7.1" - web3-errors: "npm:^1.3.1" - web3-eth-abi: "npm:^4.4.1" - web3-eth-accounts: "npm:^4.3.1" - web3-net: "npm:^4.1.0" - web3-providers-ws: "npm:^4.0.8" - web3-rpc-methods: "npm:^1.3.0" - web3-types: "npm:^1.10.0" - web3-utils: "npm:^4.3.3" - web3-validator: "npm:^2.0.6" - checksum: 10c0/139b7b59fdaf31884422a2cb06deb0de6e17e960d2952d7e06ff9690ff2db43f97c63109027dd529ba0103964827e2fc8aaa8c7f351ad8889429788fddbdf44f - languageName: node - linkType: hard - -"web3-net@npm:^4.1.0": - version: 4.1.0 - resolution: "web3-net@npm:4.1.0" - dependencies: - web3-core: "npm:^4.4.0" - web3-rpc-methods: "npm:^1.3.0" - web3-types: "npm:^1.6.0" - web3-utils: "npm:^4.3.0" - checksum: 10c0/17a70d941116e8d08a65109c447897121af39c74ed0e3ef61ec9833bf268b6e527507b8c0544852d0fe9e6964fe7731117640629b5a3ca562be4115b74f60acd - languageName: node - linkType: hard - -"web3-providers-http@npm:^4.2.0": - version: 4.2.0 - resolution: "web3-providers-http@npm:4.2.0" - dependencies: - cross-fetch: "npm:^4.0.0" - web3-errors: "npm:^1.3.0" - web3-types: "npm:^1.7.0" - web3-utils: "npm:^4.3.1" - checksum: 10c0/4541552fa48bc44c49a59ffd3c7d2ed5e3bf5bad0987bde95876aed4962fd74f2b8eb3b884fa6c7c43c493eb3febcb68f6f25be9867a9436aced618a9324eff5 - languageName: node - linkType: hard - -"web3-providers-ipc@npm:^4.0.7": - version: 4.0.7 - resolution: "web3-providers-ipc@npm:4.0.7" - dependencies: - web3-errors: "npm:^1.1.3" - web3-types: "npm:^1.3.0" - web3-utils: "npm:^4.0.7" - checksum: 10c0/3eb1db6514e8d9cf8d8d9e34d215deda6b68129df276bd0854ed16f01546d53a7ae2640d4788f9947ecd94ef9d2a905dd16b4d233f48712f7b9c4d1b4ffedc86 - languageName: node - linkType: hard - -"web3-providers-ws@npm:^4.0.8": - version: 4.0.8 - resolution: "web3-providers-ws@npm:4.0.8" - dependencies: - "@types/ws": "npm:8.5.3" - isomorphic-ws: "npm:^5.0.0" - web3-errors: "npm:^1.2.0" - web3-types: "npm:^1.7.0" - web3-utils: "npm:^4.3.1" - ws: "npm:^8.17.1" - checksum: 10c0/befbcab0cc2faf3376433dd8f18a080a5ce17e4b95bc1088179fb4409eeeebd01e715568aa67879161bb996944d5be2b53e6709d2d830243159b4f0144625bfa - languageName: node - linkType: hard - -"web3-rpc-methods@npm:^1.3.0": - version: 1.3.0 - resolution: "web3-rpc-methods@npm:1.3.0" - dependencies: - web3-core: "npm:^4.4.0" - web3-types: "npm:^1.6.0" - web3-validator: "npm:^2.0.6" - checksum: 10c0/28a3350de4a94c7773860cc960ea6d8afe73dc1cc368e0c455fb6a4e054178e649f3b426992612a860924b631fc015c5b8f58d583a9b3a6cd9a19d5481d8172f - languageName: node - linkType: hard - -"web3-rpc-providers@npm:^1.0.0-rc.4": - version: 1.0.0-rc.4 - resolution: "web3-rpc-providers@npm:1.0.0-rc.4" - dependencies: - web3-errors: "npm:^1.3.1" - web3-providers-http: "npm:^4.2.0" - web3-providers-ws: "npm:^4.0.8" - web3-types: "npm:^1.10.0" - web3-utils: "npm:^4.3.3" - web3-validator: "npm:^2.0.6" - checksum: 10c0/5f74e5f3c12c06348abf73180a9b9405d6148c4db22a3c34f825fb8fb48a9793a239256d539d885479897954f853b534b012abb89c10505cf4af3e40f74e8925 - languageName: node - linkType: hard - -"web3-types@npm:^1.10.0, web3-types@npm:^1.3.0, web3-types@npm:^1.6.0, web3-types@npm:^1.7.0, web3-types@npm:^1.8.0": - version: 1.10.0 - resolution: "web3-types@npm:1.10.0" - checksum: 10c0/e7238b48f62dd03a4eda2ca6d150f0ae7d02a0bede886b36316e57ee6535ccf9965ba938afc9dcbdd807696df782eff1a29658ed03a917d92f88798cf8db2bc7 - languageName: node - linkType: hard - -"web3-utils@npm:^4.0.7, web3-utils@npm:^4.3.0, web3-utils@npm:^4.3.1, web3-utils@npm:^4.3.3": - version: 4.3.3 - resolution: "web3-utils@npm:4.3.3" - dependencies: - ethereum-cryptography: "npm:^2.0.0" - eventemitter3: "npm:^5.0.1" - web3-errors: "npm:^1.3.1" - web3-types: "npm:^1.10.0" - web3-validator: "npm:^2.0.6" - checksum: 10c0/c56040d254ac168c4c3266ac00dbef3a16e81093cc7926e53d0c619d2c354818bc04f2b0475dd18cb60e6167262154b8bfd0540683c1f4c91045791ad2667963 - languageName: node - linkType: hard - -"web3-validator@npm:^2.0.3, web3-validator@npm:^2.0.6": - version: 2.0.6 - resolution: "web3-validator@npm:2.0.6" - dependencies: - ethereum-cryptography: "npm:^2.0.0" - util: "npm:^0.12.5" - web3-errors: "npm:^1.2.0" - web3-types: "npm:^1.6.0" - zod: "npm:^3.21.4" - checksum: 10c0/28728773b9abad2531f7a4145784db56ec9ecffeb25cc9f6fe67bedeb01a1833b1a5d1a2e0f431ce4a3c8c6f13b111f35202dd8fa0829c6e2fcd68c58d1d5658 - languageName: node - linkType: hard - -"web3@npm:^4.16.0": - version: 4.16.0 - resolution: "web3@npm:4.16.0" - dependencies: - web3-core: "npm:^4.7.1" - web3-errors: "npm:^1.3.1" - web3-eth: "npm:^4.11.1" - web3-eth-abi: "npm:^4.4.1" - web3-eth-accounts: "npm:^4.3.1" - web3-eth-contract: "npm:^4.7.2" - web3-eth-ens: "npm:^4.4.0" - web3-eth-iban: "npm:^4.0.7" - web3-eth-personal: "npm:^4.1.0" - web3-net: "npm:^4.1.0" - web3-providers-http: "npm:^4.2.0" - web3-providers-ws: "npm:^4.0.8" - web3-rpc-methods: "npm:^1.3.0" - web3-rpc-providers: "npm:^1.0.0-rc.4" - web3-types: "npm:^1.10.0" - web3-utils: "npm:^4.3.3" - web3-validator: "npm:^2.0.6" - checksum: 10c0/c8a80833f5ec69d69bf30fc0c77accbb7c5a74917fa66b21d40e2f889e38d4f8723ed39264170f742807c8dc418b05b34f7bd328b576af38a8b92e1308506087 - languageName: node - linkType: hard - -"webidl-conversions@npm:^3.0.0": - version: 3.0.1 - resolution: "webidl-conversions@npm:3.0.1" - checksum: 10c0/5612d5f3e54760a797052eb4927f0ddc01383550f542ccd33d5238cfd65aeed392a45ad38364970d0a0f4fea32e1f4d231b3d8dac4a3bdd385e5cf802ae097db - languageName: node - linkType: hard - -"whatwg-url@npm:^5.0.0": - version: 5.0.0 - resolution: "whatwg-url@npm:5.0.0" - dependencies: - tr46: "npm:~0.0.3" - webidl-conversions: "npm:^3.0.0" - checksum: 10c0/1588bed84d10b72d5eec1d0faa0722ba1962f1821e7539c535558fb5398d223b0c50d8acab950b8c488b4ba69043fd833cc2697056b167d8ad46fac3995a55d5 - languageName: node - linkType: hard - -"which-typed-array@npm:^1.1.16, which-typed-array@npm:^1.1.2": - version: 1.1.19 - resolution: "which-typed-array@npm:1.1.19" - dependencies: - available-typed-arrays: "npm:^1.0.7" - call-bind: "npm:^1.0.8" - call-bound: "npm:^1.0.4" - for-each: "npm:^0.3.5" - get-proto: "npm:^1.0.1" - gopd: "npm:^1.2.0" - has-tostringtag: "npm:^1.0.2" - checksum: 10c0/702b5dc878addafe6c6300c3d0af5983b175c75fcb4f2a72dfc3dd38d93cf9e89581e4b29c854b16ea37e50a7d7fca5ae42ece5c273d8060dcd603b2404bbb3f - languageName: node - linkType: hard - -"which@npm:^2.0.1": - version: 2.0.2 - resolution: "which@npm:2.0.2" - dependencies: - isexe: "npm:^2.0.0" - bin: - node-which: ./bin/node-which - checksum: 10c0/66522872a768b60c2a65a57e8ad184e5372f5b6a9ca6d5f033d4b0dc98aff63995655a7503b9c0a2598936f532120e81dd8cc155e2e92ed662a2b9377cc4374f - languageName: node - linkType: hard - -"which@npm:^5.0.0": - version: 5.0.0 - resolution: "which@npm:5.0.0" - dependencies: - isexe: "npm:^3.1.1" - bin: - node-which: bin/which.js - checksum: 10c0/e556e4cd8b7dbf5df52408c9a9dd5ac6518c8c5267c8953f5b0564073c66ed5bf9503b14d876d0e9c7844d4db9725fb0dcf45d6e911e17e26ab363dc3965ae7b - languageName: node - linkType: hard - -"widest-line@npm:^3.1.0": - version: 3.1.0 - resolution: "widest-line@npm:3.1.0" - dependencies: - string-width: "npm:^4.0.0" - checksum: 10c0/b1e623adcfb9df35350dd7fc61295d6d4a1eaa65a406ba39c4b8360045b614af95ad10e05abf704936ed022569be438c4bfa02d6d031863c4166a238c301119f - languageName: node - linkType: hard - -"workerpool@npm:^6.5.1": - version: 6.5.1 - resolution: "workerpool@npm:6.5.1" - checksum: 10c0/58e8e969782292cb3a7bfba823f1179a7615250a0cefb4841d5166234db1880a3d0fe83a31dd8d648329ec92c2d0cd1890ad9ec9e53674bb36ca43e9753cdeac - languageName: node - linkType: hard - -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0, wrap-ansi@npm:^7.0.0": - version: 7.0.0 - resolution: "wrap-ansi@npm:7.0.0" - dependencies: - ansi-styles: "npm:^4.0.0" - string-width: "npm:^4.1.0" - strip-ansi: "npm:^6.0.0" - checksum: 10c0/d15fc12c11e4cbc4044a552129ebc75ee3f57aa9c1958373a4db0292d72282f54373b536103987a4a7594db1ef6a4f10acf92978f79b98c49306a4b58c77d4da - languageName: node - linkType: hard - -"wrap-ansi@npm:^8.1.0": - version: 8.1.0 - resolution: "wrap-ansi@npm:8.1.0" - dependencies: - ansi-styles: "npm:^6.1.0" - string-width: "npm:^5.0.1" - strip-ansi: "npm:^7.0.1" - checksum: 10c0/138ff58a41d2f877eae87e3282c0630fc2789012fc1af4d6bd626eeb9a2f9a65ca92005e6e69a75c7b85a68479fe7443c7dbe1eb8fbaa681a4491364b7c55c60 - languageName: node - linkType: hard - -"wrappy@npm:1": - version: 1.0.2 - resolution: "wrappy@npm:1.0.2" - checksum: 10c0/56fece1a4018c6a6c8e28fbc88c87e0fbf4ea8fd64fc6c63b18f4acc4bd13e0ad2515189786dd2c30d3eec9663d70f4ecf699330002f8ccb547e4a18231fc9f0 - languageName: node - linkType: hard - -"ws@npm:8.13.0": - version: 8.13.0 - resolution: "ws@npm:8.13.0" - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ">=5.0.2" - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - checksum: 10c0/579817dbbab3ee46669129c220cfd81ba6cdb9ab5c3e9a105702dd045743c4ab72e33bb384573827c0c481213417cc880e41bc097e0fc541a0b79fa3eb38207d - languageName: node - linkType: hard - -"ws@npm:^7.4.6": - version: 7.5.10 - resolution: "ws@npm:7.5.10" - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - checksum: 10c0/bd7d5f4aaf04fae7960c23dcb6c6375d525e00f795dd20b9385902bd008c40a94d3db3ce97d878acc7573df852056ca546328b27b39f47609f80fb22a0a9b61d - languageName: node - linkType: hard - -"ws@npm:^8.17.1": - version: 8.18.2 - resolution: "ws@npm:8.18.2" - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ">=5.0.2" - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - checksum: 10c0/4b50f67931b8c6943c893f59c524f0e4905bbd183016cfb0f2b8653aa7f28dad4e456b9d99d285bbb67cca4fedd9ce90dfdfaa82b898a11414ebd66ee99141e4 - languageName: node - linkType: hard - -"y18n@npm:^5.0.5": - version: 5.0.8 - resolution: "y18n@npm:5.0.8" - checksum: 10c0/4df2842c36e468590c3691c894bc9cdbac41f520566e76e24f59401ba7d8b4811eb1e34524d57e54bc6d864bcb66baab7ffd9ca42bf1eda596618f9162b91249 - languageName: node - linkType: hard - -"yallist@npm:^4.0.0": - version: 4.0.0 - resolution: "yallist@npm:4.0.0" - checksum: 10c0/2286b5e8dbfe22204ab66e2ef5cc9bbb1e55dfc873bbe0d568aa943eb255d131890dfd5bf243637273d31119b870f49c18fcde2c6ffbb7a7a092b870dc90625a - languageName: node - linkType: hard - -"yallist@npm:^5.0.0": - version: 5.0.0 - resolution: "yallist@npm:5.0.0" - checksum: 10c0/a499c81ce6d4a1d260d4ea0f6d49ab4da09681e32c3f0472dee16667ed69d01dae63a3b81745a24bd78476ec4fcf856114cb4896ace738e01da34b2c42235416 - languageName: node - linkType: hard - -"yargs-parser@npm:^20.2.2, yargs-parser@npm:^20.2.9": - version: 20.2.9 - resolution: "yargs-parser@npm:20.2.9" - checksum: 10c0/0685a8e58bbfb57fab6aefe03c6da904a59769bd803a722bb098bd5b0f29d274a1357762c7258fb487512811b8063fb5d2824a3415a0a4540598335b3b086c72 - languageName: node - linkType: hard - -"yargs-unparser@npm:^2.0.0": - version: 2.0.0 - resolution: "yargs-unparser@npm:2.0.0" - dependencies: - camelcase: "npm:^6.0.0" - decamelize: "npm:^4.0.0" - flat: "npm:^5.0.2" - is-plain-obj: "npm:^2.1.0" - checksum: 10c0/a5a7d6dc157efa95122e16780c019f40ed91d4af6d2bac066db8194ed0ec5c330abb115daa5a79ff07a9b80b8ea80c925baacf354c4c12edd878c0529927ff03 - languageName: node - linkType: hard - -"yargs@npm:^16.2.0": - version: 16.2.0 - resolution: "yargs@npm:16.2.0" - dependencies: - cliui: "npm:^7.0.2" - escalade: "npm:^3.1.1" - get-caller-file: "npm:^2.0.5" - require-directory: "npm:^2.1.1" - string-width: "npm:^4.2.0" - y18n: "npm:^5.0.5" - yargs-parser: "npm:^20.2.2" - checksum: 10c0/b1dbfefa679848442454b60053a6c95d62f2d2e21dd28def92b647587f415969173c6e99a0f3bab4f1b67ee8283bf735ebe3544013f09491186ba9e8a9a2b651 - languageName: node - linkType: hard - -"yocto-queue@npm:^0.1.0": - version: 0.1.0 - resolution: "yocto-queue@npm:0.1.0" - checksum: 10c0/dceb44c28578b31641e13695d200d34ec4ab3966a5729814d5445b194933c096b7ced71494ce53a0e8820685d1d010df8b2422e5bf2cdea7e469d97ffbea306f - languageName: node - linkType: hard - -"zod@npm:^3.21.4": - version: 3.25.48 - resolution: "zod@npm:3.25.48" - checksum: 10c0/bb1a537b27b62e6e7a37f909e9ff029c6ddac89fd6bba24b8e92b2002d5e9aaa90f74b30da1186a1f6ea5f1a0e216b77fad49301a91998d32730fc1b65719dc3 - languageName: node - linkType: hard +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@adraffy/ens-normalize@^1.8.8": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.11.0.tgz#42cc67c5baa407ac25059fcd7d405cc5ecdb0c33" + integrity sha512-/3DDPKHqqIqxUULp8yP4zODUY1i+2xvVWsv8A79xGWdCAG+8sb0hRh0Rk2QyOJUnnbyPUAZYcpBuRe3nS2OIUg== + +"@esbuild/aix-ppc64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz#4e0f91776c2b340e75558f60552195f6fad09f18" + integrity sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA== + +"@esbuild/android-arm64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.5.tgz#bc766407f1718923f6b8079c8c61bf86ac3a6a4f" + integrity sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg== + +"@esbuild/android-arm@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.5.tgz#4290d6d3407bae3883ad2cded1081a234473ce26" + integrity sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA== + +"@esbuild/android-x64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.5.tgz#40c11d9cbca4f2406548c8a9895d321bc3b35eff" + integrity sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw== + +"@esbuild/darwin-arm64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.5.tgz#49d8bf8b1df95f759ac81eb1d0736018006d7e34" + integrity sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ== + +"@esbuild/darwin-x64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.5.tgz#e27a5d92a14886ef1d492fd50fc61a2d4d87e418" + integrity sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ== + +"@esbuild/freebsd-arm64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.5.tgz#97cede59d638840ca104e605cdb9f1b118ba0b1c" + integrity sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw== + +"@esbuild/freebsd-x64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.5.tgz#71c77812042a1a8190c3d581e140d15b876b9c6f" + integrity sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw== + +"@esbuild/linux-arm64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.5.tgz#f7b7c8f97eff8ffd2e47f6c67eb5c9765f2181b8" + integrity sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg== + +"@esbuild/linux-arm@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.5.tgz#2a0be71b6cd8201fa559aea45598dffabc05d911" + integrity sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw== + +"@esbuild/linux-ia32@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.5.tgz#763414463cd9ea6fa1f96555d2762f9f84c61783" + integrity sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA== + +"@esbuild/linux-loong64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.5.tgz#428cf2213ff786a502a52c96cf29d1fcf1eb8506" + integrity sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg== + +"@esbuild/linux-mips64el@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.5.tgz#5cbcc7fd841b4cd53358afd33527cd394e325d96" + integrity sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg== + +"@esbuild/linux-ppc64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.5.tgz#0d954ab39ce4f5e50f00c4f8c4fd38f976c13ad9" + integrity sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ== + +"@esbuild/linux-riscv64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.5.tgz#0e7dd30730505abd8088321e8497e94b547bfb1e" + integrity sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA== + +"@esbuild/linux-s390x@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.5.tgz#5669af81327a398a336d7e40e320b5bbd6e6e72d" + integrity sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ== + +"@esbuild/linux-x64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.5.tgz#b2357dd153aa49038967ddc1ffd90c68a9d2a0d4" + integrity sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw== + +"@esbuild/netbsd-arm64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.5.tgz#53b4dfb8fe1cee93777c9e366893bd3daa6ba63d" + integrity sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw== + +"@esbuild/netbsd-x64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.5.tgz#a0206f6314ce7dc8713b7732703d0f58de1d1e79" + integrity sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ== + +"@esbuild/openbsd-arm64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.5.tgz#2a796c87c44e8de78001d808c77d948a21ec22fd" + integrity sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw== + +"@esbuild/openbsd-x64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.5.tgz#28d0cd8909b7fa3953af998f2b2ed34f576728f0" + integrity sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg== + +"@esbuild/sunos-x64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.5.tgz#a28164f5b997e8247d407e36c90d3fd5ddbe0dc5" + integrity sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA== + +"@esbuild/win32-arm64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.5.tgz#6eadbead38e8bd12f633a5190e45eff80e24007e" + integrity sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw== + +"@esbuild/win32-ia32@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.5.tgz#bab6288005482f9ed2adb9ded7e88eba9a62cc0d" + integrity sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ== + +"@esbuild/win32-x64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.5.tgz#7fc114af5f6563f19f73324b5d5ff36ece0803d1" + integrity sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g== + +"@ethereumjs/rlp@^4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@ethereumjs/rlp/-/rlp-4.0.1.tgz#626fabfd9081baab3d0a3074b0c7ecaf674aaa41" + integrity sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw== + +"@ethereumjs/rlp@^5.0.2": + version "5.0.2" + resolved "https://registry.yarnpkg.com/@ethereumjs/rlp/-/rlp-5.0.2.tgz#c89bd82f2f3bec248ab2d517ae25f5bbc4aac842" + integrity sha512-DziebCdg4JpGlEqEdGgXmjqcFoJi+JGulUXwEjsZGAscAQ7MyD/7LE/GVCP29vEQxKc7AAwjT3A2ywHp2xfoCA== + +"@ethereumjs/util@^9.1.0": + version "9.1.0" + resolved "https://registry.yarnpkg.com/@ethereumjs/util/-/util-9.1.0.tgz#75e3898a3116d21c135fa9e29886565609129bce" + integrity sha512-XBEKsYqLGXLah9PNJbgdkigthkG7TAGvlD/sH12beMXEyHDyigfcbdvHhmLyDWgDyOJn4QwiQUaF7yeuhnjdog== + dependencies: + "@ethereumjs/rlp" "^5.0.2" + ethereum-cryptography "^2.2.1" + +"@ethersproject/abi@^5.1.2": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.8.0.tgz#e79bb51940ac35fe6f3262d7fe2cdb25ad5f07d9" + integrity sha512-b9YS/43ObplgyV6SlyQsG53/vkSal0MNA1fskSC4mbnCMi8R+NkcH8K9FPYNESf6jUefBUniE4SOKms0E/KK1Q== + dependencies: + "@ethersproject/address" "^5.8.0" + "@ethersproject/bignumber" "^5.8.0" + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/constants" "^5.8.0" + "@ethersproject/hash" "^5.8.0" + "@ethersproject/keccak256" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + "@ethersproject/properties" "^5.8.0" + "@ethersproject/strings" "^5.8.0" + +"@ethersproject/abstract-provider@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.8.0.tgz#7581f9be601afa1d02b95d26b9d9840926a35b0c" + integrity sha512-wC9SFcmh4UK0oKuLJQItoQdzS/qZ51EJegK6EmAWlh+OptpQ/npECOR3QqECd8iGHC0RJb4WKbVdSfif4ammrg== + dependencies: + "@ethersproject/bignumber" "^5.8.0" + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + "@ethersproject/networks" "^5.8.0" + "@ethersproject/properties" "^5.8.0" + "@ethersproject/transactions" "^5.8.0" + "@ethersproject/web" "^5.8.0" + +"@ethersproject/abstract-signer@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.8.0.tgz#8d7417e95e4094c1797a9762e6789c7356db0754" + integrity sha512-N0XhZTswXcmIZQdYtUnd79VJzvEwXQw6PK0dTl9VoYrEBxxCPXqS0Eod7q5TNKRxe1/5WUMuR0u0nqTF/avdCA== + dependencies: + "@ethersproject/abstract-provider" "^5.8.0" + "@ethersproject/bignumber" "^5.8.0" + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + "@ethersproject/properties" "^5.8.0" + +"@ethersproject/address@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.8.0.tgz#3007a2c352eee566ad745dca1dbbebdb50a6a983" + integrity sha512-GhH/abcC46LJwshoN+uBNoKVFPxUuZm6dA257z0vZkKmU1+t8xTn8oK7B9qrj8W2rFRMch4gbJl6PmVxjxBEBA== + dependencies: + "@ethersproject/bignumber" "^5.8.0" + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/keccak256" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + "@ethersproject/rlp" "^5.8.0" + +"@ethersproject/base64@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.8.0.tgz#61c669c648f6e6aad002c228465d52ac93ee83eb" + integrity sha512-lN0oIwfkYj9LbPx4xEkie6rAMJtySbpOAFXSDVQaBnAzYfB4X2Qr+FXJGxMoc3Bxp2Sm8OwvzMrywxyw0gLjIQ== + dependencies: + "@ethersproject/bytes" "^5.8.0" + +"@ethersproject/bignumber@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.8.0.tgz#c381d178f9eeb370923d389284efa19f69efa5d7" + integrity sha512-ZyaT24bHaSeJon2tGPKIiHszWjD/54Sz8t57Toch475lCLljC6MgPmxk7Gtzz+ddNN5LuHea9qhAe0x3D+uYPA== + dependencies: + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + bn.js "^5.2.1" + +"@ethersproject/bytes@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.8.0.tgz#9074820e1cac7507a34372cadeb035461463be34" + integrity sha512-vTkeohgJVCPVHu5c25XWaWQOZ4v+DkGoC42/TS2ond+PARCxTJvgTFUNDZovyQ/uAQ4EcpqqowKydcdmRKjg7A== + dependencies: + "@ethersproject/logger" "^5.8.0" + +"@ethersproject/constants@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.8.0.tgz#12f31c2f4317b113a4c19de94e50933648c90704" + integrity sha512-wigX4lrf5Vu+axVTIvNsuL6YrV4O5AXl5ubcURKMEME5TnWBouUh0CDTWxZ2GpnRn1kcCgE7l8O5+VbV9QTTcg== + dependencies: + "@ethersproject/bignumber" "^5.8.0" + +"@ethersproject/hash@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.8.0.tgz#b8893d4629b7f8462a90102572f8cd65a0192b4c" + integrity sha512-ac/lBcTbEWW/VGJij0CNSw/wPcw9bSRgCB0AIBz8CvED/jfvDoV9hsIIiWfvWmFEi8RcXtlNwp2jv6ozWOsooA== + dependencies: + "@ethersproject/abstract-signer" "^5.8.0" + "@ethersproject/address" "^5.8.0" + "@ethersproject/base64" "^5.8.0" + "@ethersproject/bignumber" "^5.8.0" + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/keccak256" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + "@ethersproject/properties" "^5.8.0" + "@ethersproject/strings" "^5.8.0" + +"@ethersproject/keccak256@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.8.0.tgz#d2123a379567faf2d75d2aaea074ffd4df349e6a" + integrity sha512-A1pkKLZSz8pDaQ1ftutZoaN46I6+jvuqugx5KYNeQOPqq+JZ0Txm7dlWesCHB5cndJSu5vP2VKptKf7cksERng== + dependencies: + "@ethersproject/bytes" "^5.8.0" + js-sha3 "0.8.0" + +"@ethersproject/logger@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.8.0.tgz#f0232968a4f87d29623a0481690a2732662713d6" + integrity sha512-Qe6knGmY+zPPWTC+wQrpitodgBfH7XoceCGL5bJVejmH+yCS3R8jJm8iiWuvWbG76RUmyEG53oqv6GMVWqunjA== + +"@ethersproject/networks@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.8.0.tgz#8b4517a3139380cba9fb00b63ffad0a979671fde" + integrity sha512-egPJh3aPVAzbHwq8DD7Po53J4OUSsA1MjQp8Vf/OZPav5rlmWUaFLiq8cvQiGK0Z5K6LYzm29+VA/p4RL1FzNg== + dependencies: + "@ethersproject/logger" "^5.8.0" + +"@ethersproject/properties@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.8.0.tgz#405a8affb6311a49a91dabd96aeeae24f477020e" + integrity sha512-PYuiEoQ+FMaZZNGrStmN7+lWjlsoufGIHdww7454FIaGdbe/p5rnaCXTr5MtBYl3NkeoVhHZuyzChPeGeKIpQw== + dependencies: + "@ethersproject/logger" "^5.8.0" + +"@ethersproject/rlp@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.8.0.tgz#5a0d49f61bc53e051532a5179472779141451de5" + integrity sha512-LqZgAznqDbiEunaUvykH2JAoXTT9NV0Atqk8rQN9nx9SEgThA/WMx5DnW8a9FOufo//6FZOCHZ+XiClzgbqV9Q== + dependencies: + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + +"@ethersproject/signing-key@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.8.0.tgz#9797e02c717b68239c6349394ea85febf8893119" + integrity sha512-LrPW2ZxoigFi6U6aVkFN/fa9Yx/+4AtIUe4/HACTvKJdhm0eeb107EVCIQcrLZkxaSIgc/eCrX8Q1GtbH+9n3w== + dependencies: + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + "@ethersproject/properties" "^5.8.0" + bn.js "^5.2.1" + elliptic "6.6.1" + hash.js "1.1.7" + +"@ethersproject/strings@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.8.0.tgz#ad79fafbf0bd272d9765603215ac74fd7953908f" + integrity sha512-qWEAk0MAvl0LszjdfnZ2uC8xbR2wdv4cDabyHiBh3Cldq/T8dPH3V4BbBsAYJUeonwD+8afVXld274Ls+Y1xXg== + dependencies: + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/constants" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + +"@ethersproject/transactions@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.8.0.tgz#1e518822403abc99def5a043d1c6f6fe0007e46b" + integrity sha512-UglxSDjByHG0TuU17bDfCemZ3AnKO2vYrL5/2n2oXvKzvb7Cz+W9gOWXKARjp2URVwcWlQlPOEQyAviKwT4AHg== + dependencies: + "@ethersproject/address" "^5.8.0" + "@ethersproject/bignumber" "^5.8.0" + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/constants" "^5.8.0" + "@ethersproject/keccak256" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + "@ethersproject/properties" "^5.8.0" + "@ethersproject/rlp" "^5.8.0" + "@ethersproject/signing-key" "^5.8.0" + +"@ethersproject/web@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.8.0.tgz#3e54badc0013b7a801463a7008a87988efce8a37" + integrity sha512-j7+Ksi/9KfGviws6Qtf9Q7KCqRhpwrYKQPs+JBA/rKVFF/yaWLHJEH3zfVP2plVu+eys0d2DlFmhoQJayFewcw== + dependencies: + "@ethersproject/base64" "^5.8.0" + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + "@ethersproject/properties" "^5.8.0" + "@ethersproject/strings" "^5.8.0" + +"@fastify/busboy@^2.0.0": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@fastify/busboy/-/busboy-2.1.1.tgz#b9da6a878a371829a0502c9b6c1c143ef6663f4d" + integrity sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA== + +"@lido-js/ganache@=7.9.2-lido": + version "7.9.2-lido" + resolved "https://registry.yarnpkg.com/@lido-js/ganache/-/ganache-7.9.2-lido.tgz#927611f015c72dbb0d68767ce69dc8f1b2bba6b8" + integrity sha512-q40Q3760CCn4rzg7prpiuPw9sYSKnrVKcIQupqrgAnWagr/I3FkUmNNhBWw4rQpPla4K50vyOJoUtPnN+hRx9g== + dependencies: + "@trufflesuite/bigint-buffer" "1.1.10" + "@trufflesuite/uws-js-unofficial" "20.30.0-unofficial.0" + "@types/bn.js" "^5.1.0" + "@types/lru-cache" "5.1.1" + "@types/seedrandom" "3.0.1" + abstract-level "1.0.3" + abstract-leveldown "7.2.0" + async-eventemitter "0.2.4" + emittery "0.10.0" + keccak "3.0.2" + leveldown "6.1.0" + secp256k1 "4.0.3" + optionalDependencies: + bufferutil "4.0.5" + utf-8-validate "5.0.7" + +"@noble/curves@1.4.2", "@noble/curves@~1.4.0": + version "1.4.2" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.4.2.tgz#40309198c76ed71bc6dbf7ba24e81ceb4d0d1fe9" + integrity sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw== + dependencies: + "@noble/hashes" "1.4.0" + +"@noble/curves@~1.8.1": + version "1.8.2" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.8.2.tgz#8f24c037795e22b90ae29e222a856294c1d9ffc7" + integrity sha512-vnI7V6lFNe0tLAuJMu+2sX+FcL14TaCWy1qiczg1VwRmPrpQCdq5ESXQMqUc2tluRNf6irBXrWbl1mGN8uaU/g== + dependencies: + "@noble/hashes" "1.7.2" + +"@noble/hashes@1.2.0", "@noble/hashes@~1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.2.0.tgz#a3150eeb09cc7ab207ebf6d7b9ad311a9bdbed12" + integrity sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ== + +"@noble/hashes@1.4.0", "@noble/hashes@~1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.4.0.tgz#45814aa329f30e4fe0ba49426f49dfccdd066426" + integrity sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg== + +"@noble/hashes@1.7.2", "@noble/hashes@~1.7.1": + version "1.7.2" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.7.2.tgz#d53c65a21658fb02f3303e7ee3ba89d6754c64b4" + integrity sha512-biZ0NUSxyjLLqo6KxEJ1b+C2NAx0wtDoFvCaXHGgUkeHzf3Xc1xKumFKREuT7f7DARNZ/slvYUwFG6B0f2b6hQ== + +"@noble/secp256k1@1.7.1", "@noble/secp256k1@~1.7.0": + version "1.7.1" + resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.7.1.tgz#b251c70f824ce3ca7f8dc3df08d58f005cc0507c" + integrity sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw== + +"@nomicfoundation/edr-darwin-arm64@0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.11.0.tgz#fa791451c5ce2acf6634143bca9fe8f1b5c66603" + integrity sha512-aYTVdcSs27XG7ayTzvZ4Yn9z/ABSaUwicrtrYK2NR8IH0ik4N4bWzo/qH8rax6rewVLbHUkGyGYnsy5ZN4iiMw== + +"@nomicfoundation/edr-darwin-x64@0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.11.0.tgz#b1aaf0bfb331f6d136a92cbe31f184e2209e7a4f" + integrity sha512-RxX7UYgvJrfcyT/uHUn44Nsy1XaoW+Q1khKMdHKxeW7BrgIi+Lz+siz3bX5vhSoAnKilDPhIVLrnC8zxQhjR2A== + +"@nomicfoundation/edr-linux-arm64-gnu@0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.11.0.tgz#fef6763c5d42bb68b4fc95df45c4745a0e31df93" + integrity sha512-J0j+rs0s11FuSipt/ymqrFmpJ7c0FSz1/+FohCIlUXDxFv//+1R/8lkGPjEYFmy8DPpk/iO8mcpqHTGckREbqA== + +"@nomicfoundation/edr-linux-arm64-musl@0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.11.0.tgz#ef89d5d2aefc1f8d4f7c699c59b8897a645d33eb" + integrity sha512-4r32zkGMN7WT/CMEuW0VjbuEdIeCskHNDMW4SSgQSJOE/N9L1KSLJCSsAbPD3aYE+e4WRDTyOwmuLjeUTcLZKQ== + +"@nomicfoundation/edr-linux-x64-gnu@0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.11.0.tgz#97432126110aa805b761d4743ab158698cae6d66" + integrity sha512-SmdncQHLYtVNWLIMyGaY6LpAfamzTDe3fxjkirmJv3CWR5tcEyC6LMui/GsIVnJzXeNJBXAzwl8hTUAxHTM6kQ== + +"@nomicfoundation/edr-linux-x64-musl@0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.11.0.tgz#7605fddbada22dfdd14b15f4ac562014d9c82332" + integrity sha512-w6hUqpn/trwiH6SRuRGysj37LsQVCX5XDCA3Xi81sbOaLhbHrNvK9TXWyZmcuzbdTKQQW6VNywcSxDdOiChcJg== + +"@nomicfoundation/edr-win32-x64-msvc@0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.11.0.tgz#6766175f3ec47bfbda0429ca00fed4ae5632a3c4" + integrity sha512-BLmULjRKoH9BsX+c4Na2ypV7NGeJ+M6Zpqj/faPOwleVscDdSr/IhriyPaXCe8dyfwbge7lWsbekiADtPSnB2Q== + +"@nomicfoundation/edr@^0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr/-/edr-0.11.0.tgz#d8b0ba4dfd7d93b9c54762e72eb9cd4e8244ce46" + integrity sha512-36WERf8ldvyHR6UAbcYsa+vpbW7tCrJGBwF4gXSsb8+STj1n66Hz85Y/O7B9+8AauX3PhglvV5dKl91tk43mWw== + dependencies: + "@nomicfoundation/edr-darwin-arm64" "0.11.0" + "@nomicfoundation/edr-darwin-x64" "0.11.0" + "@nomicfoundation/edr-linux-arm64-gnu" "0.11.0" + "@nomicfoundation/edr-linux-arm64-musl" "0.11.0" + "@nomicfoundation/edr-linux-x64-gnu" "0.11.0" + "@nomicfoundation/edr-linux-x64-musl" "0.11.0" + "@nomicfoundation/edr-win32-x64-msvc" "0.11.0" + +"@nomicfoundation/solidity-analyzer-darwin-arm64@0.1.2": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-darwin-arm64/-/solidity-analyzer-darwin-arm64-0.1.2.tgz#3a9c3b20d51360b20affb8f753e756d553d49557" + integrity sha512-JaqcWPDZENCvm++lFFGjrDd8mxtf+CtLd2MiXvMNTBD33dContTZ9TWETwNFwg7JTJT5Q9HEecH7FA+HTSsIUw== + +"@nomicfoundation/solidity-analyzer-darwin-x64@0.1.2": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-darwin-x64/-/solidity-analyzer-darwin-x64-0.1.2.tgz#74dcfabeb4ca373d95bd0d13692f44fcef133c28" + integrity sha512-fZNmVztrSXC03e9RONBT+CiksSeYcxI1wlzqyr0L7hsQlK1fzV+f04g2JtQ1c/Fe74ZwdV6aQBdd6Uwl1052sw== + +"@nomicfoundation/solidity-analyzer-linux-arm64-gnu@0.1.2": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-arm64-gnu/-/solidity-analyzer-linux-arm64-gnu-0.1.2.tgz#4af5849a89e5a8f511acc04f28eb5d4460ba2b6a" + integrity sha512-3d54oc+9ZVBuB6nbp8wHylk4xh0N0Gc+bk+/uJae+rUgbOBwQSfuGIbAZt1wBXs5REkSmynEGcqx6DutoK0tPA== + +"@nomicfoundation/solidity-analyzer-linux-arm64-musl@0.1.2": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-arm64-musl/-/solidity-analyzer-linux-arm64-musl-0.1.2.tgz#54036808a9a327b2ff84446c130a6687ee702a8e" + integrity sha512-iDJfR2qf55vgsg7BtJa7iPiFAsYf2d0Tv/0B+vhtnI16+wfQeTbP7teookbGvAo0eJo7aLLm0xfS/GTkvHIucA== + +"@nomicfoundation/solidity-analyzer-linux-x64-gnu@0.1.2": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-x64-gnu/-/solidity-analyzer-linux-x64-gnu-0.1.2.tgz#466cda0d6e43691986c944b909fc6dbb8cfc594e" + integrity sha512-9dlHMAt5/2cpWyuJ9fQNOUXFB/vgSFORg1jpjX1Mh9hJ/MfZXlDdHQ+DpFCs32Zk5pxRBb07yGvSHk9/fezL+g== + +"@nomicfoundation/solidity-analyzer-linux-x64-musl@0.1.2": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-x64-musl/-/solidity-analyzer-linux-x64-musl-0.1.2.tgz#2b35826987a6e94444140ac92310baa088ee7f94" + integrity sha512-GzzVeeJob3lfrSlDKQw2bRJ8rBf6mEYaWY+gW0JnTDHINA0s2gPR4km5RLIj1xeZZOYz4zRw+AEeYgLRqB2NXg== + +"@nomicfoundation/solidity-analyzer-win32-x64-msvc@0.1.2": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-win32-x64-msvc/-/solidity-analyzer-win32-x64-msvc-0.1.2.tgz#e6363d13b8709ca66f330562337dbc01ce8bbbd9" + integrity sha512-Fdjli4DCcFHb4Zgsz0uEJXZ2K7VEO+w5KVv7HmT7WO10iODdU9csC2az4jrhEsRtiR9Gfd74FlG0NYlw1BMdyA== + +"@nomicfoundation/solidity-analyzer@^0.1.0": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer/-/solidity-analyzer-0.1.2.tgz#8bcea7d300157bf3a770a851d9f5c5e2db34ac55" + integrity sha512-q4n32/FNKIhQ3zQGGw5CvPF6GTvDCpYwIf7bEY/dZTZbgfDsHyjJwURxUJf3VQuuJj+fDIFl4+KkBVbw4Ef6jA== + optionalDependencies: + "@nomicfoundation/solidity-analyzer-darwin-arm64" "0.1.2" + "@nomicfoundation/solidity-analyzer-darwin-x64" "0.1.2" + "@nomicfoundation/solidity-analyzer-linux-arm64-gnu" "0.1.2" + "@nomicfoundation/solidity-analyzer-linux-arm64-musl" "0.1.2" + "@nomicfoundation/solidity-analyzer-linux-x64-gnu" "0.1.2" + "@nomicfoundation/solidity-analyzer-linux-x64-musl" "0.1.2" + "@nomicfoundation/solidity-analyzer-win32-x64-msvc" "0.1.2" + +"@scure/base@~1.1.0", "@scure/base@~1.1.6": + version "1.1.9" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.9.tgz#e5e142fbbfe251091f9c5f1dd4c834ac04c3dbd1" + integrity sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg== + +"@scure/base@~1.2.5": + version "1.2.6" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.2.6.tgz#ca917184b8231394dd8847509c67a0be522e59f6" + integrity sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg== + +"@scure/bip32@1.1.5": + version "1.1.5" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.1.5.tgz#d2ccae16dcc2e75bc1d75f5ef3c66a338d1ba300" + integrity sha512-XyNh1rB0SkEqd3tXcXMi+Xe1fvg+kUIcoRIEujP1Jgv7DqW2r9lg3Ah0NkFaCs9sTkQAQA8kw7xiRXzENi9Rtw== + dependencies: + "@noble/hashes" "~1.2.0" + "@noble/secp256k1" "~1.7.0" + "@scure/base" "~1.1.0" + +"@scure/bip32@1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.4.0.tgz#4e1f1e196abedcef395b33b9674a042524e20d67" + integrity sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg== + dependencies: + "@noble/curves" "~1.4.0" + "@noble/hashes" "~1.4.0" + "@scure/base" "~1.1.6" + +"@scure/bip39@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.1.1.tgz#b54557b2e86214319405db819c4b6a370cf340c5" + integrity sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg== + dependencies: + "@noble/hashes" "~1.2.0" + "@scure/base" "~1.1.0" + +"@scure/bip39@1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.3.0.tgz#0f258c16823ddd00739461ac31398b4e7d6a18c3" + integrity sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ== + dependencies: + "@noble/hashes" "~1.4.0" + "@scure/base" "~1.1.6" + +"@sentry/core@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.30.0.tgz#6b203664f69e75106ee8b5a2fe1d717379b331f3" + integrity sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg== + dependencies: + "@sentry/hub" "5.30.0" + "@sentry/minimal" "5.30.0" + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + tslib "^1.9.3" + +"@sentry/hub@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.30.0.tgz#2453be9b9cb903404366e198bd30c7ca74cdc100" + integrity sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ== + dependencies: + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + tslib "^1.9.3" + +"@sentry/minimal@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.30.0.tgz#ce3d3a6a273428e0084adcb800bc12e72d34637b" + integrity sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw== + dependencies: + "@sentry/hub" "5.30.0" + "@sentry/types" "5.30.0" + tslib "^1.9.3" + +"@sentry/node@^5.18.1": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/node/-/node-5.30.0.tgz#4ca479e799b1021285d7fe12ac0858951c11cd48" + integrity sha512-Br5oyVBF0fZo6ZS9bxbJZG4ApAjRqAnqFFurMVJJdunNb80brh7a5Qva2kjhm+U6r9NJAB5OmDyPkA1Qnt+QVg== + dependencies: + "@sentry/core" "5.30.0" + "@sentry/hub" "5.30.0" + "@sentry/tracing" "5.30.0" + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + cookie "^0.4.1" + https-proxy-agent "^5.0.0" + lru_map "^0.3.3" + tslib "^1.9.3" + +"@sentry/tracing@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-5.30.0.tgz#501d21f00c3f3be7f7635d8710da70d9419d4e1f" + integrity sha512-dUFowCr0AIMwiLD7Fs314Mdzcug+gBVo/+NCMyDw8tFxJkwWAKl7Qa2OZxLQ0ZHjakcj1hNKfCQJ9rhyfOl4Aw== + dependencies: + "@sentry/hub" "5.30.0" + "@sentry/minimal" "5.30.0" + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + tslib "^1.9.3" + +"@sentry/types@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.30.0.tgz#19709bbe12a1a0115bc790b8942917da5636f402" + integrity sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw== + +"@sentry/utils@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.30.0.tgz#9a5bd7ccff85ccfe7856d493bffa64cabc41e980" + integrity sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww== + dependencies: + "@sentry/types" "5.30.0" + tslib "^1.9.3" + +"@trufflesuite/bigint-buffer@1.1.10": + version "1.1.10" + resolved "https://registry.yarnpkg.com/@trufflesuite/bigint-buffer/-/bigint-buffer-1.1.10.tgz#a1d9ca22d3cad1a138b78baaf15543637a3e1692" + integrity sha512-pYIQC5EcMmID74t26GCC67946mgTJFiLXOT/BYozgrd4UEY2JHEGLhWi9cMiQCt5BSqFEvKkCHNnoj82SRjiEw== + dependencies: + node-gyp-build "4.4.0" + +"@trufflesuite/uws-js-unofficial@20.30.0-unofficial.0": + version "20.30.0-unofficial.0" + resolved "https://registry.yarnpkg.com/@trufflesuite/uws-js-unofficial/-/uws-js-unofficial-20.30.0-unofficial.0.tgz#2fbc2f8ef7e82fbeea6abaf7e8a9d42a02b479d3" + integrity sha512-r5X0aOQcuT6pLwTRLD+mPnAM/nlKtvIK4Z+My++A8tTOR0qTjNRx8UB8jzRj3D+p9PMAp5LnpCUUGmz7/TppwA== + dependencies: + ws "8.13.0" + optionalDependencies: + bufferutil "4.0.7" + utf-8-validate "6.0.3" + +"@types/bn.js@^5.1.0": + version "5.1.5" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.5.tgz#2e0dacdcce2c0f16b905d20ff87aedbc6f7b4bf0" + integrity sha512-V46N0zwKRF5Q00AZ6hWtN0T8gGmDUaUzLWQvHFo5yThtVwK/VCenFY3wXVbOvNfajEpsTfQM4IN9k/d6gUVX3A== + dependencies: + "@types/node" "*" + +"@types/lru-cache@5.1.1", "@types/lru-cache@^5.1.0": + version "5.1.1" + resolved "https://registry.yarnpkg.com/@types/lru-cache/-/lru-cache-5.1.1.tgz#c48c2e27b65d2a153b19bfc1a317e30872e01eef" + integrity sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw== + +"@types/node@*": + version "20.11.16" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.16.tgz#4411f79411514eb8e2926f036c86c9f0e4ec6708" + integrity sha512-gKb0enTmRCzXSSUJDq6/sPcqrfCv2mkkG6Jt/clpn5eiCbKTY+SgZUxo+p8ZKMof5dCp9vHQUAB7wOUTod22wQ== + dependencies: + undici-types "~5.26.4" + +"@types/seedrandom@3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/seedrandom/-/seedrandom-3.0.1.tgz#1254750a4fec4aff2ebec088ccd0bb02e91fedb4" + integrity sha512-giB9gzDeiCeloIXDgzFBCgjj1k4WxcDrZtGl6h1IqmUPlxF+Nx8Ve+96QCyDZ/HseB/uvDsKbpib9hU5cU53pw== + +"@types/ws@8.5.3": + version "8.5.3" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.3.tgz#7d25a1ffbecd3c4f2d35068d0b283c037003274d" + integrity sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w== + dependencies: + "@types/node" "*" + +abitype@0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/abitype/-/abitype-0.7.1.tgz#16db20abe67de80f6183cf75f3de1ff86453b745" + integrity sha512-VBkRHTDZf9Myaek/dO3yMmOzB/y2s3Zo6nVU7yaw1G+TvCHAjwaJzNGN9yo4K5D8bU/VZXKP1EJpRhFr862PlQ== + +abstract-level@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/abstract-level/-/abstract-level-1.0.3.tgz#78a67d3d84da55ee15201486ab44c09560070741" + integrity sha512-t6jv+xHy+VYwc4xqZMn2Pa9DjcdzvzZmQGRjTFc8spIbRGHgBrEKbPq+rYXc7CCo0lxgYvSgKVg9qZAhpVQSjA== + dependencies: + buffer "^6.0.3" + catering "^2.1.0" + is-buffer "^2.0.5" + level-supports "^4.0.0" + level-transcoder "^1.0.1" + module-error "^1.0.1" + queue-microtask "^1.2.3" + +abstract-leveldown@7.2.0, abstract-leveldown@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-7.2.0.tgz#08d19d4e26fb5be426f7a57004851b39e1795a2e" + integrity sha512-DnhQwcFEaYsvYDnACLZhMmCWd3rkOeEvglpa4q5i/5Jlm3UIsWaxVzuXvDLFCSCWRO3yy2/+V/G7FusFgejnfQ== + dependencies: + buffer "^6.0.3" + catering "^2.0.0" + is-buffer "^2.0.5" + level-concat-iterator "^3.0.0" + level-supports "^2.0.1" + queue-microtask "^1.2.3" + +adm-zip@^0.4.16: + version "0.4.16" + resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.16.tgz#cf4c508fdffab02c269cbc7f471a875f05570365" + integrity sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg== + +agent-base@6: + version "6.0.2" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== + dependencies: + debug "4" + +aggregate-error@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" + integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== + dependencies: + clean-stack "^2.0.0" + indent-string "^4.0.0" + +ansi-align@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.1.tgz#0cdf12e111ace773a86e9a1fad1225c43cb19a59" + integrity sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w== + dependencies: + string-width "^4.1.0" + +ansi-colors@^4.1.1, ansi-colors@^4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" + integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== + +ansi-escapes@^4.3.0: + version "4.3.2" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +async-eventemitter@0.2.4: + version "0.2.4" + resolved "https://registry.yarnpkg.com/async-eventemitter/-/async-eventemitter-0.2.4.tgz#f5e7c8ca7d3e46aab9ec40a292baf686a0bafaca" + integrity sha512-pd20BwL7Yt1zwDFy+8MX8F1+WCT8aQeKj0kQnTrH9WaeRETlRamVhD0JtRPmrV4GfOJ2F9CvdQkZeZhnh2TuHw== + dependencies: + async "^2.4.0" + +async@^2.4.0: + version "2.6.4" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221" + integrity sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA== + dependencies: + lodash "^4.17.14" + +available-typed-arrays@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846" + integrity sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ== + dependencies: + possible-typed-array-names "^1.0.0" + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + +bignumber.js@^9.3.0: + version "9.3.0" + resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.3.0.tgz#bdba7e2a4c1a2eba08290e8dcad4f36393c92acd" + integrity sha512-EM7aMFTXbptt/wZdMlBv2t8IViwQL+h6SLHosp8Yf0dqJMTnY6iL32opnAB6kAdL0SZPuvcAzFr31o0c/R3/RA== + +binary-extensions@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" + integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== + +bn.js@^4.11.9: + version "4.12.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" + integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== + +bn.js@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" + integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== + +boxen@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/boxen/-/boxen-5.1.2.tgz#788cb686fc83c1f486dfa8a40c68fc2b831d2b50" + integrity sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ== + dependencies: + ansi-align "^3.0.0" + camelcase "^6.2.0" + chalk "^4.1.0" + cli-boxes "^2.2.1" + string-width "^4.2.2" + type-fest "^0.20.2" + widest-line "^3.1.0" + wrap-ansi "^7.0.0" + +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + +braces@~3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== + dependencies: + fill-range "^7.1.1" + +brorand@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== + +browser-stdout@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +buffer@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" + integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.2.1" + +bufferutil@4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.5.tgz#da9ea8166911cc276bf677b8aed2d02d31f59028" + integrity sha512-HTm14iMQKK2FjFLRTM5lAVcyaUzOnqbPtesFIvREgXpJHdQm8bWS+GkQgIkfaBYRHuCnea7w8UVNfwiAQhlr9A== + dependencies: + node-gyp-build "^4.3.0" + +bufferutil@4.0.7: + version "4.0.7" + resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.7.tgz#60c0d19ba2c992dd8273d3f73772ffc894c153ad" + integrity sha512-kukuqc39WOHtdxtw4UScxF/WVnMFVSQVKhtx3AjZJzhd0RGZZldcrfSEbVsWWe6KNH253574cq5F+wpv0G9pJw== + dependencies: + node-gyp-build "^4.3.0" + +bytes@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== + +call-bind-apply-helpers@^1.0.0, call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz#4b5428c222be985d79c3d82657479dbe0b59b2d6" + integrity sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ== + dependencies: + es-errors "^1.3.0" + function-bind "^1.1.2" + +call-bind@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.8.tgz#0736a9660f537e3388826f440d5ec45f744eaa4c" + integrity sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww== + dependencies: + call-bind-apply-helpers "^1.0.0" + es-define-property "^1.0.0" + get-intrinsic "^1.2.4" + set-function-length "^1.2.2" + +call-bound@^1.0.2, call-bound@^1.0.3, call-bound@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/call-bound/-/call-bound-1.0.4.tgz#238de935d2a2a692928c538c7ccfa91067fd062a" + integrity sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg== + dependencies: + call-bind-apply-helpers "^1.0.2" + get-intrinsic "^1.3.0" + +camelcase@^6.0.0, camelcase@^6.2.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + +catering@^2.0.0, catering@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/catering/-/catering-2.1.1.tgz#66acba06ed5ee28d5286133982a927de9a04b510" + integrity sha512-K7Qy8O9p76sL3/3m7/zLKbRkyOlSZAgzEaLhyj2mXS8PsCud2Eo4hAb8aLtZqHh0QGqLcb9dlJSu6lHRVENm1w== + +chalk@^4.1.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chokidar@^3.5.3: + version "3.6.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" + integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +chokidar@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-4.0.3.tgz#7be37a4c03c9aee1ecfe862a4a23b2c70c205d30" + integrity sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA== + dependencies: + readdirp "^4.0.1" + +ci-info@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" + integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== + +clean-stack@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== + +cli-boxes@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f" + integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw== + +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +command-exists@^1.2.8: + version "1.2.9" + resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69" + integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w== + +commander@^8.1.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" + integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== + +cookie@^0.4.1: + version "0.4.2" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" + integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== + +crc-32@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.2.tgz#3cad35a934b8bf71f25ca524b6da51fb7eace2ff" + integrity sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ== + +cross-fetch@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-4.1.0.tgz#8f69355007ee182e47fa692ecbaa37a52e43c3d2" + integrity sha512-uKm5PU+MHTootlWEY+mZ4vvXoCn4fLQxT9dSc1sXVMSFkINTJVN8cAQROpwcKm8bJ/c7rgZVIBWzH5T78sNZZw== + dependencies: + node-fetch "^2.7.0" + +debug@4, debug@^4.1.1, debug@^4.3.5: + version "4.4.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a" + integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== + dependencies: + ms "^2.1.3" + +decamelize@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" + integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== + +define-data-property@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" + integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + gopd "^1.0.1" + +depd@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + +diff@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.2.0.tgz#26ded047cd1179b78b9537d5ef725503ce1ae531" + integrity sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A== + +dunder-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a" + integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A== + dependencies: + call-bind-apply-helpers "^1.0.1" + es-errors "^1.3.0" + gopd "^1.2.0" + +elliptic@6.6.1: + version "6.6.1" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.6.1.tgz#3b8ffb02670bf69e382c7f65bf524c97c5405c06" + integrity sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g== + dependencies: + bn.js "^4.11.9" + brorand "^1.1.0" + hash.js "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" + +elliptic@^6.5.4: + version "6.5.4" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" + integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== + dependencies: + bn.js "^4.11.9" + brorand "^1.1.0" + hash.js "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" + +emittery@0.10.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.10.0.tgz#bb373c660a9d421bb44706ec4967ed50c02a8026" + integrity sha512-AGvFfs+d0JKCJQ4o01ASQLGPmSCxgfU9RFXvzPvZdjKK8oscynksuJhWrSTSw7j7Ep/sZct5b5ZhYCi8S/t0HQ== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +enquirer@^2.3.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.4.1.tgz#93334b3fbd74fc7097b224ab4a8fb7e40bf4ae56" + integrity sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ== + dependencies: + ansi-colors "^4.1.1" + strip-ansi "^6.0.1" + +env-paths@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" + integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== + +es-define-property@^1.0.0, es-define-property@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa" + integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g== + +es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + +es-object-atoms@^1.0.0, es-object-atoms@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz#1c4f2c4837327597ce69d2ca190a7fdd172338c1" + integrity sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA== + dependencies: + es-errors "^1.3.0" + +esbuild@~0.25.0: + version "0.25.5" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.25.5.tgz#71075054993fdfae76c66586f9b9c1f8d7edd430" + integrity sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ== + optionalDependencies: + "@esbuild/aix-ppc64" "0.25.5" + "@esbuild/android-arm" "0.25.5" + "@esbuild/android-arm64" "0.25.5" + "@esbuild/android-x64" "0.25.5" + "@esbuild/darwin-arm64" "0.25.5" + "@esbuild/darwin-x64" "0.25.5" + "@esbuild/freebsd-arm64" "0.25.5" + "@esbuild/freebsd-x64" "0.25.5" + "@esbuild/linux-arm" "0.25.5" + "@esbuild/linux-arm64" "0.25.5" + "@esbuild/linux-ia32" "0.25.5" + "@esbuild/linux-loong64" "0.25.5" + "@esbuild/linux-mips64el" "0.25.5" + "@esbuild/linux-ppc64" "0.25.5" + "@esbuild/linux-riscv64" "0.25.5" + "@esbuild/linux-s390x" "0.25.5" + "@esbuild/linux-x64" "0.25.5" + "@esbuild/netbsd-arm64" "0.25.5" + "@esbuild/netbsd-x64" "0.25.5" + "@esbuild/openbsd-arm64" "0.25.5" + "@esbuild/openbsd-x64" "0.25.5" + "@esbuild/sunos-x64" "0.25.5" + "@esbuild/win32-arm64" "0.25.5" + "@esbuild/win32-ia32" "0.25.5" + "@esbuild/win32-x64" "0.25.5" + +escalade@^3.1.1: + version "3.2.0" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" + integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +ethereum-cryptography@^1.0.3: + version "1.2.0" + resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz#5ccfa183e85fdaf9f9b299a79430c044268c9b3a" + integrity sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw== + dependencies: + "@noble/hashes" "1.2.0" + "@noble/secp256k1" "1.7.1" + "@scure/bip32" "1.1.5" + "@scure/bip39" "1.1.1" + +ethereum-cryptography@^2.0.0, ethereum-cryptography@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz#58f2810f8e020aecb97de8c8c76147600b0b8ccf" + integrity sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg== + dependencies: + "@noble/curves" "1.4.2" + "@noble/hashes" "1.4.0" + "@scure/bip32" "1.4.0" + "@scure/bip39" "1.3.0" + +eventemitter3@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.1.tgz#53f5ffd0a492ac800721bb42c66b841de96423c4" + integrity sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA== + +fdir@^6.4.3: + version "6.4.3" + resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.4.3.tgz#011cdacf837eca9b811c89dbb902df714273db72" + integrity sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw== + +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== + dependencies: + to-regex-range "^5.0.1" + +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +flat@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" + integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== + +follow-redirects@^1.12.1: + version "1.15.9" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1" + integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ== + +for-each@^0.3.5: + version "0.3.5" + resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.5.tgz#d650688027826920feeb0af747ee7b9421a41d47" + integrity sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg== + dependencies: + is-callable "^1.2.7" + +fp-ts@1.19.3: + version "1.19.3" + resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-1.19.3.tgz#261a60d1088fbff01f91256f91d21d0caaaaa96f" + integrity sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg== + +fp-ts@^1.0.0: + version "1.19.5" + resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-1.19.5.tgz#3da865e585dfa1fdfd51785417357ac50afc520a" + integrity sha512-wDNqTimnzs8QqpldiId9OavWK2NptormjXnRJTQecNjzwfyp6P/8s/zG8e4h3ja3oqkKaY72UlTjQYt/1yXf9A== + +fs-extra@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" + integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== + dependencies: + graceful-fs "^4.1.2" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@~2.3.2, fsevents@~2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-intrinsic@^1.2.4, get-intrinsic@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz#743f0e3b6964a93a5491ed1bffaae054d7f98d01" + integrity sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ== + dependencies: + call-bind-apply-helpers "^1.0.2" + es-define-property "^1.0.1" + es-errors "^1.3.0" + es-object-atoms "^1.1.1" + function-bind "^1.1.2" + get-proto "^1.0.1" + gopd "^1.2.0" + has-symbols "^1.1.0" + hasown "^2.0.2" + math-intrinsics "^1.1.0" + +get-proto@^1.0.0, get-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/get-proto/-/get-proto-1.0.1.tgz#150b3f2743869ef3e851ec0c49d15b1d14d00ee1" + integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g== + dependencies: + dunder-proto "^1.0.1" + es-object-atoms "^1.0.0" + +get-tsconfig@^4.7.5: + version "4.10.1" + resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.10.1.tgz#d34c1c01f47d65a606c37aa7a177bc3e56ab4b2e" + integrity sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ== + dependencies: + resolve-pkg-maps "^1.0.0" + +glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" + integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^5.0.1" + once "^1.3.0" + +gopd@^1.0.1, gopd@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" + integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== + +graceful-fs@^4.1.2, graceful-fs@^4.1.6: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + +hardhat@^2.24.1: + version "2.24.1" + resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.24.1.tgz#08cc2c43210be21eb1e7900123b63f465f656eb7" + integrity sha512-3iwrO2liEGCw1rz/l/mlB1rSNexCc4CFcMj0DlvjXGChzmD3sGUgLwWDOZPf+ya8MEm5ZhO1oprRVmb/wVi0YA== + dependencies: + "@ethereumjs/util" "^9.1.0" + "@ethersproject/abi" "^5.1.2" + "@nomicfoundation/edr" "^0.11.0" + "@nomicfoundation/solidity-analyzer" "^0.1.0" + "@sentry/node" "^5.18.1" + "@types/bn.js" "^5.1.0" + "@types/lru-cache" "^5.1.0" + adm-zip "^0.4.16" + aggregate-error "^3.0.0" + ansi-escapes "^4.3.0" + boxen "^5.1.2" + chokidar "^4.0.0" + ci-info "^2.0.0" + debug "^4.1.1" + enquirer "^2.3.0" + env-paths "^2.2.0" + ethereum-cryptography "^1.0.3" + find-up "^5.0.0" + fp-ts "1.19.3" + fs-extra "^7.0.1" + immutable "^4.0.0-rc.12" + io-ts "1.10.4" + json-stream-stringify "^3.1.4" + keccak "^3.0.2" + lodash "^4.17.11" + micro-eth-signer "^0.14.0" + mnemonist "^0.38.0" + mocha "^10.0.0" + p-map "^4.0.0" + picocolors "^1.1.0" + raw-body "^2.4.1" + resolve "1.17.0" + semver "^6.3.0" + solc "0.8.26" + source-map-support "^0.5.13" + stacktrace-parser "^0.1.10" + tinyglobby "^0.2.6" + tsort "0.0.1" + undici "^5.14.0" + uuid "^8.3.2" + ws "^7.4.6" + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-property-descriptors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" + integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== + dependencies: + es-define-property "^1.0.0" + +has-symbols@^1.0.3, has-symbols@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338" + integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ== + +has-tostringtag@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" + integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== + dependencies: + has-symbols "^1.0.3" + +hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3: + version "1.1.7" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.1" + +hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + +he@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +hmac-drbg@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + +http-errors@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" + integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== + dependencies: + depd "2.0.0" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses "2.0.1" + toidentifier "1.0.1" + +https-proxy-agent@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" + integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== + dependencies: + agent-base "6" + debug "4" + +iconv-lite@0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +ieee754@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + +immutable@^4.0.0-rc.12: + version "4.3.7" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.7.tgz#c70145fc90d89fb02021e65c84eb0226e4e5a381" + integrity sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw== + +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.4, inherits@^2.0.3, inherits@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +io-ts@1.10.4: + version "1.10.4" + resolved "https://registry.yarnpkg.com/io-ts/-/io-ts-1.10.4.tgz#cd5401b138de88e4f920adbcb7026e2d1967e6e2" + integrity sha512-b23PteSnYXSONJ6JQXRAlvJhuw8KOtkqa87W4wDtvMrud/DTJd5X+NpOOI+O/zZwVq6v0VLAaJ+1EDViKEuN9g== + dependencies: + fp-ts "^1.0.0" + +is-arguments@^1.0.4: + version "1.2.0" + resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.2.0.tgz#ad58c6aecf563b78ef2bf04df540da8f5d7d8e1b" + integrity sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA== + dependencies: + call-bound "^1.0.2" + has-tostringtag "^1.0.2" + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-buffer@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" + integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== + +is-callable@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" + integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-generator-function@^1.0.7: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.1.0.tgz#bf3eeda931201394f57b5dba2800f91a238309ca" + integrity sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ== + dependencies: + call-bound "^1.0.3" + get-proto "^1.0.0" + has-tostringtag "^1.0.2" + safe-regex-test "^1.1.0" + +is-glob@^4.0.1, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + +is-regex@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.2.1.tgz#76d70a3ed10ef9be48eb577887d74205bf0cad22" + integrity sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g== + dependencies: + call-bound "^1.0.2" + gopd "^1.2.0" + has-tostringtag "^1.0.2" + hasown "^2.0.2" + +is-typed-array@^1.1.3: + version "1.1.15" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.15.tgz#4bfb4a45b61cee83a5a46fba778e4e8d59c0ce0b" + integrity sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ== + dependencies: + which-typed-array "^1.1.16" + +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + +isomorphic-ws@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz#e5529148912ecb9b451b46ed44d53dae1ce04bbf" + integrity sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw== + +js-sha3@0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" + integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== + +js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +json-stream-stringify@^3.1.4: + version "3.1.6" + resolved "https://registry.yarnpkg.com/json-stream-stringify/-/json-stream-stringify-3.1.6.tgz#ebe32193876fb99d4ec9f612389a8d8e2b5d54d4" + integrity sha512-x7fpwxOkbhFCaJDJ8vb1fBY3DdSa4AlITaz+HHILQJzdPMnHEFjxPwVUi1ALIbcIxDE0PNe/0i7frnY8QnBQog== + +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg== + optionalDependencies: + graceful-fs "^4.1.6" + +keccak@3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.2.tgz#4c2c6e8c54e04f2670ee49fa734eb9da152206e0" + integrity sha512-PyKKjkH53wDMLGrvmRGSNWgmSxZOUqbnXwKL9tmgbFYA1iAYqW21kfR7mZXV0MlESiefxQQE9X9fTa3X+2MPDQ== + dependencies: + node-addon-api "^2.0.0" + node-gyp-build "^4.2.0" + readable-stream "^3.6.0" + +keccak@^3.0.2: + version "3.0.4" + resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.4.tgz#edc09b89e633c0549da444432ecf062ffadee86d" + integrity sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q== + dependencies: + node-addon-api "^2.0.0" + node-gyp-build "^4.2.0" + readable-stream "^3.6.0" + +level-concat-iterator@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/level-concat-iterator/-/level-concat-iterator-3.1.0.tgz#5235b1f744bc34847ed65a50548aa88d22e881cf" + integrity sha512-BWRCMHBxbIqPxJ8vHOvKUsaO0v1sLYZtjN3K2iZJsRBYtp+ONsY6Jfi6hy9K3+zolgQRryhIn2NRZjZnWJ9NmQ== + dependencies: + catering "^2.1.0" + +level-supports@^2.0.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/level-supports/-/level-supports-2.1.0.tgz#9af908d853597ecd592293b2fad124375be79c5f" + integrity sha512-E486g1NCjW5cF78KGPrMDRBYzPuueMZ6VBXHT6gC7A8UYWGiM14fGgp+s/L1oFfDWSPV/+SFkYCmZ0SiESkRKA== + +level-supports@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/level-supports/-/level-supports-4.0.1.tgz#431546f9d81f10ff0fea0e74533a0e875c08c66a" + integrity sha512-PbXpve8rKeNcZ9C1mUicC9auIYFyGpkV9/i6g76tLgANwWhtG2v7I4xNBUlkn3lE2/dZF3Pi0ygYGtLc4RXXdA== + +level-transcoder@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/level-transcoder/-/level-transcoder-1.0.1.tgz#f8cef5990c4f1283d4c86d949e73631b0bc8ba9c" + integrity sha512-t7bFwFtsQeD8cl8NIoQ2iwxA0CL/9IFw7/9gAjOonH0PWTTiRfY7Hq+Ejbsxh86tXobDQ6IOiddjNYIfOBs06w== + dependencies: + buffer "^6.0.3" + module-error "^1.0.1" + +leveldown@6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/leveldown/-/leveldown-6.1.0.tgz#7ab1297706f70c657d1a72b31b40323aa612b9ee" + integrity sha512-8C7oJDT44JXxh04aSSsfcMI8YiaGRhOFI9/pMEL7nWJLVsWajDPTRxsSHTM2WcTVY5nXM+SuRHzPPi0GbnDX+w== + dependencies: + abstract-leveldown "^7.2.0" + napi-macros "~2.0.0" + node-gyp-build "^4.3.0" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash@^4.17.11, lodash@^4.17.14: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +log-symbols@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + +lru_map@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd" + integrity sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ== + +math-intrinsics@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9" + integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g== + +memorystream@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" + integrity sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw== + +micro-eth-signer@^0.14.0: + version "0.14.0" + resolved "https://registry.yarnpkg.com/micro-eth-signer/-/micro-eth-signer-0.14.0.tgz#8aa1fe997d98d6bdf42f2071cef7eb01a66ecb22" + integrity sha512-5PLLzHiVYPWClEvZIXXFu5yutzpadb73rnQCpUqIHu3No3coFuWQNfE5tkBQJ7djuLYl6aRLaS0MgWJYGoqiBw== + dependencies: + "@noble/curves" "~1.8.1" + "@noble/hashes" "~1.7.1" + micro-packed "~0.7.2" + +micro-packed@~0.7.2: + version "0.7.3" + resolved "https://registry.yarnpkg.com/micro-packed/-/micro-packed-0.7.3.tgz#59e96b139dffeda22705c7a041476f24cabb12b6" + integrity sha512-2Milxs+WNC00TRlem41oRswvw31146GiSaoCT7s3Xi2gMUglW5QBeqlQaZeHr5tJx9nm3i57LNXPqxOOaWtTYg== + dependencies: + "@scure/base" "~1.2.5" + +minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== + +minimatch@^5.0.1, minimatch@^5.1.6: + version "5.1.6" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" + integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== + dependencies: + brace-expansion "^2.0.1" + +mnemonist@^0.38.0: + version "0.38.5" + resolved "https://registry.yarnpkg.com/mnemonist/-/mnemonist-0.38.5.tgz#4adc7f4200491237fe0fa689ac0b86539685cade" + integrity sha512-bZTFT5rrPKtPJxj8KSV0WkPyNxl72vQepqqVUAW2ARUpUSF2qXMB6jZj7hW5/k7C1rtpzqbD/IIbJwLXUjCHeg== + dependencies: + obliterator "^2.0.0" + +mocha@^10.0.0: + version "10.8.2" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.8.2.tgz#8d8342d016ed411b12a429eb731b825f961afb96" + integrity sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg== + dependencies: + ansi-colors "^4.1.3" + browser-stdout "^1.3.1" + chokidar "^3.5.3" + debug "^4.3.5" + diff "^5.2.0" + escape-string-regexp "^4.0.0" + find-up "^5.0.0" + glob "^8.1.0" + he "^1.2.0" + js-yaml "^4.1.0" + log-symbols "^4.1.0" + minimatch "^5.1.6" + ms "^2.1.3" + serialize-javascript "^6.0.2" + strip-json-comments "^3.1.1" + supports-color "^8.1.1" + workerpool "^6.5.1" + yargs "^16.2.0" + yargs-parser "^20.2.9" + yargs-unparser "^2.0.0" + +module-error@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/module-error/-/module-error-1.0.2.tgz#8d1a48897ca883f47a45816d4fb3e3c6ba404d86" + integrity sha512-0yuvsqSCv8LbaOKhnsQ/T5JhyFlCYLPXK3U2sgV10zoKQwzs/MyfuQUOZQ1V/6OCOJsK/TRgNVrPuPDqtdMFtA== + +ms@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +napi-macros@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/napi-macros/-/napi-macros-2.0.0.tgz#2b6bae421e7b96eb687aa6c77a7858640670001b" + integrity sha512-A0xLykHtARfueITVDernsAWdtIMbOJgKgcluwENp3AlsKN/PloyO10HtmoqnFAQAcxPkgZN7wdfPfEd0zNGxbg== + +node-addon-api@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" + integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA== + +node-fetch@^2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== + dependencies: + whatwg-url "^5.0.0" + +node-gyp-build@4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.4.0.tgz#42e99687ce87ddeaf3a10b99dc06abc11021f3f4" + integrity sha512-amJnQCcgtRVw9SvoebO3BKGESClrfXGCUTX9hSn1OuGQTQBOZmVd0Z0OlecpuRksKvbsUqALE8jls/ErClAPuQ== + +node-gyp-build@^4.2.0, node-gyp-build@^4.3.0: + version "4.8.0" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.8.0.tgz#3fee9c1731df4581a3f9ead74664369ff00d26dd" + integrity sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og== + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +obliterator@^2.0.0: + version "2.0.5" + resolved "https://registry.yarnpkg.com/obliterator/-/obliterator-2.0.5.tgz#031e0145354b0c18840336ae51d41e7d6d2c76aa" + integrity sha512-42CPE9AhahZRsMNslczq0ctAEtqk8Eka26QofnqC346BZdHDySk3LWka23LI7ULIw11NmltpiLagIq8gBozxTw== + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +p-map@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" + integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== + dependencies: + aggregate-error "^3.0.0" + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-parse@^1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +picocolors@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" + integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== + +picomatch@^2.0.4, picomatch@^2.2.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +picomatch@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.2.tgz#77c742931e8f3b8820946c76cd0c1f13730d1dab" + integrity sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg== + +possible-typed-array-names@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz#93e3582bc0e5426586d9d07b79ee40fc841de4ae" + integrity sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg== + +queue-microtask@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +raw-body@^2.4.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" + integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA== + dependencies: + bytes "3.1.2" + http-errors "2.0.0" + iconv-lite "0.4.24" + unpipe "1.0.0" + +readable-stream@^3.6.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readdirp@^4.0.1: + version "4.1.2" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-4.1.2.tgz#eb85801435fbf2a7ee58f19e0921b068fc69948d" + integrity sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg== + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +resolve-pkg-maps@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" + integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== + +resolve@1.17.0: + version "1.17.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" + integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== + dependencies: + path-parse "^1.0.6" + +safe-buffer@^5.1.0, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safe-regex-test@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.1.0.tgz#7f87dfb67a3150782eaaf18583ff5d1711ac10c1" + integrity sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + is-regex "^1.2.1" + +"safer-buffer@>= 2.1.2 < 3": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +secp256k1@4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-4.0.3.tgz#c4559ecd1b8d3c1827ed2d1b94190d69ce267303" + integrity sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA== + dependencies: + elliptic "^6.5.4" + node-addon-api "^2.0.0" + node-gyp-build "^4.2.0" + +semver@^5.5.0: + version "5.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== + +semver@^6.3.0: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +serialize-javascript@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" + integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g== + dependencies: + randombytes "^2.1.0" + +set-function-length@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" + integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== + dependencies: + define-data-property "^1.1.4" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + gopd "^1.0.1" + has-property-descriptors "^1.0.2" + +setimmediate@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== + +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== + +solc@0.8.26: + version "0.8.26" + resolved "https://registry.yarnpkg.com/solc/-/solc-0.8.26.tgz#afc78078953f6ab3e727c338a2fefcd80dd5b01a" + integrity sha512-yiPQNVf5rBFHwN6SIf3TUUvVAFKcQqmSUFeq+fb6pNRCo0ZCgpYOZDi3BVoezCPIAcKrVYd/qXlBLUP9wVrZ9g== + dependencies: + command-exists "^1.2.8" + commander "^8.1.0" + follow-redirects "^1.12.1" + js-sha3 "0.8.0" + memorystream "^0.3.1" + semver "^5.5.0" + tmp "0.0.33" + +source-map-support@^0.5.13: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +stacktrace-parser@^0.1.10: + version "0.1.11" + resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.11.tgz#c7c08f9b29ef566b9a6f7b255d7db572f66fabc4" + integrity sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg== + dependencies: + type-fest "^0.7.1" + +statuses@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + +string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-color@^8.1.1: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +tinyglobby@^0.2.6: + version "0.2.12" + resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.12.tgz#ac941a42e0c5773bd0b5d08f32de82e74a1a61b5" + integrity sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww== + dependencies: + fdir "^6.4.3" + picomatch "^4.0.2" + +tmp@0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + dependencies: + os-tmpdir "~1.0.2" + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== + +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + +tslib@^1.9.3: + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + +tsort@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/tsort/-/tsort-0.0.1.tgz#e2280f5e817f8bf4275657fd0f9aebd44f5a2786" + integrity sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw== + +tsx@^4.19.4: + version "4.19.4" + resolved "https://registry.yarnpkg.com/tsx/-/tsx-4.19.4.tgz#647b4141f4fdd9d773a9b564876773d2846901f4" + integrity sha512-gK5GVzDkJK1SI1zwHf32Mqxf2tSJkNx+eYcNly5+nHvWqXUJYUkWBQtKauoESz3ymezAI++ZwT855x5p5eop+Q== + dependencies: + esbuild "~0.25.0" + get-tsconfig "^4.7.5" + optionalDependencies: + fsevents "~2.3.3" + +type-fest@^0.20.2: + version "0.20.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== + +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + +type-fest@^0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.7.1.tgz#8dda65feaf03ed78f0a3f9678f1869147f7c5c48" + integrity sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg== + +undici-types@~5.26.4: + version "5.26.5" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" + integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== + +undici@^5.14.0: + version "5.28.5" + resolved "https://registry.yarnpkg.com/undici/-/undici-5.28.5.tgz#b2b94b6bf8f1d919bc5a6f31f2c01deb02e54d4b" + integrity sha512-zICwjrDrcrUE0pyyJc1I2QzBkLM8FINsgOrt6WjA+BgajVq9Nxu2PbFFXUrAggLfDXlZGZBVZYw7WNV5KiBiBA== + dependencies: + "@fastify/busboy" "^2.0.0" + +universalify@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== + +unpipe@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== + +utf-8-validate@5.0.7: + version "5.0.7" + resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.7.tgz#c15a19a6af1f7ad9ec7ddc425747ca28c3644922" + integrity sha512-vLt1O5Pp+flcArHGIyKEQq883nBt8nN8tVBcoL0qUXj2XT1n7p70yGIq2VK98I5FdZ1YHc0wk/koOnHjnXWk1Q== + dependencies: + node-gyp-build "^4.3.0" + +utf-8-validate@6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-6.0.3.tgz#7d8c936d854e86b24d1d655f138ee27d2636d777" + integrity sha512-uIuGf9TWQ/y+0Lp+KGZCMuJWc3N9BHA+l/UmHd/oUHwJJDeysyTRxNQVkbzsIWfGFbRe3OcgML/i0mvVRPOyDA== + dependencies: + node-gyp-build "^4.3.0" + +util-deprecate@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +util@^0.12.5: + version "0.12.5" + resolved "https://registry.yarnpkg.com/util/-/util-0.12.5.tgz#5f17a6059b73db61a875668781a1c2b136bd6fbc" + integrity sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA== + dependencies: + inherits "^2.0.3" + is-arguments "^1.0.4" + is-generator-function "^1.0.7" + is-typed-array "^1.1.3" + which-typed-array "^1.1.2" + +uuid@^8.3.2: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + +web3-core@^4.4.0, web3-core@^4.5.0, web3-core@^4.6.0, web3-core@^4.7.1: + version "4.7.1" + resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-4.7.1.tgz#bc56cd7959fe44ee77139d591211f69851140009" + integrity sha512-9KSeASCb/y6BG7rwhgtYC4CvYY66JfkmGNEYb7q1xgjt9BWfkf09MJPaRyoyT5trdOxYDHkT9tDlypvQWaU8UQ== + dependencies: + web3-errors "^1.3.1" + web3-eth-accounts "^4.3.1" + web3-eth-iban "^4.0.7" + web3-providers-http "^4.2.0" + web3-providers-ws "^4.0.8" + web3-types "^1.10.0" + web3-utils "^4.3.3" + web3-validator "^2.0.6" + optionalDependencies: + web3-providers-ipc "^4.0.7" + +web3-errors@^1.1.3, web3-errors@^1.2.0, web3-errors@^1.3.0, web3-errors@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/web3-errors/-/web3-errors-1.3.1.tgz#163bc4d869f98614760b683d733c3ed1fb415d98" + integrity sha512-w3NMJujH+ZSW4ltIZZKtdbkbyQEvBzyp3JRn59Ckli0Nz4VMsVq8aF1bLWM7A2kuQ+yVEm3ySeNU+7mSRwx7RQ== + dependencies: + web3-types "^1.10.0" + +web3-eth-abi@^4.4.1: + version "4.4.1" + resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-4.4.1.tgz#1dca9d80341b3cd7a1ae07dc98080c2073d62a29" + integrity sha512-60ecEkF6kQ9zAfbTY04Nc9q4eEYM0++BySpGi8wZ2PD1tw/c0SDvsKhV6IKURxLJhsDlb08dATc3iD6IbtWJmg== + dependencies: + abitype "0.7.1" + web3-errors "^1.3.1" + web3-types "^1.10.0" + web3-utils "^4.3.3" + web3-validator "^2.0.6" + +web3-eth-accounts@^4.3.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-4.3.1.tgz#6712ea915940d03d596015a87f9167171e8306a6" + integrity sha512-rTXf+H9OKze6lxi7WMMOF1/2cZvJb2AOnbNQxPhBDssKOllAMzLhg1FbZ4Mf3lWecWfN6luWgRhaeSqO1l+IBQ== + dependencies: + "@ethereumjs/rlp" "^4.0.1" + crc-32 "^1.2.2" + ethereum-cryptography "^2.0.0" + web3-errors "^1.3.1" + web3-types "^1.10.0" + web3-utils "^4.3.3" + web3-validator "^2.0.6" + +web3-eth-contract@^4.5.0, web3-eth-contract@^4.7.2: + version "4.7.2" + resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-4.7.2.tgz#a1851e566ceb4b0da3792ff4d8f7cb6fd91d3401" + integrity sha512-3ETqs2pMNPEAc7BVY/C3voOhTUeJdkf2aM3X1v+edbngJLHAxbvxKpOqrcO0cjXzC4uc2Q8Zpf8n8zT5r0eLnA== + dependencies: + "@ethereumjs/rlp" "^5.0.2" + web3-core "^4.7.1" + web3-errors "^1.3.1" + web3-eth "^4.11.1" + web3-eth-abi "^4.4.1" + web3-types "^1.10.0" + web3-utils "^4.3.3" + web3-validator "^2.0.6" + +web3-eth-ens@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-4.4.0.tgz#bc0d11d755cb15ed4b82e38747c5104622d9a4b9" + integrity sha512-DeyVIS060hNV9g8dnTx92syqvgbvPricE3MerCxe/DquNZT3tD8aVgFfq65GATtpCgDDJffO2bVeHp3XBemnSQ== + dependencies: + "@adraffy/ens-normalize" "^1.8.8" + web3-core "^4.5.0" + web3-errors "^1.2.0" + web3-eth "^4.8.0" + web3-eth-contract "^4.5.0" + web3-net "^4.1.0" + web3-types "^1.7.0" + web3-utils "^4.3.0" + web3-validator "^2.0.6" + +web3-eth-iban@^4.0.7: + version "4.0.7" + resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-4.0.7.tgz#ee504f845d7b6315f0be78fcf070ccd5d38e4aaf" + integrity sha512-8weKLa9KuKRzibC87vNLdkinpUE30gn0IGY027F8doeJdcPUfsa4IlBgNC4k4HLBembBB2CTU0Kr/HAOqMeYVQ== + dependencies: + web3-errors "^1.1.3" + web3-types "^1.3.0" + web3-utils "^4.0.7" + web3-validator "^2.0.3" + +web3-eth-personal@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-4.1.0.tgz#f5b506a4570bf1241d1db2de12cb413ea0bb4486" + integrity sha512-RFN83uMuvA5cu1zIwwJh9A/bAj0OBxmGN3tgx19OD/9ygeUZbifOL06jgFzN0t+1ekHqm3DXYQM8UfHpXi7yDQ== + dependencies: + web3-core "^4.6.0" + web3-eth "^4.9.0" + web3-rpc-methods "^1.3.0" + web3-types "^1.8.0" + web3-utils "^4.3.1" + web3-validator "^2.0.6" + +web3-eth@^4.11.1, web3-eth@^4.8.0, web3-eth@^4.9.0: + version "4.11.1" + resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-4.11.1.tgz#f558ab1482d4196de0f0a7da5985de42d06664ea" + integrity sha512-q9zOkzHnbLv44mwgLjLXuyqszHuUgZWsQayD2i/rus2uk0G7hMn11bE2Q3hOVnJS4ws4VCtUznlMxwKQ+38V2w== + dependencies: + setimmediate "^1.0.5" + web3-core "^4.7.1" + web3-errors "^1.3.1" + web3-eth-abi "^4.4.1" + web3-eth-accounts "^4.3.1" + web3-net "^4.1.0" + web3-providers-ws "^4.0.8" + web3-rpc-methods "^1.3.0" + web3-types "^1.10.0" + web3-utils "^4.3.3" + web3-validator "^2.0.6" + +web3-net@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-4.1.0.tgz#db7bde675e58b153339e4f149f29ec0410d6bab2" + integrity sha512-WWmfvHVIXWEoBDWdgKNYKN8rAy6SgluZ0abyRyXOL3ESr7ym7pKWbfP4fjApIHlYTh8tNqkrdPfM4Dyi6CA0SA== + dependencies: + web3-core "^4.4.0" + web3-rpc-methods "^1.3.0" + web3-types "^1.6.0" + web3-utils "^4.3.0" + +web3-providers-http@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-4.2.0.tgz#0f4bf424681a068d49994aa7fabc69bed45ac50b" + integrity sha512-IPMnDtHB7dVwaB7/mMxAZzyq7d5ezfO1+Vw0bNfAeIi7gaDlJiggp85SdyAfOgov8AMUA/dyiY72kQ0KmjXKvQ== + dependencies: + cross-fetch "^4.0.0" + web3-errors "^1.3.0" + web3-types "^1.7.0" + web3-utils "^4.3.1" + +web3-providers-ipc@^4.0.7: + version "4.0.7" + resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-4.0.7.tgz#9ec4c8565053af005a5170ba80cddeb40ff3e3d3" + integrity sha512-YbNqY4zUvIaK2MHr1lQFE53/8t/ejHtJchrWn9zVbFMGXlTsOAbNoIoZWROrg1v+hCBvT2c9z8xt7e/+uz5p1g== + dependencies: + web3-errors "^1.1.3" + web3-types "^1.3.0" + web3-utils "^4.0.7" + +web3-providers-ws@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-4.0.8.tgz#6de7b262f7ec6df1a2dff466ba91d7ebdac2c45e" + integrity sha512-goJdgata7v4pyzHRsg9fSegUG4gVnHZSHODhNnn6J93ykHkBI1nz4fjlGpcQLUMi4jAMz6SHl9Ibzs2jj9xqPw== + dependencies: + "@types/ws" "8.5.3" + isomorphic-ws "^5.0.0" + web3-errors "^1.2.0" + web3-types "^1.7.0" + web3-utils "^4.3.1" + ws "^8.17.1" + +web3-rpc-methods@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/web3-rpc-methods/-/web3-rpc-methods-1.3.0.tgz#d5ee299a69389d63822d354ddee2c6a121a6f670" + integrity sha512-/CHmzGN+IYgdBOme7PdqzF+FNeMleefzqs0LVOduncSaqsppeOEoskLXb2anSpzmQAP3xZJPaTrkQPWSJMORig== + dependencies: + web3-core "^4.4.0" + web3-types "^1.6.0" + web3-validator "^2.0.6" + +web3-rpc-providers@^1.0.0-rc.4: + version "1.0.0-rc.4" + resolved "https://registry.yarnpkg.com/web3-rpc-providers/-/web3-rpc-providers-1.0.0-rc.4.tgz#93cec88175eb2f7972e12be30af4c2f296b1923f" + integrity sha512-PXosCqHW0EADrYzgmueNHP3Y5jcSmSwH+Dkqvn7EYD0T2jcsdDAIHqk6szBiwIdhumM7gv9Raprsu/s/f7h1fw== + dependencies: + web3-errors "^1.3.1" + web3-providers-http "^4.2.0" + web3-providers-ws "^4.0.8" + web3-types "^1.10.0" + web3-utils "^4.3.3" + web3-validator "^2.0.6" + +web3-types@^1.10.0, web3-types@^1.3.0, web3-types@^1.6.0, web3-types@^1.7.0, web3-types@^1.8.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/web3-types/-/web3-types-1.10.0.tgz#41b0b4d2dd75e919d5b6f37bf139e29f445db04e" + integrity sha512-0IXoaAFtFc8Yin7cCdQfB9ZmjafrbP6BO0f0KT/khMhXKUpoJ6yShrVhiNpyRBo8QQjuOagsWzwSK2H49I7sbw== + +web3-utils@^4.0.7, web3-utils@^4.3.0, web3-utils@^4.3.1, web3-utils@^4.3.3: + version "4.3.3" + resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-4.3.3.tgz#e380a1c03a050d3704f94bd08c1c9f50a1487205" + integrity sha512-kZUeCwaQm+RNc2Bf1V3BYbF29lQQKz28L0y+FA4G0lS8IxtJVGi5SeDTUkpwqqkdHHC7JcapPDnyyzJ1lfWlOw== + dependencies: + ethereum-cryptography "^2.0.0" + eventemitter3 "^5.0.1" + web3-errors "^1.3.1" + web3-types "^1.10.0" + web3-validator "^2.0.6" + +web3-validator@^2.0.3, web3-validator@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/web3-validator/-/web3-validator-2.0.6.tgz#a0cdaa39e1d1708ece5fae155b034e29d6a19248" + integrity sha512-qn9id0/l1bWmvH4XfnG/JtGKKwut2Vokl6YXP5Kfg424npysmtRLe9DgiNBM9Op7QL/aSiaA0TVXibuIuWcizg== + dependencies: + ethereum-cryptography "^2.0.0" + util "^0.12.5" + web3-errors "^1.2.0" + web3-types "^1.6.0" + zod "^3.21.4" + +web3@^4.16.0: + version "4.16.0" + resolved "https://registry.yarnpkg.com/web3/-/web3-4.16.0.tgz#1da10d8405bf27a76de6cbbce3de9fa93f7c0449" + integrity sha512-SgoMSBo6EsJ5GFCGar2E/pR2lcR/xmUSuQ61iK6yDqzxmm42aPPxSqZfJz2z/UCR6pk03u77pU8TGV6lgMDdIQ== + dependencies: + web3-core "^4.7.1" + web3-errors "^1.3.1" + web3-eth "^4.11.1" + web3-eth-abi "^4.4.1" + web3-eth-accounts "^4.3.1" + web3-eth-contract "^4.7.2" + web3-eth-ens "^4.4.0" + web3-eth-iban "^4.0.7" + web3-eth-personal "^4.1.0" + web3-net "^4.1.0" + web3-providers-http "^4.2.0" + web3-providers-ws "^4.0.8" + web3-rpc-methods "^1.3.0" + web3-rpc-providers "^1.0.0-rc.4" + web3-types "^1.10.0" + web3-utils "^4.3.3" + web3-validator "^2.0.6" + +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + +which-typed-array@^1.1.16, which-typed-array@^1.1.2: + version "1.1.19" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.19.tgz#df03842e870b6b88e117524a4b364b6fc689f956" + integrity sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw== + dependencies: + available-typed-arrays "^1.0.7" + call-bind "^1.0.8" + call-bound "^1.0.4" + for-each "^0.3.5" + get-proto "^1.0.1" + gopd "^1.2.0" + has-tostringtag "^1.0.2" + +widest-line@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca" + integrity sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg== + dependencies: + string-width "^4.0.0" + +workerpool@^6.5.1: + version "6.5.1" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.5.1.tgz#060f73b39d0caf97c6db64da004cd01b4c099544" + integrity sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA== + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +ws@8.13.0: + version "8.13.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0" + integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA== + +ws@^7.4.6: + version "7.5.10" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9" + integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ== + +ws@^8.17.1: + version "8.18.2" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.2.tgz#42738b2be57ced85f46154320aabb51ab003705a" + integrity sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yargs-parser@^20.2.2, yargs-parser@^20.2.9: + version "20.2.9" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== + +yargs-unparser@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" + integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== + dependencies: + camelcase "^6.0.0" + decamelize "^4.0.0" + flat "^5.0.2" + is-plain-obj "^2.1.0" + +yargs@^16.2.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + +zod@^3.21.4: + version "3.25.48" + resolved "https://registry.yarnpkg.com/zod/-/zod-3.25.48.tgz#6c2b536fbb519905e8f4a4ac58743de4d5331bb2" + integrity sha512-0X1mz8FtgEIvaxGjdIImYpZEaZMrund9pGXm3M6vM7Reba0e2eI71KPjSCGXBfwKDPwPoywf6waUKc3/tFvX2Q==