From 0c1cb996d768af2cfe3203e57aacb416ff082d96 Mon Sep 17 00:00:00 2001 From: Anna Mukharram Date: Tue, 7 Jul 2026 09:33:43 +0400 Subject: [PATCH 01/30] feat: srv3 acceptance tests --- brownie-config.yml | 1 + configs/config_mainnet.py | 226 +- interfaces/Accounting.json | 631 +++-- interfaces/AccountingOracle.json | 52 +- interfaces/CSEjector.json | 756 +++++- interfaces/CSFeeOracle.json | 1351 +++++++++- interfaces/CSParametersRegistry.json | 2386 ++++++++++++++++- interfaces/ConsolidationBus.json | 873 ++++++ interfaces/ConsolidationGateway.json | 851 ++++++ interfaces/ConsolidationMigrator.json | 764 ++++++ interfaces/Lido.json | 270 +- interfaces/LidoLocator.json | 36 + interfaces/OracleReportSanityChecker.json | 710 ++++- interfaces/StakingRouter.json | 908 +++++-- interfaces/TopUpGateway.json | 1041 +++++++ interfaces/UpgradeVoteScript.json | 266 ++ interfaces/WithdrawalVault.json | 122 +- scripts/upgrade_2026_04_30_srv3_cmv2.py | 227 ++ tests/acceptance/test_accounting_oracle.py | 44 +- .../test_accounting_oracle_negative.py | 195 +- tests/acceptance/test_burner.py | 16 +- tests/acceptance/test_consolidation.py | 257 ++ tests/acceptance/test_csm.py | 66 +- tests/acceptance/test_dsm.py | 6 +- tests/acceptance/test_lido.py | 77 +- tests/acceptance/test_locator.py | 5 + .../test_node_operators_registry.py | 97 +- .../test_oracle_report_sanity_checker.py | 56 +- tests/acceptance/test_simple_dvt_module.py | 17 +- tests/acceptance/test_staking_router.py | 95 +- tests/acceptance/test_top_up_gateway.py | 171 ++ tests/acceptance/test_veb_negative.py | 78 +- tests/acceptance/test_veb_oracle.py | 25 +- tests/acceptance/test_withdrawal_queue.py | 11 +- tests/acceptance/test_withdrawal_vault.py | 16 +- tests/acceptance/test_withdrawals_negative.py | 20 +- utils/config.py | 18 +- utils/dual_governance.py | 104 +- utils/test/exit_bus_data.py | 37 +- utils/test/helpers.py | 12 + utils/test/oracle_report_helpers.py | 192 +- 41 files changed, 12038 insertions(+), 1048 deletions(-) create mode 100644 interfaces/ConsolidationBus.json create mode 100644 interfaces/ConsolidationGateway.json create mode 100644 interfaces/ConsolidationMigrator.json create mode 100644 interfaces/TopUpGateway.json create mode 100644 interfaces/UpgradeVoteScript.json create mode 100644 scripts/upgrade_2026_04_30_srv3_cmv2.py create mode 100644 tests/acceptance/test_consolidation.py create mode 100644 tests/acceptance/test_top_up_gateway.py diff --git a/brownie-config.yml b/brownie-config.yml index 98db6cfb..c7acdf8e 100644 --- a/brownie-config.yml +++ b/brownie-config.yml @@ -5,6 +5,7 @@ dependencies: networks: default: mainnet-fork development: + gas_limit: auto priority_fee: auto live: priority_fee: auto diff --git a/configs/config_mainnet.py b/configs/config_mainnet.py index bd775a68..aef4e75f 100644 --- a/configs/config_mainnet.py +++ b/configs/config_mainnet.py @@ -32,7 +32,9 @@ LIDO_IMPL_V1 = "0x47EbaB13B806773ec2A2d16873e2dF770D130b50" LEGACY_ORACLE_IMPL_V1 = "0x1430194905301504e8830ce4B0b0df7187E84AbD" -NODE_OPERATORS_REGISTRY_IMPL_V1 = "0x5d39ABaa161e622B99D45616afC8B837E9F19a25" # was used in archived tests +NODE_OPERATORS_REGISTRY_IMPL_V1 = ( + "0x5d39ABaa161e622B99D45616afC8B837E9F19a25" # was used in archived tests +) VALIDATOR_EXIT_VERIFIER = "0xbDb567672c867DB533119C2dcD4FB9d8b44EC82f" # Aragon APM Repos @@ -64,22 +66,46 @@ EASYTRACK = "0xF0211b7660680B49De1A7E9f25C65660F0a13Fea" EASYTRACK_EVMSCRIPT_EXECUTOR = "0xFE5986E06210aC1eCC1aDCafc0cc7f8D63B3F977" -EASYTRACK_INCREASE_NOP_STAKING_LIMIT_FACTORY = "0xFeBd8FAC16De88206d4b18764e826AF38546AfE0" +EASYTRACK_INCREASE_NOP_STAKING_LIMIT_FACTORY = ( + "0xFeBd8FAC16De88206d4b18764e826AF38546AfE0" +) EASYTRACK_SIMPLE_DVT_TRUSTED_CALLER = "0x08637515E85A4633E23dfc7861e2A9f53af640f7" -EASYTRACK_SIMPLE_DVT_ADD_NODE_OPERATORS_FACTORY = "0xcAa3AF7460E83E665EEFeC73a7a542E5005C9639" -EASYTRACK_SIMPLE_DVT_ACTIVATE_NODE_OPERATORS_FACTORY = "0xCBb418F6f9BFd3525CE6aADe8F74ECFEfe2DB5C8" -EASYTRACK_SIMPLE_DVT_DEACTIVATE_NODE_OPERATORS_FACTORY = "0x8B82C1546D47330335a48406cc3a50Da732672E7" -EASYTRACK_SIMPLE_DVT_SET_VETTED_VALIDATORS_LIMITS_FACTORY = "0xD75778b855886Fc5e1eA7D6bFADA9EB68b35C19D" -EASYTRACK_SIMPLE_DVT_SET_NODE_OPERATOR_NAMES_FACTORY = "0x7d509BFF310d9460b1F613e4e40d342201a83Ae4" -EASYTRACK_SIMPLE_DVT_SET_NODE_OPERATOR_REWARD_ADDRESSES_FACTORY = "0x589e298964b9181D9938B84bB034C3BB9024E2C0" -EASYTRACK_SIMPLE_DVT_UPDATE_TARGET_VALIDATOR_LIMITS_FACTORY = "0x161a4552A625844c822954C5AcBac928ee0f399B" -EASYTRACK_SIMPLE_DVT_CHANGE_NODE_OPERATOR_MANAGERS_FACTORY = "0xE31A0599A6772BCf9b2bFc9e25cf941e793c9a7D" -EASYTRACK_CSM_SETTLE_EL_REWARDS_STEALING_PENALTY_FACTORY = "0xF6B6E7997338C48Ea3a8BCfa4BB64a315fDa76f4" +EASYTRACK_SIMPLE_DVT_ADD_NODE_OPERATORS_FACTORY = ( + "0xcAa3AF7460E83E665EEFeC73a7a542E5005C9639" +) +EASYTRACK_SIMPLE_DVT_ACTIVATE_NODE_OPERATORS_FACTORY = ( + "0xCBb418F6f9BFd3525CE6aADe8F74ECFEfe2DB5C8" +) +EASYTRACK_SIMPLE_DVT_DEACTIVATE_NODE_OPERATORS_FACTORY = ( + "0x8B82C1546D47330335a48406cc3a50Da732672E7" +) +EASYTRACK_SIMPLE_DVT_SET_VETTED_VALIDATORS_LIMITS_FACTORY = ( + "0xD75778b855886Fc5e1eA7D6bFADA9EB68b35C19D" +) +EASYTRACK_SIMPLE_DVT_SET_NODE_OPERATOR_NAMES_FACTORY = ( + "0x7d509BFF310d9460b1F613e4e40d342201a83Ae4" +) +EASYTRACK_SIMPLE_DVT_SET_NODE_OPERATOR_REWARD_ADDRESSES_FACTORY = ( + "0x589e298964b9181D9938B84bB034C3BB9024E2C0" +) +EASYTRACK_SIMPLE_DVT_UPDATE_TARGET_VALIDATOR_LIMITS_FACTORY = ( + "0x161a4552A625844c822954C5AcBac928ee0f399B" +) +EASYTRACK_SIMPLE_DVT_CHANGE_NODE_OPERATOR_MANAGERS_FACTORY = ( + "0xE31A0599A6772BCf9b2bFc9e25cf941e793c9a7D" +) +EASYTRACK_CSM_SETTLE_EL_REWARDS_STEALING_PENALTY_FACTORY = ( + "0xF6B6E7997338C48Ea3a8BCfa4BB64a315fDa76f4" +) EASYTRACK_MEV_BOOST_ADD_RELAYS_FACTORY = "0x00A3D6260f70b1660c8646Ef25D0820EFFd7bE60" EASYTRACK_MEV_BOOST_REMOVE_RELAYS_FACTORY = "0x9721c0f77E3Ea40eD592B9DCf3032DaF269c0306" EASYTRACK_MEV_BOOST_EDIT_RELAYS_FACTORY = "0x6b7863f2c7dEE99D3b744fDAEDbEB1aeCC025535" -EASYTRACK_CURATED_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY = "0x4F716AD3Cc7A3A5cdA2359e5B2c84335c171dCde" -EASYTRACK_SIMPLE_DVT_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY = "0x58A59dDC6Aea9b1D5743D024E15DfA4badB56E37" +EASYTRACK_CURATED_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY = ( + "0x4F716AD3Cc7A3A5cdA2359e5B2c84335c171dCde" +) +EASYTRACK_SIMPLE_DVT_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY = ( + "0x58A59dDC6Aea9b1D5743D024E15DfA4badB56E37" +) EASYTRACK_CS_SET_VETTED_GATE_TREE_FACTORY = "0xBc5642bDD6F2a54b01A75605aAe9143525D97308" # Liquidity Observation Lab (LOL) stETH AllowedRecipientsRegistry @@ -116,7 +142,7 @@ # LidoLocator LIDO_LOCATOR = "0xC1d0b3DE6792Bf6b4b37EccdcC24e45978Cfd2Eb" -LIDO_LOCATOR_IMPL = "0x2f8779042EFaEd4c53db2Ce293eB6B3f7096C72d" +LIDO_LOCATOR_IMPL = "0x9E6b222a71644484b6E9eb67bD8400128e0c3fb8" # SRV3 # Other upgrade addresses LIDO_V2_UPGRADE_TEMPLATE = "0xa818fF9EC93122Bf9401ab4340C42De638CD600a" @@ -126,24 +152,34 @@ DEPLOYER_EOA = "0x8Ea83AD72396f1E0cD2f8E72b1461db8Eb6aF7B5" # 0x01...withdrawal_vault or Lido.getWithdrawalCredentials() -WITHDRAWAL_CREDENTIALS = "0x010000000000000000000000b9d7934878b5fb9610b3fe8a5e441e8fad7e293f" +WITHDRAWAL_CREDENTIALS = ( + "0x010000000000000000000000b9d7934878b5fb9610b3fe8a5e441e8fad7e293f" +) # Lido -LIDO_IMPL = "0x6ca84080381E43938476814be61B779A8bB6a600" +LIDO_IMPL = "0x59deCAF1289BbF615Ac8b1024127eC7FF842aB01" # SRV3 # see Lido's proxy appId() -LIDO_ARAGON_APP_ID = "0x3ca7c3e38968823ccb4c78ea688df41356f182ae1d159e4ee608d30d68cef320" +LIDO_ARAGON_APP_ID = ( + "0x3ca7c3e38968823ccb4c78ea688df41356f182ae1d159e4ee608d30d68cef320" +) LIDO_MAX_STAKE_LIMIT_ETH = 150_000 +# set by finalizeUpgrade_v4 (upgrade-params-mainnet.toml [lido].depositsReserveTarget) +LIDO_DEPOSITS_RESERVE_TARGET = 1_500 * 10**18 # 1500 ETH # SRV3 # LegacyOracle (former LidoOracle) ## address is LIDO_LEGACY_ORACLE LEGACY_ORACLE_IMPL = "0xa29b819654cE6224A222bb5f586920105E2D7E0E" ## see LidoOracle's proxy appId() -ORACLE_ARAGON_APP_ID = "0x8b47ba2a8454ec799cd91646e7ec47168e91fd139b23f017455f3e5898aaba93" +ORACLE_ARAGON_APP_ID = ( + "0x8b47ba2a8454ec799cd91646e7ec47168e91fd139b23f017455f3e5898aaba93" +) # NodeOperatorsRegistry aka Curated Staking Module NODE_OPERATORS_REGISTRY_IMPL = "0x6828b023e737f96B168aCd0b5c6351971a4F81aE" ## see NodeOperatorsRegistry's proxy appId() -NODE_OPERATORS_REGISTRY_ARAGON_APP_ID = "0x7071f283424072341f856ac9e947e7ec0eb68719f757a7e785979b6b8717579d" +NODE_OPERATORS_REGISTRY_ARAGON_APP_ID = ( + "0x7071f283424072341f856ac9e947e7ec0eb68719f757a7e785979b6b8717579d" +) NODE_OPERATORS_REGISTRY_VERSION = 4 NOR_EXIT_DEADLINE_IN_SEC = 172800 @@ -163,12 +199,32 @@ CURATED_STAKING_MODULE_MAX_DEPOSITS_PER_BLOCK = 150 CURATED_STAKING_MODULE_MIN_DEPOSITS_BLOCK_DISTANCE = 25 +# Curated Module v2 — added by the SRv3/CMv2 upgrade via StakingRouter.addStakingModule. +# Values mirror UpgradeConfig.getCuratedModuleConfig() (see core deployed-*.json `curatedModule`). +# It is appended after the existing 3 modules (Curated=1, SimpleDVT=2, CSM=3), so its id is 4. +CURATED_V2_STAKING_MODULE_ID = 4 +CURATED_V2_STAKING_MODULE_ADDRESS = "0x1A54c1b37CB228e506838486592D54Bec5Bb3747" # SRV3 +CURATED_V2_STAKING_MODULE_NAME = "curated-onchain-v2" +CURATED_V2_STAKING_MODULE_TARGET_SHARE_BP = 10000 +CURATED_V2_STAKING_MODULE_PRIORITY_EXIT_SHARE_THRESHOLD = 10000 +CURATED_V2_STAKING_MODULE_MODULE_FEE_BP = 400 +CURATED_V2_STAKING_MODULE_TREASURY_FEE_BP = 600 +CURATED_V2_STAKING_MODULE_MAX_DEPOSITS_PER_BLOCK = 100 +CURATED_V2_STAKING_MODULE_MIN_DEPOSITS_BLOCK_DISTANCE = 75 +CURATED_V2_ACCOUNTING = "0xFfFEF82624cf7ad1300D084aA547DDa828a95eAd" # SRV3 + +# SRv3/CMv2 upgrade omnibus (UpgradeVoteScript) — the vote script reads its items +# from this contract. Fork-deployed, synced from core/deployed-local.json. +UPGRADE_VOTE_SCRIPT = "0xA2B2Fc588E2B69B781E9DdCE8d8671cd9CbbC224" # SRV3 + # NodeOperatorsRegistry clone aka SimpleDVT SIMPLE_DVT_IMPL = "0x6828b023e737f96B168aCd0b5c6351971a4F81aE" SIMPLE_DVT_REPO = "0x2325b0a607808dE42D918DB07F925FFcCfBb2968" ## see SimpleDVT's proxy appId() SIMPLE_DVT_ARAGON_APP_NAME = "simple-dvt" -SIMPLE_DVT_ARAGON_APP_ID = "0xe1635b63b5f7b5e545f2a637558a4029dea7905361a2f0fc28c66e9136cf86a4" +SIMPLE_DVT_ARAGON_APP_ID = ( + "0xe1635b63b5f7b5e545f2a637558a4029dea7905361a2f0fc28c66e9136cf86a4" +) SIMPLE_DVT_MODULE_STUCK_PENALTY_DELAY = 0 SIMPLE_DVT_MODULE_TARGET_SHARE_BP = 430 SIMPLE_DVT_MODULE_MODULE_FEE_BP = 800 @@ -186,6 +242,9 @@ # CSM CS_ORACLE_EPOCHS_PER_FRAME = 225 * 28 # 28 days +CS_FEE_ORACLE_CONSENSUS_VERSION = ( + 4 # SRV3: set by FeeOracle.finalizeUpgradeV3(consensusVersion) +) CS_MODULE_ID = 3 CS_MODULE_NAME = "Community Staking" CS_MODULE_MODULE_FEE_BP = 600 @@ -195,6 +254,8 @@ CS_MODULE_MAX_DEPOSITS_PER_BLOCK = 30 CS_MODULE_MIN_DEPOSIT_BLOCK_DISTANCE = 25 +# CMV2 + # OracleDaemonConfig ORACLE_DAEMON_CONFIG = "0xbf05A929c3D7885a6aeAd833a992dA6E5ac23b09" NORMALIZED_CL_REWARD_PER_EPOCH = 64 @@ -209,7 +270,7 @@ EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS = 14 * 7200 # 14 days # OracleReportSanityChecker -ORACLE_REPORT_SANITY_CHECKER = "0xf1647c86E6D7959f638DD9CE1d90e2F3C9503129" +ORACLE_REPORT_SANITY_CHECKER = "0xD63E39dD4EC7BFB901C7a77aa0470E1D9aD67FF8" # SRV3 APPEARED_VALIDATORS_PER_DAY_LIMIT = 1800 EXITED_VALIDATORS_PER_DAY_LIMIT = 3600 ANNUAL_BALANCE_INCREASE_BP_LIMIT = 1000 # 10% @@ -223,14 +284,26 @@ INACTIVITY_PENALTIES_AMOUNT_PWEI = 101 CL_BALANCE_ORACLES_ERROR_UPPER_BP_LIMIT = 50 +EXITED_ETH_AMOUNT_PER_DAY_LIMIT = 57600 +APPEARED_ETH_AMOUNT_PER_DAY_LIMIT = 57600 +MAX_BALANCE_EXIT_REQUESTED_PER_REPORT_IN_ETH = 19200 +MAX_EFFECTIVE_BALANCE_WEIGHT_WC_TYPE_01 = 32 +MAX_EFFECTIVE_BALANCE_WEIGHT_WC_TYPE_02 = 2048 +MAX_CL_BALANCE_DECREASE_BP = 360 +CONSOLIDATION_ETH_AMOUNT_PER_DAY_LIMIT = 93375 +EXITED_VALIDATOR_ETH_AMOUNT_LIMIT = 32 +EXTERNAL_PENDING_BALANCE_CAP_ETH = 300 + # Burner BURNER = "0xE76c52750019b80B43E36DF30bf4060EB73F573a" TOTAL_NON_COVER_SHARES_BURNT = 32145684728326685744 TOTAL_COVER_SHARES_BURNT = 0 # DepositSecurityModule -DEPOSIT_SECURITY_MODULE = "0xfFA96D84dEF2EA035c7AB153D8B991128e3d72fD" -DEPOSIT_SECURITY_MODULE_V2 = "0xC77F8768774E1c9244BEed705C4354f2113CFc09" # dsm address before SR V2 enact +DEPOSIT_SECURITY_MODULE = "0x53fa102681e10C680cb1EdEe1A15ea5630e61Ac5" # SRV3 +DEPOSIT_SECURITY_MODULE_V2 = ( + "0xC77F8768774E1c9244BEed705C4354f2113CFc09" # dsm address before SR V2 enact +) DSM_MAX_OPERATORS_PER_UNVETTING = 200 DSM_PAUSE_INTENT_VALIDITY_PERIOD_BLOCKS = 6646 ## Migrated from LIDO_DEPOSIT_SECURITY_MODULE_V1 @@ -247,23 +320,27 @@ # AccountingOracle # and its corresponding HashConsensus ACCOUNTING_ORACLE = "0x852deD011285fe67063a08005c71a85690503Cee" -ACCOUNTING_ORACLE_IMPL = "0x1455B96780A93e08abFE41243Db92E2fCbb0141c" +ACCOUNTING_ORACLE_IMPL = "0x839cBf32175fC81712dc2c59617C0cd2B5d421cf" # SRV3 HASH_CONSENSUS_FOR_AO = "0xD624B08C83bAECF0807Dd2c6880C3154a5F0B288" AO_EPOCHS_PER_FRAME = 225 AO_FAST_LANE_LENGTH_SLOTS = 100 -AO_CONSENSUS_VERSION = 5 +# set by finalizeUpgrade_v5 (upgrade-params-mainnet.toml [accountingOracle].consensusVersion) +AO_CONSENSUS_VERSION = 6 # SRV3 # ValidatorsExitBusOracle VALIDATORS_EXIT_BUS_ORACLE = "0x0De4Ea0184c2ad0BacA7183356Aea5B8d5Bf5c6e" -VALIDATORS_EXIT_BUS_ORACLE_IMPL = "0x905A211eD6830Cfc95643f0bE2ff64E7f3bf9b94" +VALIDATORS_EXIT_BUS_ORACLE_IMPL = "0x9812525C76ca09F30410c0402aBC612aBc3bCaDc" # SRV3 HASH_CONSENSUS_FOR_VEBO = "0x7FaDB6358950c5fAA66Cb5EB8eE5147De3df355a" VEBO_EPOCHS_PER_FRAME = 45 VEBO_FAST_LANE_LENGTH_SLOTS = 100 -VEBO_CONSENSUS_VERSION = 4 +VEBO_CONSENSUS_VERSION = 5 # SRV3 (finalizeUpgrade_v3) MAX_VALIDATORS_PER_REPORT = 600 MAX_EXIT_REQUESTS_LIMIT = 11200 EXITS_PER_FRAME = 1 FRAME_DURATION_IN_SEC = 48 +# VEBO exit-balance rate limit, set by finalizeUpgrade_v3 (upgrade-params-mainnet.toml [validatorsExitBusOracle]) +VEBO_MAX_EXIT_BALANCE_ETH = 358400 +VEBO_BALANCE_PER_FRAME_ETH = 32 # AccountingOracle and ValidatorsExitBusOracle @@ -300,7 +377,7 @@ # WithdrawalsVault WITHDRAWAL_VAULT_IMPL_V1 = "0xe681faB8851484B57F32143FD78548f25fD59980" -WITHDRAWAL_VAULT_IMPL = "0x7D2BAa6094E1C4B60Da4cbAF4A77C3f4694fD53D" +WITHDRAWAL_VAULT_IMPL = "0xB1cF93F953586f7B9C26B61Ac9342a18C96c27a1" # SRV3 # EIP712StETH EIP712_STETH = "0x8F73e4C2A6D852bb4ab2A45E6a9CF5715b3228B7" @@ -308,9 +385,50 @@ # StakingRouter STAKING_ROUTER = "0xFdDf38947aFB03C621C71b06C9C70bce73f12999" -STAKING_ROUTER_IMPL = "0x226f9265CBC37231882b7409658C18bB7738173A" -STAKING_ROUTER_VERSION = 3 +STAKING_ROUTER_IMPL = "0x6f058a2abc238D775531e1d391d7E0337d024Df7" # SRV3 +STAKING_ROUTER_VERSION = 4 # SRV3 +# Global per-block top-up cap (in Gwei), set by StakingRouter.finalizeUpgrade_v4 +STAKING_ROUTER_MAX_TOP_UP_PER_BLOCK_GWEI = 3200000000000 # SRV3 + +# TopUpGateway +TOP_UP_GATEWAY = "0xaC10e29fFc0e2Ba64c0D91db7EA31fE45FE43E68" # SRV3 +TOP_UP_GATEWAY_IMPL = "0xF9C0092ae1f3B2E08D07ceAD0C2927318e7B3E21" # SRV3 +# initialize() params — upgrade-params-mainnet.toml [topUpGateway] +TOP_UP_GATEWAY_MAX_VALIDATORS_PER_TOP_UP = 32 +TOP_UP_GATEWAY_MIN_BLOCK_DISTANCE = 75 +TOP_UP_GATEWAY_MAX_ROOT_AGE = 600 # seconds +TOP_UP_GATEWAY_TARGET_BALANCE_GWEI = ( + 2_046_750_000_000 # 2046.75 ETH (1.25 ETH margin below MaxEB) +) +TOP_UP_GATEWAY_MIN_TOP_UP_GWEI = 2_000_000_000 # 2 ETH +# sole TOP_UP_ROLE holder (coreUpgrade.topUpGatewayDepositor, stable deploy input) +TOP_UP_GATEWAY_DEPOSITOR = "0xF82aC5937A20dC862F9bc0668779031E06000f17" +# CircuitBreaker — TW-upgrade pause hub; the SRv3 vote registers it as pauser for the new gateways +CIRCUIT_BREAKER = "0x6019CB557978296BA3C08a7B73225C0975DFB2F7" + +# ConsolidationGateway — deployed directly (no proxy), admin/limits set in the constructor +CONSOLIDATION_GATEWAY = "0xe446b867936f6E8cbcbf6B680D5db1b1344ee08F" # SRV3 +# constructor params — upgrade-params-mainnet.toml [consolidationGateway] +CONSOLIDATION_GATEWAY_MAX_REQUESTS_LIMIT = 2900 # SRV3 +CONSOLIDATION_GATEWAY_CONSOLIDATIONS_PER_FRAME = 1 # SRV3 +CONSOLIDATION_GATEWAY_FRAME_DURATION_IN_SEC = 30 # SRV3 + +# ConsolidationBus +CONSOLIDATION_BUS = "0x69f49a6681D72D373f2dC4977b05882196e9c660" # SRV3 +CONSOLIDATION_BUS_IMPL = "0x012811b876787FbeE4558064103647E2D36055ED" # SRV3 +# initialize() params — upgrade-params-mainnet.toml [consolidationBus] +CONSOLIDATION_BUS_BATCH_SIZE = 200 # SRV3 +CONSOLIDATION_BUS_MAX_GROUPS_IN_BATCH = 10 # SRV3 +CONSOLIDATION_BUS_EXECUTION_DELAY = 86400 # SRV3 (seconds) + +# ConsolidationMigrator — Curated (id 1) -> Curated Module v2 (id 4) migration +CONSOLIDATION_MIGRATOR = "0x5f401c9cF95cB75bC8B28981D3d77b6513Ad652A" # SRV3 +CONSOLIDATION_MIGRATOR_IMPL = "0xB45052DD52e14591C5cb4307e8fbd4bC11608f20" # SRV3 +CONSOLIDATION_SOURCE_MODULE_ID = 1 # SRV3 +CONSOLIDATION_TARGET_MODULE_ID = 4 # SRV3 == CURATED_V2_STAKING_MODULE_ID +# Curated Module Committee (CMC) multisig — stable deploy input from the toml +CONSOLIDATION_COMMITTEE = "0x2570e0b22AD904501dfB0d49575991ACB801dD91" # SRV3 # Not a precise but still some estimation of the fees. Assume here that all modules are filled # SR_MODULES_FEE = @@ -319,26 +437,30 @@ # + cs_module_fee * cs_module_share SR_MODULES_FEE_BP = ( - CURATED_STAKING_MODULE_MODULE_FEE_BP * (100_00 - SIMPLE_DVT_MODULE_TARGET_SHARE_BP - CS_MODULE_TARGET_SHARE_BP) + CURATED_STAKING_MODULE_MODULE_FEE_BP + * (100_00 - SIMPLE_DVT_MODULE_TARGET_SHARE_BP - CS_MODULE_TARGET_SHARE_BP) + SIMPLE_DVT_MODULE_MODULE_FEE_BP * SIMPLE_DVT_MODULE_TARGET_SHARE_BP + CS_MODULE_MODULE_FEE_BP * CS_MODULE_TARGET_SHARE_BP ) // 100_00 SR_TREASURY_FEE_BP = ( - CURATED_STAKING_MODULE_TREASURY_FEE_BP * (100_00 - SIMPLE_DVT_MODULE_TARGET_SHARE_BP - CS_MODULE_TARGET_SHARE_BP) + CURATED_STAKING_MODULE_TREASURY_FEE_BP + * (100_00 - SIMPLE_DVT_MODULE_TARGET_SHARE_BP - CS_MODULE_TARGET_SHARE_BP) + SIMPLE_DVT_MODULE_TREASURY_FEE_BP * SIMPLE_DVT_MODULE_TARGET_SHARE_BP + CS_MODULE_TREASURY_FEE_BP * CS_MODULE_TARGET_SHARE_BP ) // 100_00 SR_MODULES_FEE_E20 = ( - CURATED_STAKING_MODULE_MODULE_FEE_BP * (100_00 - SIMPLE_DVT_MODULE_TARGET_SHARE_BP - CS_MODULE_TARGET_SHARE_BP) + CURATED_STAKING_MODULE_MODULE_FEE_BP + * (100_00 - SIMPLE_DVT_MODULE_TARGET_SHARE_BP - CS_MODULE_TARGET_SHARE_BP) + SIMPLE_DVT_MODULE_MODULE_FEE_BP * SIMPLE_DVT_MODULE_TARGET_SHARE_BP + CS_MODULE_MODULE_FEE_BP * CS_MODULE_TARGET_SHARE_BP ) * 10**12 # same as for SR_MODULES_FEE_E20 SR_TREASURY_FEE_E20 = ( - CURATED_STAKING_MODULE_TREASURY_FEE_BP * (100_00 - SIMPLE_DVT_MODULE_TARGET_SHARE_BP - CS_MODULE_TARGET_SHARE_BP) + CURATED_STAKING_MODULE_TREASURY_FEE_BP + * (100_00 - SIMPLE_DVT_MODULE_TARGET_SHARE_BP - CS_MODULE_TARGET_SHARE_BP) + SIMPLE_DVT_MODULE_TREASURY_FEE_BP * SIMPLE_DVT_MODULE_TARGET_SHARE_BP + CS_MODULE_TREASURY_FEE_BP * CS_MODULE_TARGET_SHARE_BP ) * 10**12 @@ -359,12 +481,12 @@ # CircuitBreaker CIRCUIT_BREAKER = "0x6019CB557978296BA3C08a7B73225C0975DFB2F7" -CIRCUIT_BREAKER_MIN_PAUSE_DURATION = 432000 # 5 days -CIRCUIT_BREAKER_MAX_PAUSE_DURATION = 5184000 # 60 days -CIRCUIT_BREAKER_PAUSE_DURATION = 1814400 # 21 days -CIRCUIT_BREAKER_MIN_HEARTBEAT_INTERVAL = 2592000 # 30 days +CIRCUIT_BREAKER_MIN_PAUSE_DURATION = 432000 # 5 days +CIRCUIT_BREAKER_MAX_PAUSE_DURATION = 5184000 # 60 days +CIRCUIT_BREAKER_PAUSE_DURATION = 1814400 # 21 days +CIRCUIT_BREAKER_MIN_HEARTBEAT_INTERVAL = 2592000 # 30 days CIRCUIT_BREAKER_MAX_HEARTBEAT_INTERVAL = 94608000 # 1095 days (~3 years) -CIRCUIT_BREAKER_HEARTBEAT_INTERVAL = 31536000 # 1 year (365 days) +CIRCUIT_BREAKER_HEARTBEAT_INTERVAL = 31536000 # 1 year (365 days) # Aragon Permissions test ACL_DEPLOY_BLOCK_NUMBER = 11473216 @@ -416,14 +538,16 @@ CS_FEE_DISTRIBUTOR_ADDRESS = "0xD99CC66fEC647E68294C6477B40fC7E0F6F618D0" CS_FEE_ORACLE_ADDRESS = "0x4D4074628678Bd302921c20573EEa1ed38DdF7FB" CS_GATE_SEAL_ADDRESS = "0x16Dbd4B85a448bE564f1742d5c8cCdD2bB3185D0" -CS_VERIFIER_ADDRESS = "0xeC6Cc185f671F627fb9b6f06C8772755F587b05d" +CS_VERIFIER_ADDRESS = "0x5B92BBACaF636fb38d52cb9d36a4986514ae4439" # SRV3 newVerifier CS_VERIFIER_ADDRESS_OLD = "0x3Dfc50f22aCA652a0a6F28a0F892ab62074b5583" CS_PARAMS_REGISTRY_ADDRESS = "0x9D28ad303C90DF524BA960d7a2DAC56DcC31e428" CS_EXIT_PENALTIES_ADDRESS = "0x06cd61045f958A209a0f8D746e103eCc625f4193" CS_STRIKES_ADDRESS = "0xaa328816027F2D32B9F56d190BC9Fa4A5C07637f" -CS_EJECTOR_ADDRESS = "0xc72b58aa02E0e98cF8A4a0E9Dce75e763800802C" +CS_EJECTOR_ADDRESS = "0x2cB8510b0A30A38427E7e9555e8584b1a90c1BF7" # SRV3 CS_VETTED_GATE_ADDRESS = "0xB314D4A76C457c93150d308787939063F4Cc67E0" -CS_PERMISSIONLESS_GATE_ADDRESS = "0xcF33a38111d0B1246A3F38a838fb41D626B454f0" +CS_PERMISSIONLESS_GATE_ADDRESS = ( + "0xe29eaE1f3A3D0eDD45Bd6D4248A38F603f1F4d1A" # SRV3 newPermissionlessGate +) CS_VERIFIER_V2_ADDRESS = "0xdC5FE1782B6943f318E05230d688713a560063DC" CS_GATE_SEAL_V2_ADDRESS = "0xE1686C2E90eb41a48356c1cC7FaA17629af3ADB3" TWO_PHASE_FRAME_CONFIG_UPDATE = "0xb2B4DB1491cbe949ae85EfF01E0d3ee239f110C1" @@ -431,7 +555,9 @@ # DualGovernance DUAL_GOVERNANCE = "0xC1db28B3301331277e307FDCfF8DE28242A4486E" TIMELOCK = "0xCE0425301C85c5Ea2A0873A2dEe44d78E02D2316" -DUAL_GOVERNANCE_EXECUTORS = ["0x23E0B465633FF5178808F4A75186E2F2F9537021"] # Executor #1 is admin executor +DUAL_GOVERNANCE_EXECUTORS = [ + "0x23E0B465633FF5178808F4A75186E2F2F9537021" +] # Executor #1 is admin executor RESEAL_MANAGER = "0x7914b5a1539b97Bd0bbd155757F25FD79A522d24" DAO_EMERGENCY_GOVERNANCE = "0x553337946F2FAb8911774b20025fa776B76a7CcE" ROLES_VALIDATOR = "0x31534e3aFE219B609da3715a00a1479D2A2d7981" @@ -474,7 +600,11 @@ "GOVERNANCE": DUAL_GOVERNANCE, "EMERGENCY_ACTIVATION_COMMITTEE": EMERGENCY_ACTIVATION_COMMITTEE, "EMERGENCY_EXECUTION_COMMITTEE": EMERGENCY_EXECUTION_COMMITTEE, - "EMERGENCY_PROTECTION_DETAILS": (2592000, 0, 1813449600), # end-date extended by vote_2026_05_13 + "EMERGENCY_PROTECTION_DETAILS": ( + 2592000, + 0, + 1813449600, + ), # end-date extended by vote_2026_05_13 } TIEBREAKER_VALUES = { @@ -539,14 +669,18 @@ "TIEBREAKER_DETAILS": { "TIEBREAKER_COMMITTEE": TIEBREAKER_VALUES["CORE_COMMITTEE"]["ADDRESS"], "TIEBREAKER_ACTIVATION_TIMEOUT": 31536000, # 1 year - "WITHDRAWAL_BLOCKERS": (WITHDRAWAL_QUEUE, VALIDATORS_EXIT_BUS_ORACLE, TRIGGERABLE_WITHDRAWALS_GATEWAY), + "WITHDRAWAL_BLOCKERS": ( + WITHDRAWAL_QUEUE, + VALIDATORS_EXIT_BUS_ORACLE, + TRIGGERABLE_WITHDRAWALS_GATEWAY, + ), }, } # Lido V3 - stVaults VAULT_HUB = "0x1d201BE093d847f6446530Efb0E8Fb426d176709" ACCOUNTING = "0x23ED611be0e1a820978875C0122F92260804cdDf" -ACCOUNTING_IMPL = "0xd43a3E984071F40d5d840f60708Af0e9526785df" +ACCOUNTING_IMPL = "0xE85FD09eBc17A3aAB5f7BA691142506ab38EC1B7" # SRV3 OPERATOR_GRID = "0xC69685E89Cefc327b43B7234AC646451B27c544d" LAZY_ORACLE = "0x5DB427080200c235F2Ae8Cd17A7be87921f7AD6c" PREDEPOSIT_GUARANTEE = "0xF4bF42c6D6A0E38825785048124DBAD6c9eaaac3" diff --git a/interfaces/Accounting.json b/interfaces/Accounting.json index 95eb78cc..f9228e98 100644 --- a/interfaces/Accounting.json +++ b/interfaces/Accounting.json @@ -1,327 +1,306 @@ [ - { - "inputs": [ - { - "internalType": "contract ILidoLocator", - "name": "_lidoLocator", - "type": "address" - }, - { - "internalType": "contract ILido", - "name": "_lido", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "reportTimestamp", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "upperBoundTimestamp", - "type": "uint256" - } - ], - "name": "IncorrectReportTimestamp", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "reportValidators", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "minValidators", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxValidators", - "type": "uint256" - } - ], - "name": "IncorrectReportValidators", - "type": "error" - }, - { - "inputs": [], - "name": "InternalSharesCantBeZero", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "operation", - "type": "string" - }, - { - "internalType": "address", - "name": "addr", - "type": "address" - } - ], - "name": "NotAuthorized", - "type": "error" - }, - { - "inputs": [], - "name": "LIDO", - "outputs": [ - { - "internalType": "contract ILido", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "LIDO_LOCATOR", - "outputs": [ - { - "internalType": "contract ILidoLocator", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "timestamp", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "timeElapsed", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "clValidators", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "clBalance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "withdrawalVaultBalance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "elRewardsVaultBalance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "sharesRequestedToBurn", - "type": "uint256" - }, - { - "internalType": "uint256[]", - "name": "withdrawalFinalizationBatches", - "type": "uint256[]" - }, - { - "internalType": "uint256", - "name": "simulatedShareRate", - "type": "uint256" - } - ], - "internalType": "struct ReportValues", - "name": "_report", - "type": "tuple" - } - ], - "name": "handleOracleReport", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "timestamp", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "timeElapsed", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "clValidators", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "clBalance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "withdrawalVaultBalance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "elRewardsVaultBalance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "sharesRequestedToBurn", - "type": "uint256" - }, - { - "internalType": "uint256[]", - "name": "withdrawalFinalizationBatches", - "type": "uint256[]" - }, - { - "internalType": "uint256", - "name": "simulatedShareRate", - "type": "uint256" - } - ], - "internalType": "struct ReportValues", - "name": "_report", - "type": "tuple" - } - ], - "name": "simulateOracleReport", - "outputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "withdrawalsVaultTransfer", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "elRewardsVaultTransfer", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "etherToFinalizeWQ", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "sharesToFinalizeWQ", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "sharesToBurnForWithdrawals", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "totalSharesToBurn", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "sharesToMintAsFees", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "address[]", - "name": "moduleFeeRecipients", - "type": "address[]" - }, - { - "internalType": "uint256[]", - "name": "moduleIds", - "type": "uint256[]" - }, - { - "internalType": "uint256[]", - "name": "moduleSharesToMint", - "type": "uint256[]" - }, - { - "internalType": "uint256", - "name": "treasurySharesToMint", - "type": "uint256" - } - ], - "internalType": "struct Accounting.FeeDistribution", - "name": "feeDistribution", - "type": "tuple" - }, - { - "internalType": "uint256", - "name": "principalClBalance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "preTotalShares", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "preTotalPooledEther", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "postInternalShares", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "postInternalEther", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "postTotalShares", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "postTotalPooledEther", - "type": "uint256" - } - ], - "internalType": "struct Accounting.CalculatedValues", - "name": "update", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - } - ] + { + "inputs": [ + { + "internalType": "contract ILidoLocator", + "name": "_lidoLocator", + "type": "address" + }, + { + "internalType": "contract ILido", + "name": "_lido", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "reportTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "upperBoundTimestamp", + "type": "uint256" + } + ], + "name": "IncorrectReportTimestamp", + "type": "error" + }, + { + "inputs": [], + "name": "InternalSharesCantBeZero", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "operation", + "type": "string" + }, + { + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "NotAuthorized", + "type": "error" + }, + { + "inputs": [], + "name": "LIDO", + "outputs": [ + { + "internalType": "contract ILido", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LIDO_LOCATOR", + "outputs": [ + { + "internalType": "contract ILidoLocator", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timeElapsed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "clValidatorsBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "clPendingBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "withdrawalVaultBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "elRewardsVaultBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "sharesRequestedToBurn", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "withdrawalFinalizationBatches", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "simulatedShareRate", + "type": "uint256" + } + ], + "internalType": "struct ReportValues", + "name": "_report", + "type": "tuple" + } + ], + "name": "handleOracleReport", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timeElapsed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "clValidatorsBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "clPendingBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "withdrawalVaultBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "elRewardsVaultBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "sharesRequestedToBurn", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "withdrawalFinalizationBatches", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "simulatedShareRate", + "type": "uint256" + } + ], + "internalType": "struct ReportValues", + "name": "_report", + "type": "tuple" + } + ], + "name": "simulateOracleReport", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "withdrawalsVaultTransfer", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "elRewardsVaultTransfer", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "etherToFinalizeWQ", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "sharesToFinalizeWQ", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "sharesToBurnForWithdrawals", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalSharesToBurn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "sharesToMintAsFees", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "address[]", + "name": "moduleFeeRecipients", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "moduleIds", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "moduleSharesToMint", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "treasurySharesToMint", + "type": "uint256" + } + ], + "internalType": "struct Accounting.FeeDistribution", + "name": "feeDistribution", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "principalClBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "preTotalShares", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "preTotalPooledEther", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "postInternalShares", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "postInternalEther", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "postTotalShares", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "postTotalPooledEther", + "type": "uint256" + } + ], + "internalType": "struct Accounting.CalculatedValues", + "name": "update", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + } +] \ No newline at end of file diff --git a/interfaces/AccountingOracle.json b/interfaces/AccountingOracle.json index 73e7ef34..00354736 100644 --- a/interfaces/AccountingOracle.json +++ b/interfaces/AccountingOracle.json @@ -76,17 +76,6 @@ "name": "HashCannotBeZero", "type": "error" }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "code", - "type": "uint256" - } - ], - "name": "IncorrectOracleMigration", - "type": "error" - }, { "inputs": [ { @@ -135,11 +124,6 @@ "name": "InvalidExtraDataSortOrder", "type": "error" }, - { - "inputs": [], - "name": "LidoCannotBeZero", - "type": "error" - }, { "inputs": [], "name": "LidoLocatorCannotBeZero", @@ -799,7 +783,7 @@ "type": "uint256" } ], - "name": "finalizeUpgrade_v4", + "name": "finalizeUpgrade_v5", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -871,6 +855,24 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "getCurrentFrame", + "outputs": [ + { + "internalType": "uint256", + "name": "refSlot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "refSlotTimestamp", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "getLastProcessingRefSlot", @@ -1177,12 +1179,12 @@ }, { "internalType": "uint256", - "name": "numValidators", + "name": "clValidatorsBalanceGwei", "type": "uint256" }, { "internalType": "uint256", - "name": "clBalanceGwei", + "name": "clPendingBalanceGwei", "type": "uint256" }, { @@ -1195,6 +1197,16 @@ "name": "numExitedValidatorsByStakingModule", "type": "uint256[]" }, + { + "internalType": "uint256[]", + "name": "stakingModuleIdsWithUpdatedBalance", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "validatorBalancesGweiByStakingModule", + "type": "uint256[]" + }, { "internalType": "uint256", "name": "withdrawalVaultBalance", @@ -1305,4 +1317,4 @@ "stateMutability": "view", "type": "function" } -] +] \ No newline at end of file diff --git a/interfaces/CSEjector.json b/interfaces/CSEjector.json index 50b02026..f457efb0 100644 --- a/interfaces/CSEjector.json +++ b/interfaces/CSEjector.json @@ -1 +1,755 @@ -[{"inputs":[{"internalType":"address","name":"module","type":"address"},{"internalType":"address","name":"strikes","type":"address"},{"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"internalType":"address","name":"admin","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":"AlreadyWithdrawn","type":"error"},{"inputs":[],"name":"NodeOperatorDoesNotExist","type":"error"},{"inputs":[],"name":"NothingToEject","type":"error"},{"inputs":[],"name":"PauseUntilMustBeInFuture","type":"error"},{"inputs":[],"name":"PausedExpected","type":"error"},{"inputs":[],"name":"ResumedExpected","type":"error"},{"inputs":[],"name":"SenderIsNotEligible","type":"error"},{"inputs":[],"name":"SenderIsNotStrikes","type":"error"},{"inputs":[],"name":"SigningKeysInvalidOffset","type":"error"},{"inputs":[],"name":"ZeroAdminAddress","type":"error"},{"inputs":[],"name":"ZeroModuleAddress","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroStrikesAddress","type":"error"},{"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"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MODULE","outputs":[{"internalType":"contract ICSModule","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":"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":"STAKING_MODULE_ID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STRIKES","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STRIKES_EXIT_TYPE_ID","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VOLUNTARY_EXIT_TYPE_ID","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nodeOperatorId","type":"uint256"},{"internalType":"uint256","name":"keyIndex","type":"uint256"},{"internalType":"address","name":"refundRecipient","type":"address"}],"name":"ejectBadPerformer","outputs":[],"stateMutability":"payable","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":"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":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"triggerableWithdrawalsGateway","outputs":[{"internalType":"contract ITriggerableWithdrawalsGateway","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nodeOperatorId","type":"uint256"},{"internalType":"uint256","name":"startFrom","type":"uint256"},{"internalType":"uint256","name":"keysCount","type":"uint256"},{"internalType":"address","name":"refundRecipient","type":"address"}],"name":"voluntaryEject","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nodeOperatorId","type":"uint256"},{"internalType":"uint256[]","name":"keyIndices","type":"uint256[]"},{"internalType":"address","name":"refundRecipient","type":"address"}],"name":"voluntaryEjectByArray","outputs":[],"stateMutability":"payable","type":"function"}] +[ + { + "type": "constructor", + "inputs": [ + { + "name": "module", + "type": "address", + "internalType": "address" + }, + { + "name": "strikes", + "type": "address", + "internalType": "address" + }, + { + "name": "admin", + "type": "address", + "internalType": "address" + } + ], + "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 IBaseModule" + } + ], + "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": "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": "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": "getRoleMembers", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "outputs": [ + { + "name": "", + "type": "address[]", + "internalType": "address[]" + } + ], + "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": "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": "stakingModuleId", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "supportsInterface", + "inputs": [ + { + "name": "interfaceId", + "type": "bytes4", + "internalType": "bytes4" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "triggerableWithdrawalsGateway", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "contract ITriggerableWithdrawalsGateway" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "voluntaryEject", + "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": "BadPerformerEjectionRequested", + "inputs": [ + { + "name": "nodeOperatorId", + "type": "uint256", + "indexed": true, + "internalType": "uint256" + }, + { + "name": "pubkey", + "type": "bytes", + "indexed": false, + "internalType": "bytes" + }, + { + "name": "refundRecipient", + "type": "address", + "indexed": false, + "internalType": "address" + } + ], + "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": "StakingModuleIdCached", + "inputs": [ + { + "name": "stakingModuleId", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "VoluntaryEjectionRequested", + "inputs": [ + { + "name": "nodeOperatorId", + "type": "uint256", + "indexed": true, + "internalType": "uint256" + }, + { + "name": "pubkey", + "type": "bytes", + "indexed": false, + "internalType": "bytes" + }, + { + "name": "refundRecipient", + "type": "address", + "indexed": false, + "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": "DuplicateKeyIndex", + "inputs": [] + }, + { + "type": "error", + "name": "NodeOperatorDoesNotExist", + "inputs": [] + }, + { + "type": "error", + "name": "NothingToEject", + "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": "StakingModuleIdNotFound", + "inputs": [] + }, + { + "type": "error", + "name": "ZeroAdminAddress", + "inputs": [] + }, + { + "type": "error", + "name": "ZeroModuleAddress", + "inputs": [] + }, + { + "type": "error", + "name": "ZeroPauseDuration", + "inputs": [] + }, + { + "type": "error", + "name": "ZeroRefundRecipient", + "inputs": [] + }, + { + "type": "error", + "name": "ZeroStrikesAddress", + "inputs": [] + } +] \ No newline at end of file diff --git a/interfaces/CSFeeOracle.json b/interfaces/CSFeeOracle.json index 6d13c0c2..c8ea7c3c 100644 --- a/interfaces/CSFeeOracle.json +++ b/interfaces/CSFeeOracle.json @@ -1 +1,1350 @@ -[{"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":[]}] +[ + { + "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 IFeeDistributor" + } + ], + "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 IValidatorStrikes" + } + ], + "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": "finalizeUpgradeV3", + "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": "getRoleMembers", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "outputs": [ + { + "name": "", + "type": "address[]", + "internalType": "address[]" + } + ], + "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": "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 IFeeOracle.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": [] + } +] \ No newline at end of file diff --git a/interfaces/CSParametersRegistry.json b/interfaces/CSParametersRegistry.json index 8a41979f..83d03dbe 100644 --- a/interfaces/CSParametersRegistry.json +++ b/interfaces/CSParametersRegistry.json @@ -1 +1,2385 @@ -[{"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":[]}] +[ + { + "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": "MANAGE_CURVE_PARAMETERS_ROLE", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "MANAGE_GENERAL_PENALTIES_AND_CHARGES_ROLE", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "MANAGE_KEYS_LIMIT_ROLE", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "MANAGE_PERFORMANCE_PARAMETERS_ROLE", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "MANAGE_QUEUE_CONFIG_ROLE", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "MANAGE_REWARD_SHARE_ROLE", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "MANAGE_VALIDATOR_EXIT_PARAMETERS_ROLE", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "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": "defaultExitDelayFee", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "defaultGeneralDelayedPenaltyAdditionalFine", + "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": "defaultMaxElWithdrawalRequestFee", + "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": "finalizeUpgradeV3", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "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": "getCurveParameters", + "inputs": [ + { + "name": "curveId", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "params", + "type": "tuple", + "internalType": "struct IParametersRegistry.CurveParameters", + "components": [ + { + "name": "keyRemovalCharge", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "generalDelayedPenaltyAdditionalFine", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "keysLimit", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "queuePriority", + "type": "uint32", + "internalType": "uint32" + }, + { + "name": "queueMaxDeposits", + "type": "uint32", + "internalType": "uint32" + }, + { + "name": "rewardShareData", + "type": "tuple[]", + "internalType": "struct IParametersRegistry.KeyNumberValueInterval[]", + "components": [ + { + "name": "minKeyNumber", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "value", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "name": "performanceLeewayData", + "type": "tuple[]", + "internalType": "struct IParametersRegistry.KeyNumberValueInterval[]", + "components": [ + { + "name": "minKeyNumber", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "value", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "name": "strikesLifetime", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "strikesThreshold", + "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": "allowedExitDelay", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "exitDelayFee", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "maxElWithdrawalRequestFee", + "type": "uint256", + "internalType": "uint256" + } + ] + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getExitDelayFee", + "inputs": [ + { + "name": "curveId", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "penalty", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getGeneralDelayedPenaltyAdditionalFine", + "inputs": [ + { + "name": "curveId", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "fine", + "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": "getMaxElWithdrawalRequestFee", + "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 IParametersRegistry.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": "priority", + "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 IParametersRegistry.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": "getRoleMembers", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "outputs": [ + { + "name": "", + "type": "address[]", + "internalType": "address[]" + } + ], + "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 IParametersRegistry.InitializationData", + "components": [ + { + "name": "defaultKeyRemovalCharge", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "defaultGeneralDelayedPenaltyAdditionalFine", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "defaultKeysLimit", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "defaultRewardShare", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "defaultPerformanceLeeway", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "defaultStrikesLifetime", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "defaultStrikesThreshold", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "defaultQueuePriority", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "defaultQueueMaxDeposits", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "defaultBadPerformancePenalty", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "defaultAttestationsWeight", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "defaultBlocksWeight", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "defaultSyncWeight", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "defaultAllowedExitDelay", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "defaultExitDelayFee", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "defaultMaxElWithdrawalRequestFee", + "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": "setDefaultExitDelayFee", + "inputs": [ + { + "name": "fee", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setDefaultGeneralDelayedPenaltyAdditionalFine", + "inputs": [ + { + "name": "fine", + "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": "setDefaultMaxElWithdrawalRequestFee", + "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": "setExitDelayFee", + "inputs": [ + { + "name": "curveId", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "fee", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setGeneralDelayedPenaltyAdditionalFine", + "inputs": [ + { + "name": "curveId", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "fine", + "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": "setMaxElWithdrawalRequestFee", + "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 IParametersRegistry.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 IParametersRegistry.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": "unsetExitDelayFee", + "inputs": [ + { + "name": "curveId", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "unsetGeneralDelayedPenaltyAdditionalFine", + "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": "unsetMaxElWithdrawalRequestFee", + "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": "DefaultExitDelayFeeSet", + "inputs": [ + { + "name": "penalty", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "DefaultGeneralDelayedPenaltyAdditionalFineSet", + "inputs": [ + { + "name": "value", + "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": "DefaultMaxElWithdrawalRequestFeeSet", + "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": "ExitDelayFeeSet", + "inputs": [ + { + "name": "curveId", + "type": "uint256", + "indexed": true, + "internalType": "uint256" + }, + { + "name": "penalty", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "ExitDelayFeeUnset", + "inputs": [ + { + "name": "curveId", + "type": "uint256", + "indexed": true, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "GeneralDelayedPenaltyAdditionalFineSet", + "inputs": [ + { + "name": "curveId", + "type": "uint256", + "indexed": true, + "internalType": "uint256" + }, + { + "name": "fine", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "GeneralDelayedPenaltyAdditionalFineUnset", + "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": "MaxElWithdrawalRequestFeeSet", + "inputs": [ + { + "name": "curveId", + "type": "uint256", + "indexed": true, + "internalType": "uint256" + }, + { + "name": "fee", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "MaxElWithdrawalRequestFeeUnset", + "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 IParametersRegistry.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 IParametersRegistry.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": [] + } +] \ No newline at end of file diff --git a/interfaces/ConsolidationBus.json b/interfaces/ConsolidationBus.json new file mode 100644 index 00000000..39a24186 --- /dev/null +++ b/interfaces/ConsolidationBus.json @@ -0,0 +1,873 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "consolidationGateway", + "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": "AdminCannotBeZero", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "batchHash", + "type": "bytes32" + } + ], + "name": "BatchAlreadyPending", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "batchHash", + "type": "bytes32" + } + ], + "name": "BatchNotFound", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "size", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "limit", + "type": "uint256" + } + ], + "name": "BatchTooLarge", + "type": "error" + }, + { + "inputs": [], + "name": "EmptyBatch", + "type": "error" + }, + { + "inputs": [], + "name": "EmptyBatchHashes", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "groupIndex", + "type": "uint256" + } + ], + "name": "EmptyGroup", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "currentTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "executeAfter", + "type": "uint256" + } + ], + "name": "ExecutionDelayNotPassed", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "groupIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "sourceIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "length", + "type": "uint256" + } + ], + "name": "InvalidSourcePubkeyLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "groupIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "length", + "type": "uint256" + } + ], + "name": "InvalidTargetPubkeyLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "maxGroupsInBatch", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "batchSizeLimit", + "type": "uint256" + } + ], + "name": "MaxGroupsExceedsBatchSize", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "groupIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "sourceIndex", + "type": "uint256" + } + ], + "name": "SourceEqualsTarget", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "groupsCount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "limit", + "type": "uint256" + } + ], + "name": "TooManyGroups", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + } + ], + "name": "ZeroArgument", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "newLimit", + "type": "uint256" + } + ], + "name": "BatchLimitUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32[]", + "name": "batchHashes", + "type": "bytes32[]" + } + ], + "name": "BatchesRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "newDelay", + "type": "uint256" + } + ], + "name": "ExecutionDelayUpdated", + "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": "newLimit", + "type": "uint256" + } + ], + "name": "MaxGroupsInBatchUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "publisher", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "batchData", + "type": "bytes" + } + ], + "name": "RequestsAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "batchHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feePaid", + "type": "uint256" + } + ], + "name": "RequestsExecuted", + "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" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MANAGE_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PUBLISH_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "REMOVE_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes[]", + "name": "sourcePubkeys", + "type": "bytes[]" + }, + { + "internalType": "bytes", + "name": "targetPubkey", + "type": "bytes" + } + ], + "internalType": "struct ConsolidationBus.ConsolidationGroup[]", + "name": "groups", + "type": "tuple[]" + } + ], + "name": "addConsolidationRequests", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "batchSize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes[]", + "name": "sourcePubkeys", + "type": "bytes[]" + }, + { + "components": [ + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + }, + { + "internalType": "bytes", + "name": "pubkey", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "validatorIndex", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "childBlockTimestamp", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "slot", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "proposerIndex", + "type": "uint64" + } + ], + "internalType": "struct IPredepositGuarantee.ValidatorWitness", + "name": "targetWitness", + "type": "tuple" + } + ], + "internalType": "struct IConsolidationGateway.ConsolidationWitnessGroup[]", + "name": "groups", + "type": "tuple[]" + } + ], + "name": "executeConsolidation", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "executionDelay", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "batchHash", + "type": "bytes32" + } + ], + "name": "getBatchInfo", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "publisher", + "type": "address" + }, + { + "internalType": "uint64", + "name": "addedAt", + "type": "uint64" + } + ], + "internalType": "struct ConsolidationBus.BatchInfo", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getConsolidationGateway", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "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" + } + ], + "name": "getRoleMembers", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "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": "uint256", + "name": "initialBatchSize", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "initialMaxGroupsInBatch", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "initialExecutionDelay", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "maxGroupsInBatch", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[]", + "name": "batchHashes", + "type": "bytes32[]" + } + ], + "name": "removeBatches", + "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": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "limit", + "type": "uint256" + } + ], + "name": "setBatchSize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "delay", + "type": "uint256" + } + ], + "name": "setExecutionDelay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "limit", + "type": "uint256" + } + ], + "name": "setMaxGroupsInBatch", + "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 diff --git a/interfaces/ConsolidationGateway.json b/interfaces/ConsolidationGateway.json new file mode 100644 index 00000000..eafc8d93 --- /dev/null +++ b/interfaces/ConsolidationGateway.json @@ -0,0 +1,851 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "address", + "name": "lidoLocator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "maxConsolidationRequestsLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "consolidationsPerFrame", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "frameDurationInSec", + "type": "uint256" + }, + { + "internalType": "GIndex", + "name": "_gIFirstValidatorPrev", + "type": "bytes32" + }, + { + "internalType": "GIndex", + "name": "_gIFirstValidatorCurr", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "_pivotSlot", + "type": "uint64" + } + ], + "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": "AdminCannotBeZero", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requestsCount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "remainingLimit", + "type": "uint256" + } + ], + "name": "ConsolidationRequestsLimitExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "DSMDepositsPaused", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "groupIndex", + "type": "uint256" + } + ], + "name": "EmptyGroup", + "type": "error" + }, + { + "inputs": [], + "name": "FeeRefundFailed", + "type": "error" + }, + { + "inputs": [], + "name": "IndexOutOfRange", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "feeRequired", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "passedValue", + "type": "uint256" + } + ], + "name": "InsufficientFee", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPubkeyLength", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSlot", + "type": "error" + }, + { + "inputs": [], + "name": "LidoDepositsPaused", + "type": "error" + }, + { + "inputs": [], + "name": "LimitExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "PauseUntilMustBeInFuture", + "type": "error" + }, + { + "inputs": [], + "name": "PausedExpected", + "type": "error" + }, + { + "inputs": [], + "name": "ResumedExpected", + "type": "error" + }, + { + "inputs": [], + "name": "RootNotFound", + "type": "error" + }, + { + "inputs": [], + "name": "TooLargeFrameDuration", + "type": "error" + }, + { + "inputs": [], + "name": "TooLargeItemsPerFrame", + "type": "error" + }, + { + "inputs": [], + "name": "TooLargeMaxLimit", + "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": "maxConsolidationRequestsLimit", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "consolidationsPerFrame", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "frameDurationInSec", + "type": "uint256" + } + ], + "name": "ConsolidationRequestsLimitSet", + "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" + }, + { + "inputs": [], + "name": "ADD_CONSOLIDATION_REQUEST_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "BEACON_ROOTS", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CONSOLIDATION_LIMIT_POSITION", + "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": "EXIT_LIMIT_MANAGER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "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_PUBKEY_WC_PARENT", + "outputs": [ + { + "internalType": "GIndex", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "GI_STATE_ROOT", + "outputs": [ + { + "internalType": "GIndex", + "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": "PIVOT_SLOT", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "RESUME_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes[]", + "name": "sourcePubkeys", + "type": "bytes[]" + }, + { + "components": [ + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + }, + { + "internalType": "bytes", + "name": "pubkey", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "validatorIndex", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "childBlockTimestamp", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "slot", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "proposerIndex", + "type": "uint64" + } + ], + "internalType": "struct IPredepositGuarantee.ValidatorWitness", + "name": "targetWitness", + "type": "tuple" + } + ], + "internalType": "struct ConsolidationGateway.ConsolidationWitnessGroup[]", + "name": "groups", + "type": "tuple[]" + }, + { + "internalType": "address", + "name": "refundRecipient", + "type": "address" + } + ], + "name": "addConsolidationRequests", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "getConsolidationRequestLimitFullInfo", + "outputs": [ + { + "internalType": "uint256", + "name": "maxConsolidationRequestsLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "consolidationsPerFrame", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "frameDurationInSec", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "prevConsolidationRequestsLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "currentConsolidationRequestsLimit", + "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" + } + ], + "name": "getRoleMembers", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "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": "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": "uint256", + "name": "maxConsolidationRequestsLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "consolidationsPerFrame", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "frameDurationInSec", + "type": "uint256" + } + ], + "name": "setConsolidationRequestLimit", + "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/ConsolidationMigrator.json b/interfaces/ConsolidationMigrator.json new file mode 100644 index 00000000..b6fca48e --- /dev/null +++ b/interfaces/ConsolidationMigrator.json @@ -0,0 +1,764 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "stakingRouter", + "type": "address" + }, + { + "internalType": "address", + "name": "consolidationBus", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_sourceModuleId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_targetModuleId", + "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": "AdminCannotBeZero", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "moduleId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "operatorId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "keyIndex", + "type": "uint256" + } + ], + "name": "KeyNotDeposited", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "sourceOperatorId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "targetOperatorId", + "type": "uint256" + } + ], + "name": "NotAuthorized", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "sourceOperatorId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "targetOperatorId", + "type": "uint256" + } + ], + "name": "PairNotInAllowlist", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + } + ], + "name": "ZeroArgument", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "sourceOperatorId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "targetOperatorId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "submitter", + "type": "address" + } + ], + "name": "ConsolidationPairAllowed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "sourceOperatorId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "targetOperatorId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "submitter", + "type": "address" + } + ], + "name": "ConsolidationPairDisallowed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "sourceOperatorId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "targetOperatorId", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint256[]", + "name": "sourceKeyIndices", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "targetKeyIndex", + "type": "uint256" + } + ], + "indexed": false, + "internalType": "struct ConsolidationMigrator.ConsolidationIndexGroup[]", + "name": "groups", + "type": "tuple[]" + } + ], + "name": "ConsolidationSubmitted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "version", + "type": "uint64" + } + ], + "name": "Initialized", + "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" + }, + { + "inputs": [], + "name": "ALLOW_PAIR_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": "DISALLOW_PAIR_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PUBKEY_LENGTH", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "sourceOperatorId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "targetOperatorId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "submitter", + "type": "address" + } + ], + "name": "allowPair", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "sourceOperatorId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "targetOperatorId", + "type": "uint256" + } + ], + "name": "disallowPair", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "sourceOperatorId", + "type": "uint256" + } + ], + "name": "getAllowedTargets", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getConsolidationBus", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "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" + } + ], + "name": "getRoleMembers", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getStakingRouter", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "sourceOperatorId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "targetOperatorId", + "type": "uint256" + } + ], + "name": "getSubmitter", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "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": [ + { + "internalType": "uint256", + "name": "sourceOperatorId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "targetOperatorId", + "type": "uint256" + } + ], + "name": "isPairAllowed", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "callerConfirmation", + "type": "address" + } + ], + "name": "renounceRole", + "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": "sourceOperatorId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "targetOperatorId", + "type": "uint256" + } + ], + "name": "selfDisallowPair", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "sourceModuleId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "sourceOperatorId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "targetOperatorId", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint256[]", + "name": "sourceKeyIndices", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "targetKeyIndex", + "type": "uint256" + } + ], + "internalType": "struct ConsolidationMigrator.ConsolidationIndexGroup[]", + "name": "groups", + "type": "tuple[]" + } + ], + "name": "submitConsolidationBatch", + "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": [], + "name": "targetModuleId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] \ No newline at end of file diff --git a/interfaces/Lido.json b/interfaces/Lido.json index e62344e9..72fdb89a 100644 --- a/interfaces/Lido.json +++ b/interfaces/Lido.json @@ -82,6 +82,20 @@ "stateMutability": "view", "type": "function" }, + { + "constant": true, + "inputs": [], + "name": "BUFFER_RESERVE_MANAGER_ROLE", + "outputs": [ + { + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, { "constant": false, "inputs": [ @@ -119,6 +133,56 @@ "stateMutability": "view", "type": "function" }, + { + "constant": false, + "inputs": [ + { + "name": "_newDepositsReserveTarget", + "type": "uint256" + } + ], + "name": "setDepositsReserveTarget", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getDepositsReserveTarget", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_lidoLocator", + "type": "address" + }, + { + "name": "_eip712StETH", + "type": "address" + }, + { + "name": "_depositsReserveTarget", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "payable": true, + "stateMutability": "payable", + "type": "function" + }, { "constant": true, "inputs": [], @@ -212,6 +276,24 @@ "stateMutability": "view", "type": "function" }, + { + "constant": false, + "inputs": [ + { + "name": "_amount", + "type": "uint256" + }, + { + "name": "_seedDepositsCount", + "type": "uint256" + } + ], + "name": "withdrawDepositableEther", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, { "constant": false, "inputs": [ @@ -347,27 +429,39 @@ "type": "function" }, { - "constant": false, - "inputs": [ + "constant": true, + "inputs": [], + "name": "PAUSE_ROLE", + "outputs": [ { - "name": "_newDepositedValidators", - "type": "uint256" + "name": "", + "type": "bytes32" } ], - "name": "unsafeChangeDepositedValidators", - "outputs": [], "payable": false, - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { "constant": true, "inputs": [], - "name": "PAUSE_ROLE", + "name": "getBalanceStats", "outputs": [ { - "name": "", - "type": "bytes32" + "name": "clValidatorsBalanceAtLastReport", + "type": "uint256" + }, + { + "name": "clPendingBalanceAtLastReport", + "type": "uint256" + }, + { + "name": "depositedSinceLastReport", + "type": "uint256" + }, + { + "name": "depositedForCurrentReport", + "type": "uint256" } ], "payable": false, @@ -439,24 +533,6 @@ "stateMutability": "view", "type": "function" }, - { - "constant": false, - "inputs": [ - { - "name": "_lidoLocator", - "type": "address" - }, - { - "name": "_eip712StETH", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, { "constant": false, "inputs": [], @@ -506,15 +582,11 @@ "type": "uint256" }, { - "name": "_preClValidators", - "type": "uint256" - }, - { - "name": "_reportClValidators", + "name": "_clValidatorsBalance", "type": "uint256" }, { - "name": "_reportClBalance", + "name": "_clPendingBalance", "type": "uint256" } ], @@ -830,31 +902,23 @@ "type": "function" }, { - "constant": false, - "inputs": [ - { - "name": "_oldBurner", - "type": "address" - }, - { - "name": "_contractsWithBurnerAllowances", - "type": "address[]" - }, + "constant": true, + "inputs": [], + "name": "getMaxMintableExternalShares", + "outputs": [ { - "name": "_initialMaxExternalRatioBP", + "name": "", "type": "uint256" } ], - "name": "finalizeUpgrade_v3", - "outputs": [], "payable": false, - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { "constant": true, "inputs": [], - "name": "getMaxMintableExternalShares", + "name": "getWithdrawalsReserve", "outputs": [ { "name": "", @@ -893,6 +957,20 @@ "stateMutability": "view", "type": "function" }, + { + "constant": false, + "inputs": [ + { + "name": "_depositsReserveTarget", + "type": "uint256" + } + ], + "name": "finalizeUpgrade_v4", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, { "constant": false, "inputs": [ @@ -1120,42 +1198,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "constant": false, - "inputs": [ - { - "name": "_maxDepositsCount", - "type": "uint256" - }, - { - "name": "_stakingModuleId", - "type": "uint256" - }, - { - "name": "_depositCalldata", - "type": "bytes" - } - ], - "name": "deposit", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "UNSAFE_CHANGE_DEPOSITED_VALIDATORS_ROLE", - "outputs": [ - { - "name": "", - "type": "bytes32" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, { "constant": true, "inputs": [], @@ -1360,6 +1402,20 @@ "stateMutability": "view", "type": "function" }, + { + "constant": true, + "inputs": [], + "name": "getDepositsReserve", + "outputs": [ + { + "name": "depositsReserve", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, { "constant": true, "inputs": [], @@ -1480,16 +1536,28 @@ }, { "indexed": false, - "name": "preCLValidators", + "name": "clValidatorsBalance", "type": "uint256" }, { "indexed": false, - "name": "postCLValidators", + "name": "clPendingBalance", "type": "uint256" } ], - "name": "CLValidatorsUpdated", + "name": "CLBalancesUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "depositedPostReport", + "type": "uint256" + } + ], + "name": "DepositedPostReportUpdated", "type": "event" }, { @@ -1745,6 +1813,30 @@ "name": "ExternalBadDebtInternalized", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "depositsReserve", + "type": "uint256" + } + ], + "name": "DepositsReserveSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "depositsReserveTarget", + "type": "uint256" + } + ], + "name": "DepositsReserveTargetSet", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -1923,4 +2015,4 @@ "name": "ContractVersionSet", "type": "event" } -] +] \ No newline at end of file diff --git a/interfaces/LidoLocator.json b/interfaces/LidoLocator.json index 3c480986..b74b466c 100644 --- a/interfaces/LidoLocator.json +++ b/interfaces/LidoLocator.json @@ -78,6 +78,11 @@ "name": "triggerableWithdrawalsGateway", "type": "address" }, + { + "internalType": "address", + "name": "consolidationGateway", + "type": "address" + }, { "internalType": "address", "name": "accounting", @@ -112,6 +117,11 @@ "internalType": "address", "name": "operatorGrid", "type": "address" + }, + { + "internalType": "address", + "name": "topUpGateway", + "type": "address" } ], "internalType": "struct LidoLocator.Config", @@ -166,6 +176,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "consolidationGateway", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "coreComponents", @@ -377,6 +400,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "topUpGateway", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "treasury", diff --git a/interfaces/OracleReportSanityChecker.json b/interfaces/OracleReportSanityChecker.json index a8fcf121..e5490a13 100644 --- a/interfaces/OracleReportSanityChecker.json +++ b/interfaces/OracleReportSanityChecker.json @@ -6,6 +6,11 @@ "name": "_lidoLocator", "type": "address" }, + { + "internalType": "address", + "name": "_accounting", + "type": "address" + }, { "internalType": "address", "name": "_admin", @@ -15,12 +20,12 @@ "components": [ { "internalType": "uint256", - "name": "exitedValidatorsPerDayLimit", + "name": "exitedEthAmountPerDayLimit", "type": "uint256" }, { "internalType": "uint256", - "name": "appearedValidatorsPerDayLimit", + "name": "appearedEthAmountPerDayLimit", "type": "uint256" }, { @@ -35,7 +40,17 @@ }, { "internalType": "uint256", - "name": "maxValidatorExitRequestsPerReport", + "name": "maxBalanceExitRequestedPerReportInEth", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxEffectiveBalanceWeightWCType01", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxEffectiveBalanceWeightWCType02", "type": "uint256" }, { @@ -60,17 +75,27 @@ }, { "internalType": "uint256", - "name": "initialSlashingAmountPWei", + "name": "maxCLBalanceDecreaseBP", "type": "uint256" }, { "internalType": "uint256", - "name": "inactivityPenaltiesAmountPWei", + "name": "clBalanceOraclesErrorUpperBPLimit", "type": "uint256" }, { "internalType": "uint256", - "name": "clBalanceOraclesErrorUpperBPLimit", + "name": "consolidationEthAmountPerDayLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "exitedValidatorEthAmountLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "externalPendingBalanceCapEth", "type": "uint256" } ], @@ -84,17 +109,28 @@ }, { "inputs": [], - "name": "ActualShareRateIsZero", + "name": "AdminCannotBeZero", "type": "error" }, { - "inputs": [], - "name": "AdminCannotBeZero", + "inputs": [ + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxValue", + "type": "uint256" + } + ], + "name": "BasisPointsOverflow", "type": "error" }, { "inputs": [], - "name": "CalledNotFromLido", + "name": "CalledNotFromAccounting", "type": "error" }, { @@ -110,18 +146,23 @@ "type": "uint256" } ], - "name": "ExitedValidatorsLimitExceeded", + "name": "ExitedEthAmountPerDayLimitExceeded", "type": "error" }, { "inputs": [ { "internalType": "uint256", - "name": "appearedValidatorsLimit", + "name": "expected", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "actual", "type": "uint256" } ], - "name": "IncorrectAppearedValidators", + "name": "InconsistentValidatorsBalanceByModule", "type": "error" }, { @@ -155,22 +196,27 @@ "inputs": [ { "internalType": "uint256", - "name": "actualELRewardsVaultBalance", + "name": "withdrawalVaultBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lastWithdrawalVaultBalanceAfterTransfer", "type": "uint256" } ], - "name": "IncorrectELRewardsVaultBalance", + "name": "IncorrectCLWithdrawalsVaultBalance", "type": "error" }, { "inputs": [ { "internalType": "uint256", - "name": "exitedValidatorsLimit", + "name": "actualELRewardsVaultBalance", "type": "uint256" } ], - "name": "IncorrectExitedValidators", + "name": "IncorrectELRewardsVaultBalance", "type": "error" }, { @@ -198,49 +244,113 @@ "inputs": [ { "internalType": "uint256", - "name": "maxRequestsCount", + "name": "requestCreationTimestamp", "type": "uint256" } ], - "name": "IncorrectNumberOfExitRequestsPerReport", + "name": "IncorrectRequestFinalization", "type": "error" }, { "inputs": [ { "internalType": "uint256", - "name": "requestCreationBlock", + "name": "actualSharesToBurn", "type": "uint256" } ], - "name": "IncorrectRequestFinalization", + "name": "IncorrectSharesRequestedToBurn", "type": "error" }, { "inputs": [ { "internalType": "uint256", - "name": "actualSharesToBurn", + "name": "simulatedShareRate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "actualShareRate", "type": "uint256" } ], - "name": "IncorrectSharesRequestedToBurn", + "name": "IncorrectSimulatedShareRate", "type": "error" }, { "inputs": [ { "internalType": "uint256", - "name": "simulatedShareRate", + "name": "maxBalanceSum", + "type": "uint256" + } + ], + "name": "IncorrectSumOfExitBalancePerReport", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "maxAllowed", "type": "uint256" }, { "internalType": "uint256", - "name": "actualShareRate", + "name": "actual", "type": "uint256" } ], - "name": "IncorrectSimulatedShareRate", + "name": "IncorrectTotalActivatedBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "maxAllowed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "actual", + "type": "uint256" + } + ], + "name": "IncorrectTotalCLBalanceIncrease", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "maxAllowed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "actual", + "type": "uint256" + } + ], + "name": "IncorrectTotalModuleValidatorsBalanceIncrease", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "maxAllowed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "actual", + "type": "uint256" + } + ], + "name": "IncorrectTotalPendingBalance", "type": "error" }, { @@ -254,6 +364,32 @@ "name": "IncorrectWithdrawalsVaultBalance", "type": "error" }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "withdrawalVaultBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "withdrawalsVaultTransfer", + "type": "uint256" + } + ], + "name": "IncorrectWithdrawalsVaultTransfer", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidClBalancesData", + "type": "error" + }, + { + "inputs": [], + "name": "MigrationAlreadyDone", + "type": "error" + }, { "inputs": [ { @@ -343,6 +479,22 @@ "name": "TooManyNodeOpsPerExtraDataItem", "type": "error" }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "actual", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expected", + "type": "uint256" + } + ], + "name": "UnexpectedLidoVersion", + "type": "error" + }, { "anonymous": false, "inputs": [ @@ -362,11 +514,30 @@ { "indexed": false, "internalType": "uint256", - "name": "appearedValidatorsPerDayLimit", + "name": "appearedEthAmountPerDayLimit", "type": "uint256" } ], - "name": "AppearedValidatorsPerDayLimitSet", + "name": "AppearedEthAmountPerDayLimitSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "clBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "clWithdrawals", + "type": "uint256" + } + ], + "name": "BaselineSnapshotMigrated", "type": "event" }, { @@ -388,11 +559,11 @@ { "indexed": false, "internalType": "uint256", - "name": "exitedValidatorsPerDayLimit", + "name": "consolidationEthAmountPerDayLimit", "type": "uint256" } ], - "name": "ExitedValidatorsPerDayLimitSet", + "name": "ConsolidationEthAmountPerDayLimitSet", "type": "event" }, { @@ -401,11 +572,11 @@ { "indexed": false, "internalType": "uint256", - "name": "inactivityPenaltiesAmountPWei", + "name": "exitedEthAmountPerDayLimit", "type": "uint256" } ], - "name": "InactivityPenaltiesAmountSet", + "name": "ExitedEthAmountPerDayLimitSet", "type": "event" }, { @@ -414,11 +585,11 @@ { "indexed": false, "internalType": "uint256", - "name": "initialSlashingAmountPWei", + "name": "exitedValidatorEthAmountLimit", "type": "uint256" } ], - "name": "InitialSlashingAmountSet", + "name": "ExitedValidatorEthAmountLimitSet", "type": "event" }, { @@ -427,11 +598,11 @@ { "indexed": false, "internalType": "uint256", - "name": "maxItemsPerExtraDataTransaction", + "name": "externalPendingBalanceCapEth", "type": "uint256" } ], - "name": "MaxItemsPerExtraDataTransactionSet", + "name": "ExternalPendingBalanceCapEthSet", "type": "event" }, { @@ -440,11 +611,11 @@ { "indexed": false, "internalType": "uint256", - "name": "maxNodeOperatorsPerExtraDataItem", + "name": "maxBalanceExitRequestedPerReportInEth", "type": "uint256" } ], - "name": "MaxNodeOperatorsPerExtraDataItemSet", + "name": "MaxBalanceExitRequestedPerReportInEthSet", "type": "event" }, { @@ -453,11 +624,11 @@ { "indexed": false, "internalType": "uint256", - "name": "maxPositiveTokenRebase", + "name": "maxCLBalanceDecreaseBP", "type": "uint256" } ], - "name": "MaxPositiveTokenRebaseSet", + "name": "MaxCLBalanceDecreaseBPSet", "type": "event" }, { @@ -466,11 +637,63 @@ { "indexed": false, "internalType": "uint256", - "name": "maxValidatorExitRequestsPerReport", + "name": "maxEffectiveBalanceWeightWCType01", "type": "uint256" } ], - "name": "MaxValidatorExitRequestsPerReportSet", + "name": "MaxEffectiveBalanceWeightWCType01Set", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "maxEffectiveBalanceWeightWCType02", + "type": "uint256" + } + ], + "name": "MaxEffectiveBalanceWeightWCType02Set", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "maxItemsPerExtraDataTransaction", + "type": "uint256" + } + ], + "name": "MaxItemsPerExtraDataTransactionSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "maxNodeOperatorsPerExtraDataItem", + "type": "uint256" + } + ], + "name": "MaxNodeOperatorsPerExtraDataItemSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "maxPositiveTokenRebase", + "type": "uint256" + } + ], + "name": "MaxPositiveTokenRebaseSet", "type": "event" }, { @@ -497,7 +720,7 @@ { "indexed": false, "internalType": "uint256", - "name": "maxAllowedCLRebaseNegativeSum", + "name": "maxAllowedDecrease", "type": "uint256" } ], @@ -671,7 +894,20 @@ }, { "inputs": [], - "name": "APPEARED_VALIDATORS_PER_DAY_LIMIT_MANAGER_ROLE", + "name": "APPEARED_ETH_AMOUNT_PER_DAY_LIMIT_MANAGER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CONSOLIDATION_ETH_AMOUNT_PER_DAY_LIMIT_MANAGER_ROLE", "outputs": [ { "internalType": "bytes32", @@ -697,7 +933,7 @@ }, { "inputs": [], - "name": "EXITED_VALIDATORS_PER_DAY_LIMIT_MANAGER_ROLE", + "name": "EXITED_ETH_AMOUNT_PER_DAY_LIMIT_MANAGER_ROLE", "outputs": [ { "internalType": "bytes32", @@ -710,7 +946,7 @@ }, { "inputs": [], - "name": "INITIAL_SLASHING_AND_PENALTIES_MANAGER_ROLE", + "name": "EXITED_VALIDATOR_ETH_AMOUNT_LIMIT_MANAGER_ROLE", "outputs": [ { "internalType": "bytes32", @@ -723,7 +959,7 @@ }, { "inputs": [], - "name": "MAX_ITEMS_PER_EXTRA_DATA_TRANSACTION_ROLE", + "name": "EXTERNAL_PENDING_BALANCE_CAP_MANAGER_ROLE", "outputs": [ { "internalType": "bytes32", @@ -736,7 +972,7 @@ }, { "inputs": [], - "name": "MAX_NODE_OPERATORS_PER_EXTRA_DATA_ITEM_ROLE", + "name": "MAX_BALANCE_EXIT_REQUESTED_PER_REPORT_IN_ETH_ROLE", "outputs": [ { "internalType": "bytes32", @@ -749,7 +985,46 @@ }, { "inputs": [], - "name": "MAX_POSITIVE_TOKEN_REBASE_MANAGER_ROLE", + "name": "MAX_CL_BALANCE_DECREASE_MANAGER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_EFFECTIVE_BALANCE_WEIGHTS_MANAGER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_ITEMS_PER_EXTRA_DATA_TRANSACTION_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_NODE_OPERATORS_PER_EXTRA_DATA_ITEM_ROLE", "outputs": [ { "internalType": "bytes32", @@ -762,7 +1037,7 @@ }, { "inputs": [], - "name": "MAX_VALIDATOR_EXIT_REQUESTS_PER_REPORT_ROLE", + "name": "MAX_POSITIVE_TOKEN_REBASE_MANAGER_ROLE", "outputs": [ { "internalType": "bytes32", @@ -821,12 +1096,22 @@ }, { "internalType": "uint256", - "name": "_preCLBalance", + "name": "_preCLValidatorsBalance", "type": "uint256" }, { "internalType": "uint256", - "name": "_postCLBalance", + "name": "_preCLPendingBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_postCLValidatorsBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_postCLPendingBalance", "type": "uint256" }, { @@ -846,12 +1131,12 @@ }, { "internalType": "uint256", - "name": "_preCLValidators", + "name": "_deposits", "type": "uint256" }, { "internalType": "uint256", - "name": "_postCLValidators", + "name": "_withdrawalsVaultTransfer", "type": "uint256" } ], @@ -864,7 +1149,7 @@ "inputs": [ { "internalType": "uint256", - "name": "_exitRequestsCount", + "name": "_maxBalanceExitRequestedPerReportInEth", "type": "uint256" } ], @@ -877,11 +1162,16 @@ "inputs": [ { "internalType": "uint256", - "name": "_exitedValidatorsCount", + "name": "_newlyExitedValidatorsCount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_timeElapsed", "type": "uint256" } ], - "name": "checkExitedValidatorsRatePerDay", + "name": "checkExitedValidatorsCount", "outputs": [], "stateMutability": "view", "type": "function" @@ -899,6 +1189,54 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "_stakingModuleIdsWithUpdatedBalance", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "_validatorBalancesWeiByStakingModule", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "_preCLValidatorsBalanceWei", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_preCLPendingBalanceWei", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_postCLValidatorsBalanceWei", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_postCLPendingBalanceWei", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_depositsWei", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_timeElapsed", + "type": "uint256" + } + ], + "name": "checkModuleAndCLBalancesChangeRates", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -921,22 +1259,22 @@ "inputs": [ { "internalType": "uint256", - "name": "_postTotalPooledEther", + "name": "_postInternalEther", "type": "uint256" }, { "internalType": "uint256", - "name": "_postTotalShares", + "name": "_postInternalShares", "type": "uint256" }, { "internalType": "uint256", - "name": "_etherLockedOnWithdrawalQueue", + "name": "_etherToFinalizeWQ", "type": "uint256" }, { "internalType": "uint256", - "name": "_sharesBurntDueToWithdrawals", + "name": "_sharesToBurnForWithdrawals", "type": "uint256" }, { @@ -981,6 +1319,45 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "getMaxCLBalanceDecreaseBP", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getMaxEffectiveBalanceWeightWCType01", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getMaxEffectiveBalanceWeightWCType02", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "getMaxPositiveTokenRebase", @@ -1002,12 +1379,12 @@ "components": [ { "internalType": "uint256", - "name": "exitedValidatorsPerDayLimit", + "name": "exitedEthAmountPerDayLimit", "type": "uint256" }, { "internalType": "uint256", - "name": "appearedValidatorsPerDayLimit", + "name": "appearedEthAmountPerDayLimit", "type": "uint256" }, { @@ -1022,7 +1399,17 @@ }, { "internalType": "uint256", - "name": "maxValidatorExitRequestsPerReport", + "name": "maxBalanceExitRequestedPerReportInEth", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxEffectiveBalanceWeightWCType01", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxEffectiveBalanceWeightWCType02", "type": "uint256" }, { @@ -1047,17 +1434,27 @@ }, { "internalType": "uint256", - "name": "initialSlashingAmountPWei", + "name": "maxCLBalanceDecreaseBP", "type": "uint256" }, { "internalType": "uint256", - "name": "inactivityPenaltiesAmountPWei", + "name": "clBalanceOraclesErrorUpperBPLimit", "type": "uint256" }, { "internalType": "uint256", - "name": "clBalanceOraclesErrorUpperBPLimit", + "name": "consolidationEthAmountPerDayLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "exitedValidatorEthAmountLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "externalPendingBalanceCapEth", "type": "uint256" } ], @@ -1186,6 +1583,52 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "isPostMigrationFirstReportDone", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastReportTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastVaultBalanceAfterTransfer", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "migrateBaselineSnapshot", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -1220,13 +1663,18 @@ "type": "uint64" }, { - "internalType": "uint64", - "name": "totalExitedValidators", - "type": "uint64" + "internalType": "uint128", + "name": "clBalance", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "deposits", + "type": "uint128" }, { "internalType": "uint128", - "name": "negativeCLRebaseWei", + "name": "clWithdrawals", "type": "uint128" } ], @@ -1281,11 +1729,11 @@ "inputs": [ { "internalType": "uint256", - "name": "_appearedValidatorsPerDayLimit", + "name": "_appearedEthAmountPerDayLimit", "type": "uint256" } ], - "name": "setAppearedValidatorsPerDayLimit", + "name": "setAppearedEthAmountPerDayLimit", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -1294,11 +1742,11 @@ "inputs": [ { "internalType": "uint256", - "name": "_exitedValidatorsPerDayLimit", + "name": "_consolidationEthAmountPerDayLimit", "type": "uint256" } ], - "name": "setExitedValidatorsPerDayLimit", + "name": "setConsolidationEthAmountPerDayLimit", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -1307,16 +1755,24 @@ "inputs": [ { "internalType": "uint256", - "name": "_initialSlashingAmountPWei", + "name": "_exitedEthAmountPerDayLimit", "type": "uint256" - }, + } + ], + "name": "setExitedEthAmountPerDayLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ { "internalType": "uint256", - "name": "_inactivityPenaltiesAmountPWei", + "name": "_exitedValidatorEthAmountLimit", "type": "uint256" } ], - "name": "setInitialSlashingAndPenaltiesAmount", + "name": "setExitedValidatorEthAmountLimit", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -1325,11 +1781,63 @@ "inputs": [ { "internalType": "uint256", - "name": "_maxValidatorExitRequestsPerReport", + "name": "_externalPendingBalanceCapEth", "type": "uint256" } ], - "name": "setMaxExitRequestsPerOracleReport", + "name": "setExternalPendingBalanceCapEth", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_maxBalanceExitRequestedPerReportInEth", + "type": "uint256" + } + ], + "name": "setMaxBalanceExitRequestedPerReportInEth", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_maxCLBalanceDecreaseBP", + "type": "uint256" + } + ], + "name": "setMaxCLBalanceDecreaseBP", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_maxEffectiveBalanceWeightWCType01", + "type": "uint256" + } + ], + "name": "setMaxEffectiveBalanceWeightWCType01", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_maxEffectiveBalanceWeightWCType02", + "type": "uint256" + } + ], + "name": "setMaxEffectiveBalanceWeightWCType02", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -1379,12 +1887,12 @@ "components": [ { "internalType": "uint256", - "name": "exitedValidatorsPerDayLimit", + "name": "exitedEthAmountPerDayLimit", "type": "uint256" }, { "internalType": "uint256", - "name": "appearedValidatorsPerDayLimit", + "name": "appearedEthAmountPerDayLimit", "type": "uint256" }, { @@ -1399,7 +1907,17 @@ }, { "internalType": "uint256", - "name": "maxValidatorExitRequestsPerReport", + "name": "maxBalanceExitRequestedPerReportInEth", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxEffectiveBalanceWeightWCType01", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxEffectiveBalanceWeightWCType02", "type": "uint256" }, { @@ -1424,17 +1942,27 @@ }, { "internalType": "uint256", - "name": "initialSlashingAmountPWei", + "name": "maxCLBalanceDecreaseBP", "type": "uint256" }, { "internalType": "uint256", - "name": "inactivityPenaltiesAmountPWei", + "name": "clBalanceOraclesErrorUpperBPLimit", "type": "uint256" }, { "internalType": "uint256", - "name": "clBalanceOraclesErrorUpperBPLimit", + "name": "consolidationEthAmountPerDayLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "exitedValidatorEthAmountLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "externalPendingBalanceCapEth", "type": "uint256" } ], @@ -1501,12 +2029,12 @@ "inputs": [ { "internalType": "uint256", - "name": "_preTotalPooledEther", + "name": "_preInternalEther", "type": "uint256" }, { "internalType": "uint256", - "name": "_preTotalShares", + "name": "_preInternalShares", "type": "uint256" }, { @@ -1559,7 +2087,7 @@ }, { "internalType": "uint256", - "name": "simulatedSharesToBurn", + "name": "sharesFromWQToBurn", "type": "uint256" }, { @@ -1590,4 +2118,4 @@ "stateMutability": "view", "type": "function" } -] +] \ No newline at end of file diff --git a/interfaces/StakingRouter.json b/interfaces/StakingRouter.json index 63233f2d..6edcf5be 100644 --- a/interfaces/StakingRouter.json +++ b/interfaces/StakingRouter.json @@ -5,6 +5,26 @@ "internalType": "address", "name": "_depositContract", "type": "address" + }, + { + "internalType": "address", + "name": "_lido", + "type": "address" + }, + { + "internalType": "address", + "name": "_lidoLocator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_maxEBType1", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_maxEBType2", + "type": "uint256" } ], "stateMutability": "nonpayable", @@ -12,28 +32,43 @@ }, { "inputs": [], - "name": "AppAuthLidoFailed", + "name": "AccessControlBadConfirmation", "type": "error" }, { "inputs": [ { - "internalType": "uint256", - "name": "firstArrayLength", - "type": "uint256" + "internalType": "address", + "name": "account", + "type": "address" }, { - "internalType": "uint256", - "name": "secondArrayLength", - "type": "uint256" + "internalType": "bytes32", + "name": "neededRole", + "type": "bytes32" } ], - "name": "ArraysLengthMismatch", + "name": "AccessControlUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [], + "name": "AllocationExceedsLimit", + "type": "error" + }, + { + "inputs": [], + "name": "AlreadyMigrated", + "type": "error" + }, + { + "inputs": [], + "name": "AmountNotAlignedToGwei", "type": "error" }, { "inputs": [], - "name": "DepositContractZeroAddress", + "name": "ArraysLengthMismatch", "type": "error" }, { @@ -43,7 +78,7 @@ }, { "inputs": [], - "name": "EmptyWithdrawalsCredentials", + "name": "EmptyKeysList", "type": "error" }, { @@ -53,23 +88,12 @@ }, { "inputs": [], - "name": "InvalidContractVersionIncrement", + "name": "InconsistentFeeSum", "type": "error" }, { - "inputs": [ - { - "internalType": "uint256", - "name": "etherValue", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "depositsCount", - "type": "uint256" - } - ], - "name": "InvalidDepositsValue", + "inputs": [], + "name": "InvalidAmountGwei", "type": "error" }, { @@ -77,6 +101,11 @@ "name": "InvalidFeeSum", "type": "error" }, + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, { "inputs": [], "name": "InvalidMaxDepositPerBlockValue", @@ -84,28 +113,17 @@ }, { "inputs": [], - "name": "InvalidMinDepositBlockDistance", + "name": "InvalidMaxTopUpPerBlockGwei", "type": "error" }, { "inputs": [], - "name": "InvalidPriorityExitShareThreshold", + "name": "InvalidMinDepositBlockDistance", "type": "error" }, { - "inputs": [ - { - "internalType": "uint256", - "name": "actual", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "expected", - "type": "uint256" - } - ], - "name": "InvalidPublicKeysBatchLength", + "inputs": [], + "name": "InvalidPriorityExitShareThreshold", "type": "error" }, { @@ -120,29 +138,33 @@ "type": "error" }, { - "inputs": [ - { - "internalType": "uint256", - "name": "actual", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "expected", - "type": "uint256" - } - ], - "name": "InvalidSignaturesBatchLength", + "inputs": [], + "name": "InvalidStakeShareLimit", "type": "error" }, { "inputs": [], - "name": "InvalidStakeShareLimit", + "name": "LidoDepositsPaused", + "type": "error" + }, + { + "inputs": [], + "name": "ModuleReturnExceedTarget", + "type": "error" + }, + { + "inputs": [], + "name": "NotAuthorized", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", "type": "error" }, { "inputs": [], - "name": "NonZeroContractVersionOnInit", + "name": "OracleExtraDataNotSubmitted", "type": "error" }, { @@ -200,7 +222,7 @@ }, { "internalType": "uint256", - "name": "received", + "name": "actual", "type": "uint256" } ], @@ -239,6 +261,22 @@ "name": "UnexpectedFinalExitedValidatorsCount", "type": "error" }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "expectedId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "actualId", + "type": "uint256" + } + ], + "name": "UnexpectedModuleId", + "type": "error" + }, { "inputs": [], "name": "UnrecoverableModuleError", @@ -246,17 +284,27 @@ }, { "inputs": [], - "name": "ZeroAddressAdmin", + "name": "WrongPubkeyLength", + "type": "error" + }, + { + "inputs": [], + "name": "WrongWithdrawalCredentialsType", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", "type": "error" }, { "inputs": [], - "name": "ZeroAddressLido", + "name": "ZeroArgument", "type": "error" }, { "inputs": [], - "name": "ZeroAddressStakingModule", + "name": "ZeroDeposits", "type": "error" }, { @@ -265,11 +313,11 @@ { "indexed": false, "internalType": "uint256", - "name": "version", + "name": "amount", "type": "uint256" } ], - "name": "ContractVersionSet", + "name": "DepositableEthReceived", "type": "event" }, { @@ -291,6 +339,38 @@ "name": "ExitedAndStuckValidatorsCountsUpdateFailed", "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": "maxTopUpPerBlockGwei", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "setBy", + "type": "address" + } + ], + "name": "MaxTopUpPerBlockGweiSet", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -416,6 +496,31 @@ "name": "StakingModuleAdded", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "stakingModuleId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "nodeOperatorId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "_publicKey", + "type": "bytes" + } + ], + "name": "StakingModuleExitNotificationFailed", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -558,7 +663,7 @@ }, { "indexed": false, - "internalType": "enum StakingRouter.StakingModuleStatus", + "internalType": "enum StakingModuleStatus", "name": "status", "type": "uint8" }, @@ -591,6 +696,25 @@ "name": "StakingRouterETHDeposited", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "stakingModuleId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "StakingRouterETHTopUp", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -668,6 +792,45 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "INITIAL_DEPOSIT_SIZE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LIDO", + "outputs": [ + { + "internalType": "contract ILido", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LIDO_LOCATOR", + "outputs": [ + { + "internalType": "contract ILidoLocator", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "MANAGE_WITHDRAWAL_CREDENTIALS_ROLE", @@ -683,7 +846,7 @@ }, { "inputs": [], - "name": "MAX_STAKING_MODULES_COUNT", + "name": "MAX_EFFECTIVE_BALANCE_WC_TYPE_01", "outputs": [ { "internalType": "uint256", @@ -696,7 +859,7 @@ }, { "inputs": [], - "name": "MAX_STAKING_MODULE_NAME_LENGTH", + "name": "MAX_EFFECTIVE_BALANCE_WC_TYPE_02", "outputs": [ { "internalType": "uint256", @@ -709,33 +872,33 @@ }, { "inputs": [], - "name": "REPORT_EXITED_VALIDATORS_ROLE", + "name": "MAX_STAKING_MODULES_COUNT", "outputs": [ { - "internalType": "bytes32", + "internalType": "uint256", "name": "", - "type": "bytes32" + "type": "uint256" } ], - "stateMutability": "view", + "stateMutability": "pure", "type": "function" }, { "inputs": [], - "name": "REPORT_REWARDS_MINTED_ROLE", + "name": "MAX_STAKING_MODULE_NAME_LENGTH", "outputs": [ { - "internalType": "bytes32", + "internalType": "uint256", "name": "", - "type": "bytes32" + "type": "uint256" } ], - "stateMutability": "view", + "stateMutability": "pure", "type": "function" }, { "inputs": [], - "name": "REPORT_VALIDATOR_EXITING_STATUS_ROLE", + "name": "REPORT_EXITED_VALIDATORS_ROLE", "outputs": [ { "internalType": "bytes32", @@ -748,7 +911,7 @@ }, { "inputs": [], - "name": "REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE", + "name": "REPORT_REWARDS_MINTED_ROLE", "outputs": [ { "internalType": "bytes32", @@ -761,7 +924,7 @@ }, { "inputs": [], - "name": "STAKING_MODULE_MANAGE_ROLE", + "name": "REPORT_VALIDATOR_EXITING_STATUS_ROLE", "outputs": [ { "internalType": "bytes32", @@ -774,7 +937,7 @@ }, { "inputs": [], - "name": "STAKING_MODULE_UNVETTING_ROLE", + "name": "REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE", "outputs": [ { "internalType": "bytes32", @@ -787,12 +950,12 @@ }, { "inputs": [], - "name": "TOTAL_BASIS_POINTS", + "name": "STAKING_MODULE_MANAGE_ROLE", "outputs": [ { - "internalType": "uint256", + "internalType": "bytes32", "name": "", - "type": "uint256" + "type": "bytes32" } ], "stateMutability": "view", @@ -800,7 +963,46 @@ }, { "inputs": [], - "name": "UNSAFE_SET_EXITED_VALIDATORS_ROLE", + "name": "STAKING_MODULE_SHARE_MANAGE_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "STAKING_MODULE_UNVETTING_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TOTAL_BASIS_POINTS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "UNSAFE_SET_EXITED_VALIDATORS_ROLE", "outputs": [ { "internalType": "bytes32", @@ -824,34 +1026,46 @@ "type": "address" }, { - "internalType": "uint256", - "name": "_stakeShareLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_priorityExitShareThreshold", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_stakingModuleFee", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_treasuryFee", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_maxDepositsPerBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_minDepositBlockDistance", - "type": "uint256" + "components": [ + { + "internalType": "uint256", + "name": "stakeShareLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "priorityExitShareThreshold", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "stakingModuleFee", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "treasuryFee", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxDepositsPerBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minDepositBlockDistance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "withdrawalCredentialsType", + "type": "uint256" + } + ], + "internalType": "struct StakingModuleConfig", + "name": "_stakingModuleConfig", + "type": "tuple" } ], "name": "addStakingModule", @@ -884,11 +1098,6 @@ }, { "inputs": [ - { - "internalType": "uint256", - "name": "_depositsCount", - "type": "uint256" - }, { "internalType": "uint256", "name": "_stakingModuleId", @@ -902,12 +1111,18 @@ ], "name": "deposit", "outputs": [], - "stateMutability": "payable", + "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [], - "name": "finalizeUpgrade_v3", + "inputs": [ + { + "internalType": "uint256", + "name": "_maxTopUpPerBlockGwei", + "type": "uint256" + } + ], + "name": "finalizeUpgrade_v4", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -977,12 +1192,12 @@ "type": "uint256" } ], - "internalType": "struct StakingRouter.NodeOperatorSummary", + "internalType": "struct NodeOperatorSummary", "name": "summary", "type": "tuple" } ], - "internalType": "struct StakingRouter.NodeOperatorDigest[]", + "internalType": "struct NodeOperatorDigest[]", "name": "", "type": "tuple[]" } @@ -1072,9 +1287,19 @@ "internalType": "uint64", "name": "minDepositBlockDistance", "type": "uint64" + }, + { + "internalType": "uint8", + "name": "withdrawalCredentialsType", + "type": "uint8" + }, + { + "internalType": "uint64", + "name": "validatorsBalanceGwei", + "type": "uint64" } ], - "internalType": "struct StakingRouter.StakingModule", + "internalType": "struct StakingModule", "name": "state", "type": "tuple" }, @@ -1096,12 +1321,12 @@ "type": "uint256" } ], - "internalType": "struct StakingRouter.StakingModuleSummary", + "internalType": "struct StakingModuleSummary", "name": "summary", "type": "tuple" } ], - "internalType": "struct StakingRouter.StakingModuleDigest[]", + "internalType": "struct StakingModuleDigest[]", "name": "", "type": "tuple[]" } @@ -1126,20 +1351,30 @@ "inputs": [ { "internalType": "uint256", - "name": "_depositsCount", + "name": "_depositAmount", "type": "uint256" + }, + { + "internalType": "bool", + "name": "_isTopUp", + "type": "bool" } ], - "name": "getDepositsAllocation", + "name": "getDepositAllocations", "outputs": [ { "internalType": "uint256", - "name": "allocated", + "name": "totalAllocated", "type": "uint256" }, { "internalType": "uint256[]", - "name": "allocations", + "name": "allocated", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "newAllocations", "type": "uint256[]" } ], @@ -1148,12 +1383,31 @@ }, { "inputs": [], - "name": "getLido", + "name": "getMaxTopUpPerBlockGwei", "outputs": [ { - "internalType": "address", + "internalType": "uint64", "name": "", - "type": "address" + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "moduleId", + "type": "uint256" + } + ], + "name": "getModuleValidatorsBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" } ], "stateMutability": "view", @@ -1229,12 +1483,12 @@ "type": "uint256" } ], - "internalType": "struct StakingRouter.NodeOperatorSummary", + "internalType": "struct NodeOperatorSummary", "name": "summary", "type": "tuple" } ], - "internalType": "struct StakingRouter.NodeOperatorDigest[]", + "internalType": "struct NodeOperatorDigest[]", "name": "digests", "type": "tuple[]" } @@ -1317,12 +1571,12 @@ "type": "uint256" } ], - "internalType": "struct StakingRouter.NodeOperatorSummary", + "internalType": "struct NodeOperatorSummary", "name": "summary", "type": "tuple" } ], - "internalType": "struct StakingRouter.NodeOperatorDigest[]", + "internalType": "struct NodeOperatorDigest[]", "name": "", "type": "tuple[]" } @@ -1388,7 +1642,7 @@ "type": "uint256" } ], - "internalType": "struct StakingRouter.NodeOperatorSummary", + "internalType": "struct NodeOperatorSummary", "name": "summary", "type": "tuple" } @@ -1458,6 +1712,25 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleMembers", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "getStakingFeeAggregateDistribution", @@ -1575,9 +1848,19 @@ "internalType": "uint64", "name": "minDepositBlockDistance", "type": "uint64" + }, + { + "internalType": "uint8", + "name": "withdrawalCredentialsType", + "type": "uint8" + }, + { + "internalType": "uint64", + "name": "validatorsBalanceGwei", + "type": "uint64" } ], - "internalType": "struct StakingRouter.StakingModule", + "internalType": "struct StakingModule", "name": "", "type": "tuple" } @@ -1692,9 +1975,19 @@ "internalType": "uint64", "name": "minDepositBlockDistance", "type": "uint64" + }, + { + "internalType": "uint8", + "name": "withdrawalCredentialsType", + "type": "uint8" + }, + { + "internalType": "uint64", + "name": "validatorsBalanceGwei", + "type": "uint64" } ], - "internalType": "struct StakingRouter.StakingModule", + "internalType": "struct StakingModule", "name": "state", "type": "tuple" }, @@ -1716,12 +2009,12 @@ "type": "uint256" } ], - "internalType": "struct StakingRouter.StakingModuleSummary", + "internalType": "struct StakingModuleSummary", "name": "summary", "type": "tuple" } ], - "internalType": "struct StakingRouter.StakingModuleDigest[]", + "internalType": "struct StakingModuleDigest[]", "name": "digests", "type": "tuple[]" } @@ -1735,7 +2028,7 @@ "outputs": [ { "internalType": "uint256[]", - "name": "stakingModuleIds", + "name": "", "type": "uint256[]" } ], @@ -1899,6 +2192,127 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_stakingModuleId", + "type": "uint256" + } + ], + "name": "getStakingModuleStateAccounting", + "outputs": [ + { + "internalType": "uint64", + "name": "validatorsBalanceGwei", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "exitedValidatorsCount", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_stakingModuleId", + "type": "uint256" + } + ], + "name": "getStakingModuleStateConfig", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "moduleAddress", + "type": "address" + }, + { + "internalType": "uint16", + "name": "moduleFee", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "treasuryFee", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "stakeShareLimit", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "priorityExitShareThreshold", + "type": "uint16" + }, + { + "internalType": "enum StakingModuleStatus", + "name": "status", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "withdrawalCredentialsType", + "type": "uint8" + } + ], + "internalType": "struct ModuleStateConfig", + "name": "stateConfig", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_stakingModuleId", + "type": "uint256" + } + ], + "name": "getStakingModuleStateDeposits", + "outputs": [ + { + "components": [ + { + "internalType": "uint64", + "name": "lastDepositAt", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "lastDepositBlock", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "maxDepositsPerBlock", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "minDepositBlockDistance", + "type": "uint64" + } + ], + "internalType": "struct ModuleStateDeposits", + "name": "stateDeposits", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -1910,7 +2324,7 @@ "name": "getStakingModuleStatus", "outputs": [ { - "internalType": "enum StakingRouter.StakingModuleStatus", + "internalType": "enum StakingModuleStatus", "name": "", "type": "uint8" } @@ -1946,7 +2360,7 @@ "type": "uint256" } ], - "internalType": "struct StakingRouter.StakingModuleSummary", + "internalType": "struct StakingModuleSummary", "name": "summary", "type": "tuple" } @@ -1954,6 +2368,25 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_stakingModuleId", + "type": "uint256" + } + ], + "name": "getStakingModuleWithdrawalCredentials", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "getStakingModules", @@ -2024,10 +2457,20 @@ "internalType": "uint64", "name": "minDepositBlockDistance", "type": "uint64" + }, + { + "internalType": "uint8", + "name": "withdrawalCredentialsType", + "type": "uint8" + }, + { + "internalType": "uint64", + "name": "validatorsBalanceGwei", + "type": "uint64" } ], - "internalType": "struct StakingRouter.StakingModule[]", - "name": "res", + "internalType": "struct StakingModule[]", + "name": "", "type": "tuple[]" } ], @@ -2093,6 +2536,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "getTotalModulesValidatorsBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "getWithdrawalCredentials", @@ -2174,15 +2630,15 @@ "name": "_admin", "type": "address" }, - { - "internalType": "address", - "name": "_lido", - "type": "address" - }, { "internalType": "bytes32", "name": "_withdrawalCredentials", "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_maxTopUpPerBlockGwei", + "type": "uint256" } ], "name": "initialize", @@ -2193,19 +2649,26 @@ { "inputs": [ { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_nodeOperatorId", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_publicKey", - "type": "bytes" + "components": [ + { + "internalType": "uint256", + "name": "stakingModuleId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "nodeOperatorId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "pubkey", + "type": "bytes" + } + ], + "internalType": "struct ValidatorExitData[]", + "name": "validatorExitData", + "type": "tuple[]" }, { "internalType": "uint256", @@ -2230,6 +2693,13 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [], + "name": "receiveDepositableEther", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, { "inputs": [ { @@ -2239,7 +2709,7 @@ }, { "internalType": "address", - "name": "account", + "name": "callerConfirmation", "type": "address" } ], @@ -2289,6 +2759,24 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "_stakingModuleIds", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "_validatorBalancesGwei", + "type": "uint256[]" + } + ], + "name": "reportValidatorBalancesByStakingModule", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -2340,6 +2828,19 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_newValue", + "type": "uint256" + } + ], + "name": "setMaxTopUpPerBlockGwei", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -2348,7 +2849,7 @@ "type": "uint256" }, { - "internalType": "enum StakingRouter.StakingModuleStatus", + "internalType": "enum StakingModuleStatus", "name": "_status", "type": "uint8" } @@ -2390,6 +2891,39 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_stakingModuleId", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "_keyIndices", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "_operatorIds", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "_pubkeys", + "type": "bytes[]" + }, + { + "internalType": "uint256[]", + "name": "_topUpLimits", + "type": "uint256[]" + } + ], + "name": "topUp", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -2430,7 +2964,7 @@ "type": "uint256" } ], - "internalType": "struct StakingRouter.ValidatorsCountsCorrection", + "internalType": "struct ValidatorsCountsCorrection", "name": "_correction", "type": "tuple" } @@ -2440,6 +2974,24 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "_stakingModuleFees", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "_treasuryFees", + "type": "uint256[]" + } + ], + "name": "updateAllStakingModulesFees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -2472,17 +3024,17 @@ "type": "uint256" }, { - "internalType": "uint256", - "name": "_nodeOperatorId", - "type": "uint256" + "internalType": "uint16", + "name": "_stakeShareLimit", + "type": "uint16" }, { - "internalType": "uint256", - "name": "_refundedValidatorsCount", - "type": "uint256" + "internalType": "uint16", + "name": "_priorityExitShareThreshold", + "type": "uint16" } ], - "name": "updateRefundedValidatorsCount", + "name": "updateModuleShares", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -2558,6 +3110,24 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "_stakingModuleIds", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "_validatorBalancesGwei", + "type": "uint256[]" + } + ], + "name": "validateReportValidatorBalancesByStakingModule", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, { "stateMutability": "payable", "type": "receive" diff --git a/interfaces/TopUpGateway.json b/interfaces/TopUpGateway.json new file mode 100644 index 00000000..53345f87 --- /dev/null +++ b/interfaces/TopUpGateway.json @@ -0,0 +1,1041 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_lidoLocator", + "type": "address" + }, + { + "internalType": "GIndex", + "name": "_gIFirstValidatorPrev", + "type": "bytes32" + }, + { + "internalType": "GIndex", + "name": "_gIFirstValidatorCurr", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "_pivotSlot", + "type": "uint64" + }, + { + "internalType": "uint256", + "name": "_slotsPerEpoch", + "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": "IndexOutOfRange", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPubkeyLength", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSlot", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidValidatorIndicesSortOrder", + "type": "error" + }, + { + "inputs": [], + "name": "MaxValidatorsPerTopUpExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "MinBlockDistanceNotMet", + "type": "error" + }, + { + "inputs": [], + "name": "MinTopUpExceedsTarget", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [], + "name": "PauseUntilMustBeInFuture", + "type": "error" + }, + { + "inputs": [], + "name": "PausedExpected", + "type": "error" + }, + { + "inputs": [], + "name": "ResumedExpected", + "type": "error" + }, + { + "inputs": [], + "name": "RootIsTooOld", + "type": "error" + }, + { + "inputs": [], + "name": "RootNotFound", + "type": "error" + }, + { + "inputs": [], + "name": "RootPrecedesLastTopUp", + "type": "error" + }, + { + "inputs": [], + "name": "TooLargeValue", + "type": "error" + }, + { + "inputs": [], + "name": "ValidatorIsNotActivated", + "type": "error" + }, + { + "inputs": [], + "name": "WrongArrayLength", + "type": "error" + }, + { + "inputs": [], + "name": "WrongPubkeyLength", + "type": "error" + }, + { + "inputs": [], + "name": "WrongWithdrawalCredentials", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "argument", + "type": "string" + } + ], + "name": "ZeroArgument", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroPauseDuration", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroValue", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "version", + "type": "uint64" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "newValue", + "type": "uint256" + } + ], + "name": "LastTopUpChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "newValue", + "type": "uint256" + } + ], + "name": "MaxRootAgeChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "newValue", + "type": "uint256" + } + ], + "name": "MaxValidatorsPerTopUpChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "newValue", + "type": "uint256" + } + ], + "name": "MinBlockDistanceChanged", + "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": "targetBalanceGwei", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "minTopUpGwei", + "type": "uint256" + } + ], + "name": "TopUpBalanceLimitsChanged", + "type": "event" + }, + { + "inputs": [], + "name": "BEACON_ROOTS", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "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_STATE_ROOT", + "outputs": [ + { + "internalType": "GIndex", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MANAGE_LIMITS_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": "PIVOT_SLOT", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "RESUME_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SLOTS_PER_EPOCH", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TOP_UP_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLastTopUpTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getMaxRootAge", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getMaxValidatorsPerTopUp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getMinBlockDistance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getMinTopUpGwei", + "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" + } + ], + "name": "getRoleMembers", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTargetBalanceGwei", + "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": "uint256", + "name": "_maxValidatorsPerTopUp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_minTopUpBlockDistance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_maxRootAgeSec", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_targetBalanceGwei", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_minTopUpGwei", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "isBlockDistancePassed", + "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": "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": "uint256", + "name": "_newValue", + "type": "uint256" + } + ], + "name": "setMaxRootAge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_newValue", + "type": "uint256" + } + ], + "name": "setMaxValidatorsPerTopUp", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_newValue", + "type": "uint256" + } + ], + "name": "setMinBlockDistance", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_targetBalanceGwei", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_minTopUpGwei", + "type": "uint256" + } + ], + "name": "setTopUpBalanceLimits", + "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": "moduleId", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "keyIndices", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "operatorIds", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "validatorIndices", + "type": "uint256[]" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "childBlockTimestamp", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "slot", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "proposerIndex", + "type": "uint64" + } + ], + "internalType": "struct BeaconRootData", + "name": "beaconRootData", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "bytes32[]", + "name": "proofValidator", + "type": "bytes32[]" + }, + { + "internalType": "bytes", + "name": "pubkey", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "effectiveBalance", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "activationEligibilityEpoch", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "activationEpoch", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "exitEpoch", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "withdrawableEpoch", + "type": "uint64" + }, + { + "internalType": "bool", + "name": "slashed", + "type": "bool" + } + ], + "internalType": "struct ValidatorWitness[]", + "name": "validatorWitness", + "type": "tuple[]" + }, + { + "internalType": "uint256[]", + "name": "pendingBalanceGwei", + "type": "uint256[]" + } + ], + "internalType": "struct TopUpData", + "name": "_topUps", + "type": "tuple" + } + ], + "name": "topUp", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/interfaces/UpgradeVoteScript.json b/interfaces/UpgradeVoteScript.json new file mode 100644 index 00000000..d712bb32 --- /dev/null +++ b/interfaces/UpgradeVoteScript.json @@ -0,0 +1,266 @@ +[ + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "upgradeTemplate", + "type": "address" + } + ], + "internalType": "struct UpgradeVoteScript.ScriptParams", + "name": "_params", + "type": "tuple" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "actual", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expected", + "type": "uint256" + } + ], + "name": "InvalidItemsCount", + "type": "error" + }, + { + "inputs": [], + "name": "CONFIG", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DG_ITEMS_COUNT", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TEMPLATE", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "VOTING_ITEMS_COUNT", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "proposalMetadata", + "type": "string" + } + ], + "name": "getEVMScript", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "description", + "type": "string" + }, + { + "internalType": "string", + "name": "proposalMetadata", + "type": "string" + } + ], + "name": "getNewVoteCallBytecode", + "outputs": [ + { + "internalType": "bytes", + "name": "newVoteBytecode", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getVoteItems", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "description", + "type": "string" + }, + { + "components": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "internalType": "struct OmnibusBase.ScriptCall", + "name": "call", + "type": "tuple" + } + ], + "internalType": "struct OmnibusBase.VoteItem[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getVoteItemsRaw", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "description", + "type": "string" + }, + { + "components": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "internalType": "struct OmnibusBase.ScriptCall", + "name": "call", + "type": "tuple" + } + ], + "internalType": "struct OmnibusBase.VoteItem[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getVotingVoteItems", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "description", + "type": "string" + }, + { + "components": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "internalType": "struct OmnibusBase.ScriptCall", + "name": "call", + "type": "tuple" + } + ], + "internalType": "struct OmnibusBase.VoteItem[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "voteId", + "type": "uint256" + }, + { + "internalType": "string", + "name": "proposalMetadata", + "type": "string" + } + ], + "name": "isValidVoteScript", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/interfaces/WithdrawalVault.json b/interfaces/WithdrawalVault.json index 4d6c2157..dd1048aa 100644 --- a/interfaces/WithdrawalVault.json +++ b/interfaces/WithdrawalVault.json @@ -15,6 +15,21 @@ "internalType": "address", "name": "_triggerableWithdrawalsGateway", "type": "address" + }, + { + "internalType": "address", + "name": "_consolidationGateway", + "type": "address" + }, + { + "internalType": "address", + "name": "_withdrawalRequest", + "type": "address" + }, + { + "internalType": "address", + "name": "_consolidationRequest", + "type": "address" } ], "stateMutability": "nonpayable", @@ -50,12 +65,12 @@ "inputs": [ { "internalType": "uint256", - "name": "providedFee", + "name": "requiredFee", "type": "uint256" }, { "internalType": "uint256", - "name": "requiredFee", + "name": "providedFee", "type": "uint256" } ], @@ -67,11 +82,27 @@ "name": "InvalidContractVersionIncrement", "type": "error" }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "pubkey", + "type": "bytes" + } + ], + "name": "InvalidPublicKeyLength", + "type": "error" + }, { "inputs": [], "name": "NonZeroContractVersionOnInit", "type": "error" }, + { + "inputs": [], + "name": "NotConsolidationGateway", + "type": "error" + }, { "inputs": [ { @@ -146,6 +177,19 @@ "name": "ZeroArgument", "type": "error" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes", + "name": "request", + "type": "bytes" + } + ], + "name": "ConsolidationRequestAdded", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -222,6 +266,32 @@ "name": "WithdrawalRequestAdded", "type": "event" }, + { + "inputs": [], + "name": "CONSOLIDATION_GATEWAY", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CONSOLIDATION_REQUEST", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "LIDO", @@ -261,6 +331,37 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "WITHDRAWAL_REQUEST", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "sourcePubkeys", + "type": "bytes[]" + }, + { + "internalType": "bytes[]", + "name": "targetPubkeys", + "type": "bytes[]" + } + ], + "name": "addConsolidationRequests", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, { "inputs": [ { @@ -281,11 +382,24 @@ }, { "inputs": [], - "name": "finalizeUpgrade_v2", + "name": "finalizeUpgrade_v3", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [], + "name": "getConsolidationRequestFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "getContractVersion", @@ -368,4 +482,4 @@ "stateMutability": "nonpayable", "type": "function" } -] +] \ No newline at end of file diff --git a/scripts/upgrade_2026_04_30_srv3_cmv2.py b/scripts/upgrade_2026_04_30_srv3_cmv2.py new file mode 100644 index 00000000..0e7fe30b --- /dev/null +++ b/scripts/upgrade_2026_04_30_srv3_cmv2.py @@ -0,0 +1,227 @@ +""" +Vote 2026_04_30 + +1. Submit a Dual Governance proposal to activate Staking Router v3 + Curated Module v2 + Community Staking Module v3 +# ======================== Core ======================== +1.1. Call UpgradeTemplate.startUpgrade +1.2. Upgrade LidoLocator implementation +1.3. Upgrade and finalize StakingRouter +1.4. Upgrade and finalize AccountingOracle +1.5. Upgrade and finalize ValidatorsExitBusOracle +1.6. Upgrade Accounting implementation +1.7. Upgrade WithdrawalVault implementation +1.8. Grant Aragon APP_MANAGER_ROLE to the AGENT +1.9. Set Lido implementation in Kernel +1.10. Revoke Aragon APP_MANAGER_ROLE from the AGENT +1.11. Create and grant Aragon BUFFER_RESERVE_MANAGER_ROLE to the AGENT +1.12. Call finalizeUpgrade_v4 on Lido +1.13. Grant STAKING_MODULE_SHARE_MANAGE_ROLE to EasyTrack executor +1.14. Revoke STAKING_MODULE_UNVETTING_ROLE from old DSM +1.15. Grant STAKING_MODULE_UNVETTING_ROLE to new DSM +1.16. Grant TW_EXIT_LIMIT_MANAGER_ROLE to Agent on TWGateway +1.17. Set TWGateway exit request limits +1.18. Register CircuitBreaker pauser for ConsolidationGateway +# ======================== CSM ======================== +1.19. Upgrade and finalize CSM v3 +1.20. Upgrade and finalize ParametersRegistry v3 +1.21. Upgrade and finalize FeeOracle v3 +1.22. Upgrade CSVettedGate implementation +1.23. Upgrade and finalize Accounting v3 +1.24. Upgrade and finalize FeeDistributor v3 +1.25. Upgrade ExitPenalties implementation +1.26. Upgrade ValidatorStrikes implementation +1.27. Point ValidatorStrikes to the new Ejector +1.28. Revoke REPORT_EL_REWARDS_STEALING_PENALTY_ROLE +1.29. Grant REPORT_GENERAL_DELAYED_PENALTY_ROLE +1.30. Revoke SETTLE_EL_REWARDS_STEALING_PENALTY_ROLE +1.31. Grant SETTLE_GENERAL_DELAYED_PENALTY_ROLE +1.32. Revoke VERIFIER_ROLE from old verifier +1.33. Grant VERIFIER_ROLE to new verifier +1.34. Grant REPORT_REGULAR_WITHDRAWN_VALIDATORS_ROLE to VerifierV3 +1.35. Grant REPORT_SLASHED_WITHDRAWN_VALIDATORS_ROLE to Easy Track +1.36. Revoke CREATE_NODE_OPERATOR_ROLE from old PermissionlessGate +1.37. Grant CREATE_NODE_OPERATOR_ROLE to new PermissionlessGate +1.38. Revoke START_REFERRAL_SEASON_ROLE +1.39. Revoke END_REFERRAL_SEASON_ROLE +1.40. Register CircuitBreaker pauser for CSM new verifier +1.41. Register CircuitBreaker pauser for CSM Ejector +1.42. Register CircuitBreaker pauser for CSM identified DVT cluster gate +1.43. Grant CREATE_NODE_OPERATOR_ROLE to identified DVT cluster gate +1.44. Grant SET_BOND_CURVE_ROLE to identified DVT cluster gate +1.45. Grant MANAGE_BOND_CURVES_ROLE to identified DVT cluster curve setup +1.46. Grant MANAGE_CURVE_PARAMETERS_ROLE to identified DVT cluster curve setup +1.47. Execute identified DVT cluster curve setup +1.48. Grant MANAGE_GENERAL_PENALTIES_AND_CHARGES_ROLE to CSM Committee +1.49. Revoke REQUEST_BURN_SHARES_ROLE from CSM Accounting +1.50. Grant REQUEST_BURN_MY_STETH_ROLE to CSM Accounting +1.51. Revoke TWG full-withdrawal role from old Ejector +1.52. Grant TWG full-withdrawal role to new Ejector +# ======================== Curated Module ======================== +1.53. Add Curated module to StakingRouter +1.54. Grant REQUEST_BURN_MY_STETH_ROLE to Curated Accounting +1.55. Grant TWG full-withdrawal role to Curated Ejector +1.56. Grant RESUME_ROLE to agent on Curated module +1.57. Resume Curated module +1.58. Revoke RESUME_ROLE from agent on Curated module +1.59. Update Curated HashConsensus frame config +1.60. Register CircuitBreaker pauser for Curated module +1.61. Register CircuitBreaker pauser for Curated Accounting +1.62. Register CircuitBreaker pauser for Curated FeeOracle +1.63. Register CircuitBreaker pauser for Curated Verifier +1.64. Register CircuitBreaker pauser for Curated Ejector +# ======================== Finish Upgrade ======================== +1.65. Call UpgradeTemplate.finishUpgrade + +# ======================== EasyTrack ======================== +2. Remove CSMSettleElStealingPenalty ET factory +3. Remove CSMSetVettedGateTree ET factory +4. Add UpdateStakingModuleShareLimits ET factory +5. Add AllowConsolidationPair ET factory +6. Add SetMerkleGateTree CSM ET factory +7. Add ReportWithdrawalsForSlashedValidators CSM ET factory +8. Add SettleGeneralDelayedPenalty CSM ET factory +9. Add SetMerkleGateTree CM ET factory +10. Add ReportWithdrawalsForSlashedValidators CM ET factory +11. Add SettleGeneralDelayedPenalty CM ET factory +12. Add CreateOrUpdateOperatorGroup CM ET factory + +Vote passed & executed on Apr-30-2026 02:04:12 PM +UTC, block 2721709. + +""" + +from typing import Dict, List, Optional, Tuple + +from brownie import interface + +from utils.config import ( + UPGRADE_VOTE_SCRIPT, + get_deployer_account, + get_is_live, + get_priority_fee, +) +from utils.dual_governance import submit_proposals +from utils.ipfs import calculate_vote_ipfs_description, upload_vote_ipfs_description +from utils.mainnet_fork import pass_and_exec_dao_vote +from utils.voting import bake_vote_items, confirm_vote_script, create_vote + + +# UPGRADE_VOTE_SCRIPT address lives in configs/config_mainnet.py and is synced +# from core/deployed-local.json by sync_fork_addresses.py. + +# ============================= Description ================================== +DG_PROPOSAL_METADATA = "Activate Staking Router v3 + Curated Module v2 + Community Staking Module v3" +DG_SUBMISSION_DESCRIPTION = "1. Submit a Dual Governance proposal to activate Staking Router v3 + Curated Module v2 + Community Staking Module v3" +IPFS_DESCRIPTION = """ +1. **Activate Staking Router v3**, including protocol contract upgrades and Dual Governance execution setup. Items 1.1-1.18. +2. **Upgrade Community Staking Module to v3**, including CSM contract upgrades, role updates and identified DVT cluster setup. Items 1.19-1.52. +3. **Add and configure Curated Module v2**. Items 1.53-1.64. +4. **Finalize the protocol upgrade**. Item 1.65. +5. **Update Easy Track factories for CSM v3 and Curated Module v2 operations**. Items 2-12. +""" + + +def is_placeholder_vote_script_address(value: str) -> bool: + normalized = value.strip().lower() + return normalized in ( + "", + "0x0000000000000000000000000000000000000000", + ) or normalized.startswith("todo") + + +def get_dg_items(upgrade_vote_script: Optional[str] = None) -> List[Tuple[str, str]]: + vote_script_address = (upgrade_vote_script or UPGRADE_VOTE_SCRIPT).strip() + if is_placeholder_vote_script_address(vote_script_address): + raise ValueError( + "UpgradeVoteScript address is not configured. " + "Pass upgrade_vote_script explicitly or set UPGRADE_VOTE_SCRIPT at the top of this file." + ) + + omnibus = interface.UpgradeVoteScript(vote_script_address) + dg_items: List[Tuple[str, str]] = [] + + for _, call_script in omnibus.getVoteItems(): + dg_items.append((call_script[0], call_script[1].hex())) + + return dg_items + + +def get_vote_items( + upgrade_vote_script: Optional[str] = None, +) -> Tuple[List[str], List[Tuple[str, str]]]: + vote_script_address = (upgrade_vote_script or UPGRADE_VOTE_SCRIPT).strip() + if is_placeholder_vote_script_address(vote_script_address): + raise ValueError( + "UpgradeVoteScript address is not configured. " + "Pass upgrade_vote_script explicitly or set UPGRADE_VOTE_SCRIPT at the top of this file." + ) + + omnibus = interface.UpgradeVoteScript(vote_script_address) + + vote_desc_items: List[str] = [] + call_script_items: List[Tuple[str, str]] = [] + + dg_items = get_dg_items(upgrade_vote_script) + + dg_call_script = submit_proposals([(dg_items, DG_PROPOSAL_METADATA)]) + vote_desc_items.append(DG_SUBMISSION_DESCRIPTION) + call_script_items.append(dg_call_script[0]) + + voting_items = omnibus.getVotingVoteItems() + for desc, call_script in voting_items: + vote_desc_items.append(desc) + call_script_items.append((call_script[0], call_script[1].hex())) + + return vote_desc_items, call_script_items + + +def start_vote( + tx_params: Dict[str, str], + silent: bool = False, + upgrade_vote_script: Optional[str] = None, +): + vote_desc_items, call_script_items = get_vote_items( + upgrade_vote_script=upgrade_vote_script, + ) + 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) + ) + + vote_id, tx = confirm_vote_script(vote_items, silent, desc_ipfs) and list( + create_vote(vote_items, tx_params, desc_ipfs=desc_ipfs) + ) + + vote_script_address = (upgrade_vote_script or UPGRADE_VOTE_SCRIPT).strip() + assert interface.UpgradeVoteScript(vote_script_address).isValidVoteScript( + vote_id, + DG_PROPOSAL_METADATA, + ) + + return vote_id, tx + + +def main(upgrade_vote_script: Optional[str] = None): + 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, + upgrade_vote_script=upgrade_vote_script, + ) + vote_id >= 0 and print(f"Vote created: {vote_id}.") + + +def start_and_execute_vote_on_fork_manual(upgrade_vote_script: Optional[str] = None): + 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, + upgrade_vote_script=upgrade_vote_script, + ) + print(f"Vote created: {vote_id}.") + pass_and_exec_dao_vote(int(vote_id), step_by_step=True) diff --git a/tests/acceptance/test_accounting_oracle.py b/tests/acceptance/test_accounting_oracle.py index a0459ee6..65c9a239 100644 --- a/tests/acceptance/test_accounting_oracle.py +++ b/tests/acceptance/test_accounting_oracle.py @@ -17,6 +17,7 @@ ) from utils.evm_script import encode_error + @pytest.fixture(scope="module") def contract() -> interface.AccountingOracle: return interface.AccountingOracle(ACCOUNTING_ORACLE) @@ -39,7 +40,7 @@ def test_constants(contract): def test_versioned(contract): - assert contract.getContractVersion() == 4 + assert contract.getContractVersion() == 5 # SRv3: finalizeUpgrade_v5 def test_initialize(contract): @@ -65,32 +66,51 @@ def test_petrified(contract): ) +def test_finalize_upgrade(contract): + # SRv3 (vote item 1.4) already bumped the contract version to 5 via + # finalizeUpgrade_v5; a repeated call must revert: 5 != current(5) + 1. + # .call() — anvil does not surface custom-error data for reverted txs. + with reverts(encode_error("InvalidContractVersionIncrement()")): + contract.finalizeUpgrade_v5.call(AO_CONSENSUS_VERSION, {"from": contracts.voting}) + + def test_consensus(contract): assert contract.getConsensusVersion() == AO_CONSENSUS_VERSION assert contract.getConsensusContract() == HASH_CONSENSUS_FOR_AO def test_processing_state(contract): + # Absolute values (deadline, hashes, submitted flags) depend on whether a report + # has landed in the current frame — they change with the fork block / fixture + # timing, so only frame-independent invariants are asserted. + consensus = interface.HashConsensus(contract.getConsensusContract()) state = contract.getProcessingState() + + # frame cross-check with the consensus contract + assert state["currentFrameRefSlot"] == consensus.getCurrentFrame()["refSlot"] assert state["currentFrameRefSlot"] > 5254400 - #assert state["processingDeadlineTime"] == 0 - #assert state["mainDataHash"] == "0x0000000000000000000000000000000000000000000000000000000000000000" - #assert state["mainDataSubmitted"] is False - #assert state["extraDataHash"] == "0x0000000000000000000000000000000000000000000000000000000000000000" - #assert state["extraDataFormat"] == 0 - #assert state["extraDataSubmitted"] is False - #assert state["extraDataItemsCount"] == 0 - #assert state["extraDataItemsSubmitted"] == 0 + # processing never runs ahead of the current frame assert contract.getLastProcessingRefSlot() > 5254400 + assert contract.getLastProcessingRefSlot() <= state["currentFrameRefSlot"] + + if state["mainDataSubmitted"]: + # a submitted report implies processing of the current frame has started + assert state["mainDataHash"] != "0x" + "00" * 32 + assert contract.getLastProcessingRefSlot() == state["currentFrameRefSlot"] + + # extra data can only follow the main report + if state["extraDataSubmitted"]: + assert state["mainDataSubmitted"] + assert state["extraDataItemsSubmitted"] <= state["extraDataItemsCount"] def test_report(contract): report = contract.getConsensusReport() - #assert report["hash"] == "0x0000000000000000000000000000000000000000000000000000000000000000" + # assert report["hash"] == "0x0000000000000000000000000000000000000000000000000000000000000000" assert report["refSlot"] > 5254400 - #assert report["processingDeadlineTime"] == 0 - #assert report["processingStarted"] is False + # assert report["processingDeadlineTime"] == 0 + # assert report["processingStarted"] is False def test_accounting_hash_consensus(contract): diff --git a/tests/acceptance/test_accounting_oracle_negative.py b/tests/acceptance/test_accounting_oracle_negative.py index 3a8080c9..4a17e056 100644 --- a/tests/acceptance/test_accounting_oracle_negative.py +++ b/tests/acceptance/test_accounting_oracle_negative.py @@ -3,7 +3,15 @@ from web3 import Web3 import pytest -from brownie import ZERO_ADDRESS, Contract, MockHashConsensus, accounts, interface, reverts, chain # type: ignore +from brownie import ( + ZERO_ADDRESS, + Contract, + MockHashConsensus, + accounts, + interface, + reverts, + chain, +) # type: ignore from brownie.network.account import Account from configs.config_mainnet import MAX_ITEMS_PER_EXTRA_DATA_TRANSACTION @@ -26,7 +34,9 @@ def chain_time_with_offset(offset: int) -> int: return chain.time() + offset -def test_sender_not_allowed(accounting_oracle: Contract, oracle_version: int, stranger: Account) -> None: +def test_sender_not_allowed( + accounting_oracle: Contract, oracle_version: int, stranger: Account +) -> None: report = oracle_report(dry_run=True) with reverts(encode_error("SenderNotAllowed()")): @@ -36,16 +46,22 @@ def test_sender_not_allowed(accounting_oracle: Contract, oracle_version: int, st accounting_oracle.submitReportExtraDataList(b"", {"from": stranger}) with reverts(encode_error("SenderNotAllowed()")): - accounting_oracle.submitReportData(report.items, oracle_version, {"from": stranger}) + accounting_oracle.submitReportData( + report.items, oracle_version, {"from": stranger} + ) with reverts(encode_error("SenderIsNotTheConsensusContract()")): - accounting_oracle.submitConsensusReport(report.hash, report.refSlot, chain.time(), {"from": stranger}) + accounting_oracle.submitConsensusReport( + report.hash, report.refSlot, chain.time(), {"from": stranger} + ) with reverts(encode_error("SenderIsNotTheConsensusContract()")): accounting_oracle.discardConsensusReport(report.refSlot, {"from": stranger}) -def test_submitConsensusReport(accounting_oracle: Contract, hash_consensus: Contract) -> None: +def test_submitConsensusReport( + accounting_oracle: Contract, hash_consensus: Contract +) -> None: report_if_processing_not_started(accounting_oracle) last_processing_ref_slot = accounting_oracle.getLastProcessingRefSlot() @@ -93,7 +109,9 @@ def test_submitConsensusReport(accounting_oracle: Contract, hash_consensus: Cont ) -def test_discardConsensusReport(accounting_oracle: Contract, hash_consensus: Contract) -> None: +def test_discardConsensusReport( + accounting_oracle: Contract, hash_consensus: Contract +) -> None: report_if_processing_not_started(accounting_oracle) last_processing_ref_slot = accounting_oracle.getLastProcessingRefSlot() @@ -115,7 +133,9 @@ def test_discardConsensusReport(accounting_oracle: Contract, hash_consensus: Con ) -def test_setConsensusVersion(accounting_oracle: Contract, aragon_agent: Account) -> None: +def test_setConsensusVersion( + accounting_oracle: Contract, aragon_agent: Account +) -> None: # There is no role holder after upgrade accounting_oracle.grantRole( accounting_oracle.MANAGE_CONSENSUS_VERSION_ROLE(), @@ -130,7 +150,9 @@ def test_setConsensusVersion(accounting_oracle: Contract, aragon_agent: Account) ) -def test_setConsensusContract(accounting_oracle: Contract, aragon_agent: Account, deployer: Account) -> None: +def test_setConsensusContract( + accounting_oracle: Contract, aragon_agent: Account, deployer: Account +) -> None: # There is no role holder after upgrade accounting_oracle.grantRole( accounting_oracle.MANAGE_CONSENSUS_CONTRACT_ROLE(), @@ -183,13 +205,15 @@ def test_setConsensusContract(accounting_oracle: Contract, aragon_agent: Account def test_finalize_upgrade(accounting_oracle: Contract, stranger: Account): + # SRv3: finalizeUpgrade_v4 was removed; the contract is already at version 5, + # so re-calling finalizeUpgrade_v5 reverts on the version bump (5 != 5 + 1) with reverts(encode_error("InvalidContractVersionIncrement()")): - accounting_oracle.finalizeUpgrade_v4( + accounting_oracle.finalizeUpgrade_v5( 1, {"from": stranger}, ) with reverts(encode_error("InvalidContractVersionIncrement()")): - accounting_oracle.finalizeUpgrade_v4( + accounting_oracle.finalizeUpgrade_v5( 2, {"from": stranger}, ) @@ -211,18 +235,34 @@ def get_nor_operator_exited_keys(self, operator_id: int) -> int: def test_too_short_extra_data_item(self): extra_data = self.build_extra_data( [ - build_extra_data_item(0, ItemType.EXTRA_DATA_TYPE_EXITED_VALIDATORS, 2, [2], [2])[:36], + build_extra_data_item( + 0, ItemType.EXTRA_DATA_TYPE_EXITED_VALIDATORS, 2, [2], [2] + )[:36], ] ) - (_, _, _, _, _, totalExitedValidators, _, _) = contracts.node_operators_registry.getNodeOperatorSummary(2) + (_, _, _, _, _, totalExitedValidators, _, _) = ( + contracts.node_operators_registry.getNodeOperatorSummary(2) + ) with reverts(encode_error("InvalidExtraDataItem(uint256)", [0])): self.report(extra_data) extra_data = self.build_extra_data( [ - build_extra_data_item(0, ItemType.EXTRA_DATA_TYPE_EXITED_VALIDATORS, 1, [2, 3, 4, 5], [totalExitedValidators]), - build_extra_data_item(1, ItemType.EXTRA_DATA_TYPE_EXITED_VALIDATORS, 2, [2], [totalExitedValidators]), + build_extra_data_item( + 0, + ItemType.EXTRA_DATA_TYPE_EXITED_VALIDATORS, + 1, + [2, 3, 4, 5], + [totalExitedValidators], + ), + build_extra_data_item( + 1, + ItemType.EXTRA_DATA_TYPE_EXITED_VALIDATORS, + 2, + [2], + [totalExitedValidators], + ), ] ) @@ -232,7 +272,9 @@ def test_too_short_extra_data_item(self): def test_nos_count_zero(self): extra_data = self.build_extra_data( [ - build_extra_data_item(0, ItemType.EXTRA_DATA_TYPE_EXITED_VALIDATORS, 2, [], [1]), + build_extra_data_item( + 0, ItemType.EXTRA_DATA_TYPE_EXITED_VALIDATORS, 2, [], [1] + ), ] ) @@ -242,8 +284,12 @@ def test_nos_count_zero(self): def test_module_id_zero(self): extra_data = self.build_extra_data( [ - build_extra_data_item(0, ItemType.EXTRA_DATA_TYPE_EXITED_VALIDATORS, 0, [2], [1]), - build_extra_data_item(1, ItemType.EXTRA_DATA_TYPE_EXITED_VALIDATORS, 0, [2], [2]), + build_extra_data_item( + 0, ItemType.EXTRA_DATA_TYPE_EXITED_VALIDATORS, 0, [2], [1] + ), + build_extra_data_item( + 1, ItemType.EXTRA_DATA_TYPE_EXITED_VALIDATORS, 0, [2], [2] + ), ] ) @@ -253,8 +299,12 @@ def test_module_id_zero(self): def test_unexpected_extra_data_index(self): extra_data = self.build_extra_data( [ - build_extra_data_item(1, ItemType.EXTRA_DATA_TYPE_EXITED_VALIDATORS, 1, [2], [1]), - build_extra_data_item(2, ItemType.EXTRA_DATA_TYPE_EXITED_VALIDATORS, 2, [2], [1]), + build_extra_data_item( + 1, ItemType.EXTRA_DATA_TYPE_EXITED_VALIDATORS, 1, [2], [1] + ), + build_extra_data_item( + 2, ItemType.EXTRA_DATA_TYPE_EXITED_VALIDATORS, 2, [2], [1] + ), ] ) @@ -265,8 +315,20 @@ def test_unexpected_extra_data_index(self): extra_data = self.build_extra_data( [ - build_extra_data_item(0, ItemType.EXTRA_DATA_TYPE_EXITED_VALIDATORS, 1, [2], [totalExitedValidators]), - build_extra_data_item(3, ItemType.EXTRA_DATA_TYPE_EXITED_VALIDATORS, 1, [2], [totalExitedValidators]), + build_extra_data_item( + 0, + ItemType.EXTRA_DATA_TYPE_EXITED_VALIDATORS, + 1, + [2], + [totalExitedValidators], + ), + build_extra_data_item( + 3, + ItemType.EXTRA_DATA_TYPE_EXITED_VALIDATORS, + 1, + [2], + [totalExitedValidators], + ), ] ) @@ -277,8 +339,20 @@ def test_unexpected_extra_data_index(self): extra_data = self.build_extra_data( [ - build_extra_data_item(0, ItemType.EXTRA_DATA_TYPE_EXITED_VALIDATORS, 1, [2], [totalExitedValidators]), - build_extra_data_item(0, ItemType.EXTRA_DATA_TYPE_EXITED_VALIDATORS, 1, [2], [totalExitedValidators]), + build_extra_data_item( + 0, + ItemType.EXTRA_DATA_TYPE_EXITED_VALIDATORS, + 1, + [2], + [totalExitedValidators], + ), + build_extra_data_item( + 0, + ItemType.EXTRA_DATA_TYPE_EXITED_VALIDATORS, + 1, + [2], + [totalExitedValidators], + ), ] ) @@ -286,7 +360,9 @@ def test_unexpected_extra_data_index(self): self.report(extra_data) def test_unsupported_extra_data_type(self): - extra_data = self.build_extra_data([build_extra_data_item(0, ItemType.UNSUPPORTED, 1, [1], [1])]) + extra_data = self.build_extra_data( + [build_extra_data_item(0, ItemType.UNSUPPORTED, 1, [1], [1])] + ) with reverts( encode_error( @@ -304,10 +380,20 @@ def test_invalid_extra_data_sort_order_on_same_items(self): extra_data = self.build_extra_data( [ - build_extra_data_item(0, ItemType.EXTRA_DATA_TYPE_EXITED_VALIDATORS, module_id, [operator_id], - [new_exited_keys]), - build_extra_data_item(1, ItemType.EXTRA_DATA_TYPE_EXITED_VALIDATORS, module_id, [operator_id], - [new_exited_keys]), + build_extra_data_item( + 0, + ItemType.EXTRA_DATA_TYPE_EXITED_VALIDATORS, + module_id, + [operator_id], + [new_exited_keys], + ), + build_extra_data_item( + 1, + ItemType.EXTRA_DATA_TYPE_EXITED_VALIDATORS, + module_id, + [operator_id], + [new_exited_keys], + ), ] ) @@ -321,8 +407,20 @@ def test_invalid_extra_data_sort_order_on_same_operator(self): extra_data = self.build_extra_data( [ - build_extra_data_item(0, ItemType.EXTRA_DATA_TYPE_EXITED_VALIDATORS, module_id, [operator_id], [current_exited_keys + 2]), - build_extra_data_item(1, ItemType.EXTRA_DATA_TYPE_EXITED_VALIDATORS, module_id, [operator_id], [current_exited_keys + 1]), + build_extra_data_item( + 0, + ItemType.EXTRA_DATA_TYPE_EXITED_VALIDATORS, + module_id, + [operator_id], + [current_exited_keys + 2], + ), + build_extra_data_item( + 1, + ItemType.EXTRA_DATA_TYPE_EXITED_VALIDATORS, + module_id, + [operator_id], + [current_exited_keys + 1], + ), ] ) @@ -332,19 +430,30 @@ def test_invalid_extra_data_sort_order_on_same_operator(self): def test_invalid_extra_data_sort_order_on_exited(self): module_id = 1 unsorted_operator_ids = [33, 35, 34] - current_exited_keys = [self.get_nor_operator_exited_keys(operator_id) for operator_id in unsorted_operator_ids] + current_exited_keys = [ + self.get_nor_operator_exited_keys(operator_id) + for operator_id in unsorted_operator_ids + ] new_exited_keys = [keys + 1 for keys in current_exited_keys] extra_data = self.build_extra_data( [ - build_extra_data_item(0, ItemType.EXTRA_DATA_TYPE_EXITED_VALIDATORS, module_id, unsorted_operator_ids, new_exited_keys), + build_extra_data_item( + 0, + ItemType.EXTRA_DATA_TYPE_EXITED_VALIDATORS, + module_id, + unsorted_operator_ids, + new_exited_keys, + ), ] ) with reverts(encode_error("InvalidExtraDataSortOrder(uint256)", [0])): self.report(extra_data) - def test_unexpected_extra_data_item(self, extra_data_service: ExtraDataService) -> None: + def test_unexpected_extra_data_item( + self, extra_data_service: ExtraDataService + ) -> None: extra_data = extra_data_service.collect( { (1, 2): self.get_nor_operator_exited_keys(2) + 1, @@ -365,8 +474,8 @@ def test_unexpected_extra_data_item(self, extra_data_service: ExtraDataService) encode_error( "UnexpectedExtraDataItemsCount(uint256,uint256)", [ - extra_data.items_count - 1, # expected count - extra_data.items_count, # received count (all items fit into a single chunk) + extra_data.items_count - 1, # expected count + extra_data.items_count, # received count (all items fit into a single chunk) ], ) ): @@ -688,7 +797,9 @@ def hash_consensus() -> Contract: @pytest.fixture(scope="module") -def push_report(accounting_oracle: Contract, hash_consensus: Contract) -> Callable[[AccountingReport], int]: +def push_report( + accounting_oracle: Contract, hash_consensus: Contract +) -> Callable[[AccountingReport], int]: def wrapped(report: AccountingReport) -> int: deadline = chain.time() + 100 accounting_oracle.submitConsensusReport( @@ -703,7 +814,9 @@ def wrapped(report: AccountingReport) -> int: @pytest.fixture(scope="module") -def submit_main_data(accounting_oracle: Contract, consensus_member: Account) -> Callable[[AccountingReport], None]: +def submit_main_data( + accounting_oracle: Contract, consensus_member: Account +) -> Callable[[AccountingReport], None]: def wrapped(report: AccountingReport) -> None: accounting_oracle.submitReportData( report.items, @@ -739,7 +852,11 @@ def build_extra_data_item( type_.value.to_bytes(FIELDS_WIDTH.ITEM_TYPE, **opts), module_id.to_bytes(FIELDS_WIDTH.MODULE_ID, **opts), len(nos_ids).to_bytes(FIELDS_WIDTH.NODE_OPS_COUNT, **opts), - b"".join(i.to_bytes(FIELDS_WIDTH.NODE_OPERATOR_IDS, **opts) for i in nos_ids), - b"".join(i.to_bytes(FIELDS_WIDTH.EXITED_VALS_COUNT, **opts) for i in vals_count), + b"".join( + i.to_bytes(FIELDS_WIDTH.NODE_OPERATOR_IDS, **opts) for i in nos_ids + ), + b"".join( + i.to_bytes(FIELDS_WIDTH.EXITED_VALS_COUNT, **opts) for i in vals_count + ), ) ) diff --git a/tests/acceptance/test_burner.py b/tests/acceptance/test_burner.py index 95234854..8855e7eb 100644 --- a/tests/acceptance/test_burner.py +++ b/tests/acceptance/test_burner.py @@ -1,9 +1,10 @@ import pytest -from brownie import interface # type: ignore +from brownie import interface, web3 # type: ignore from utils.config import ( contracts, BURNER, + CURATED_V2_ACCOUNTING, TOTAL_NON_COVER_SHARES_BURNT, TOTAL_COVER_SHARES_BURNT, ) @@ -17,3 +18,16 @@ def contract() -> interface.Burner: def test_links(contract): assert contract.LIDO() == contracts.lido assert contract.LOCATOR() == contracts.lido_locator + + +def test_roles(contract): + # Burner role changes made by the SRv3/CMv2 vote (the Burner contract itself is not upgraded). + REQUEST_BURN_SHARES_ROLE = web3.keccak(text="REQUEST_BURN_SHARES_ROLE").hex() + REQUEST_BURN_MY_STETH_ROLE = web3.keccak(text="REQUEST_BURN_MY_STETH_ROLE").hex() + + # CSM Accounting: REQUEST_BURN_SHARES_ROLE revoked, REQUEST_BURN_MY_STETH_ROLE granted + assert not contract.hasRole(REQUEST_BURN_SHARES_ROLE, contracts.cs_accounting) + assert contract.hasRole(REQUEST_BURN_MY_STETH_ROLE, contracts.cs_accounting) + + # Curated (CMv2) Accounting: REQUEST_BURN_MY_STETH_ROLE granted + assert contract.hasRole(REQUEST_BURN_MY_STETH_ROLE, CURATED_V2_ACCOUNTING) diff --git a/tests/acceptance/test_consolidation.py b/tests/acceptance/test_consolidation.py new file mode 100644 index 00000000..4eb2353e --- /dev/null +++ b/tests/acceptance/test_consolidation.py @@ -0,0 +1,257 @@ +""" +Acceptance tests for the consolidation pipeline added by the SRv3 upgrade: + +- ConsolidationGateway — entry point for consolidation requests; deployed directly + (no proxy), admin and limits are set in the constructor; wired into the upgraded + LidoLocator; the vote registers a CircuitBreaker pauser for it (item 1.18). +- ConsolidationBus (OssifiableProxy) — queue/batch layer between the migrator and + the gateway. +- ConsolidationMigrator (OssifiableProxy) — migrates Curated (module id 1) + validators into Curated Module v2 (id 4); pairs are allowed via the EasyTrack + AllowConsolidationPair factory and disallowed by the CMC committee. +""" + +import pytest +from brownie import interface, reverts, web3 # type: ignore +from brownie.convert.datatypes import HexString + +from utils.config import ( + contracts, + AGENT, + CIRCUIT_BREAKER, + RESEAL_MANAGER, + EASYTRACK_EVMSCRIPT_EXECUTOR, + STAKING_ROUTER, + CURATED_V2_STAKING_MODULE_ID, + CONSOLIDATION_GATEWAY, + CONSOLIDATION_GATEWAY_MAX_REQUESTS_LIMIT, + CONSOLIDATION_GATEWAY_CONSOLIDATIONS_PER_FRAME, + CONSOLIDATION_GATEWAY_FRAME_DURATION_IN_SEC, + CONSOLIDATION_BUS, + CONSOLIDATION_BUS_IMPL, + CONSOLIDATION_BUS_BATCH_SIZE, + CONSOLIDATION_BUS_MAX_GROUPS_IN_BATCH, + CONSOLIDATION_BUS_EXECUTION_DELAY, + CONSOLIDATION_MIGRATOR, + CONSOLIDATION_MIGRATOR_IMPL, + CONSOLIDATION_SOURCE_MODULE_ID, + CONSOLIDATION_TARGET_MODULE_ID, + CONSOLIDATION_COMMITTEE, +) +from utils.evm_script import encode_error +from utils.test.helpers import access_control_unauthorized as unauthorized + +DEFAULT_ADMIN_ROLE = "0x" + "00" * 32 +GI_FIRST_VALIDATOR = HexString("0x0000000000000000000000000000000000000000000000000096000000000028", "bytes") + + +@pytest.fixture(scope="module") +def gateway() -> interface.ConsolidationGateway: + return interface.ConsolidationGateway(CONSOLIDATION_GATEWAY) + + +@pytest.fixture(scope="module") +def bus() -> interface.ConsolidationBus: + return interface.ConsolidationBus(CONSOLIDATION_BUS) + + +@pytest.fixture(scope="module") +def migrator() -> interface.ConsolidationMigrator: + return interface.ConsolidationMigrator(CONSOLIDATION_MIGRATOR) + + +class TestConsolidationGateway: + def test_locator_wiring(self, gateway): + assert contracts.lido_locator.consolidationGateway() == gateway.address + + def test_immutables(self, gateway): + # constructor args (upgrade-params-mainnet.toml [consolidationGateway]) + assert gateway.GI_FIRST_VALIDATOR_PREV() == GI_FIRST_VALIDATOR + assert gateway.GI_FIRST_VALIDATOR_CURR() == GI_FIRST_VALIDATOR + assert gateway.PIVOT_SLOT() == 0 + + def test_limits(self, gateway): + ( + max_requests_limit, + consolidations_per_frame, + frame_duration_in_sec, + _prev_limit, + current_limit, + ) = gateway.getConsolidationRequestLimitFullInfo() + assert max_requests_limit == CONSOLIDATION_GATEWAY_MAX_REQUESTS_LIMIT + assert consolidations_per_frame == CONSOLIDATION_GATEWAY_CONSOLIDATIONS_PER_FRAME + assert frame_duration_in_sec == CONSOLIDATION_GATEWAY_FRAME_DURATION_IN_SEC + assert current_limit <= max_requests_limit + + def test_initial_state(self, gateway): + assert not gateway.isPaused() + + def test_roles(self, gateway): + """Mirrors UpgradeTemplate checks + item 1.18 (CircuitBreaker pauser).""" + pause_role = web3.keccak(text="PAUSE_ROLE") + resume_role = web3.keccak(text="RESUME_ROLE") + add_request_role = web3.keccak(text="ADD_CONSOLIDATION_REQUEST_ROLE") + exit_limit_manager_role = web3.keccak(text="EXIT_LIMIT_MANAGER_ROLE") + + # DEFAULT_ADMIN_ROLE: only the Agent (temporary admin renounced) + assert gateway.getRoleMemberCount(DEFAULT_ADMIN_ROLE) == 1 + assert gateway.getRoleMember(DEFAULT_ADMIN_ROLE, 0) == AGENT + + # PAUSE_ROLE: CircuitBreaker + ResealManager + assert gateway.getRoleMemberCount(pause_role) == 2 + assert { + gateway.getRoleMember(pause_role, 0), + gateway.getRoleMember(pause_role, 1), + } == {CIRCUIT_BREAKER, RESEAL_MANAGER} + + # RESUME_ROLE: only the ResealManager + assert gateway.getRoleMemberCount(resume_role) == 1 + assert gateway.getRoleMember(resume_role, 0) == RESEAL_MANAGER + + # ADD_CONSOLIDATION_REQUEST_ROLE: only the ConsolidationBus + assert gateway.getRoleMemberCount(add_request_role) == 1 + assert gateway.getRoleMember(add_request_role, 0) == CONSOLIDATION_BUS + + # EXIT_LIMIT_MANAGER_ROLE: not granted to anyone by the upgrade + assert gateway.getRoleMemberCount(exit_limit_manager_role) == 0 + + def test_acl(self, gateway, stranger): + # .call() — anvil does not surface custom-error data for reverted txs + # the main gated entry point (bus-only) + with reverts(unauthorized(stranger, "ADD_CONSOLIDATION_REQUEST_ROLE")): + gateway.addConsolidationRequests.call([], stranger, {"from": stranger}) + + # 1 sec: a zero duration would revert with ZeroPauseDuration before the ACL check + with reverts(unauthorized(stranger, "PAUSE_ROLE")): + gateway.pauseFor.call(1, {"from": stranger}) + + with reverts(unauthorized(stranger, "RESUME_ROLE")): + gateway.resume.call({"from": stranger}) + + # NB: EXIT_LIMIT_MANAGER_ROLE has no holders, so this reverts for anyone; + # kept as a smoke check that the method is not open + with reverts(unauthorized(stranger, "EXIT_LIMIT_MANAGER_ROLE")): + gateway.setConsolidationRequestLimit.call(1, 1, 1, {"from": stranger}) + + +class TestConsolidationBus: + def test_proxy(self, bus): + proxy = interface.OssifiableProxy(bus) + assert proxy.proxy__getImplementation() == CONSOLIDATION_BUS_IMPL + assert proxy.proxy__getAdmin() == AGENT + + def test_state(self, bus): + # immutable, points back to the gateway (checked by the template too) + assert bus.getConsolidationGateway() == CONSOLIDATION_GATEWAY + # initialize() params — upgrade-params-mainnet.toml [consolidationBus] + assert bus.batchSize() == CONSOLIDATION_BUS_BATCH_SIZE + assert bus.maxGroupsInBatch() == CONSOLIDATION_BUS_MAX_GROUPS_IN_BATCH + assert bus.executionDelay() == CONSOLIDATION_BUS_EXECUTION_DELAY + + def test_initialize(self, bus): + with reverts(encode_error("InvalidInitialization()")): + bus.initialize.call( + AGENT, + CONSOLIDATION_BUS_BATCH_SIZE, + CONSOLIDATION_BUS_MAX_GROUPS_IN_BATCH, + CONSOLIDATION_BUS_EXECUTION_DELAY, + {"from": contracts.voting}, + ) + + def test_petrified(self): + # the implementation calls _disableInitializers() in the constructor + impl = interface.ConsolidationBus(CONSOLIDATION_BUS_IMPL) + with reverts(encode_error("InvalidInitialization()")): + impl.initialize.call( + AGENT, + CONSOLIDATION_BUS_BATCH_SIZE, + CONSOLIDATION_BUS_MAX_GROUPS_IN_BATCH, + CONSOLIDATION_BUS_EXECUTION_DELAY, + {"from": contracts.voting}, + ) + + def test_roles(self, bus): + publish_role = web3.keccak(text="PUBLISH_ROLE") + remove_role = web3.keccak(text="REMOVE_ROLE") + manage_role = web3.keccak(text="MANAGE_ROLE") + + assert bus.getRoleMemberCount(DEFAULT_ADMIN_ROLE) == 1 + assert bus.getRoleMember(DEFAULT_ADMIN_ROLE, 0) == AGENT + + # PUBLISH_ROLE: only the ConsolidationMigrator + assert bus.getRoleMemberCount(publish_role) == 1 + assert bus.getRoleMember(publish_role, 0) == CONSOLIDATION_MIGRATOR + + # REMOVE_ROLE: only the CMC committee + assert bus.getRoleMemberCount(remove_role) == 1 + assert bus.getRoleMember(remove_role, 0) == CONSOLIDATION_COMMITTEE + + # MANAGE_ROLE: not granted to anyone by the upgrade + assert bus.getRoleMemberCount(manage_role) == 0 + + def test_acl(self, bus, stranger): + # the main gated entry point (PUBLISH_ROLE, migrator-only) + with reverts(unauthorized(stranger, "PUBLISH_ROLE")): + bus.addConsolidationRequests.call([], {"from": stranger}) + + with reverts(unauthorized(stranger, "REMOVE_ROLE")): + bus.removeBatches.call([], {"from": stranger}) + + # NB: MANAGE_ROLE has no holders, so these revert for anyone; + # kept as a smoke check that the setters are not open + with reverts(unauthorized(stranger, "MANAGE_ROLE")): + bus.setBatchSize.call(1, {"from": stranger}) + with reverts(unauthorized(stranger, "MANAGE_ROLE")): + bus.setMaxGroupsInBatch.call(1, {"from": stranger}) + with reverts(unauthorized(stranger, "MANAGE_ROLE")): + bus.setExecutionDelay.call(1, {"from": stranger}) + + +class TestConsolidationMigrator: + def test_proxy(self, migrator): + proxy = interface.OssifiableProxy(migrator) + assert proxy.proxy__getImplementation() == CONSOLIDATION_MIGRATOR_IMPL + assert proxy.proxy__getAdmin() == AGENT + + def test_state(self, migrator): + # immutables (constructor args) + assert migrator.getStakingRouter() == STAKING_ROUTER + assert migrator.getConsolidationBus() == CONSOLIDATION_BUS + assert migrator.sourceModuleId() == CONSOLIDATION_SOURCE_MODULE_ID + # the template checks targetModuleId == the freshly added CMv2 module id + assert migrator.targetModuleId() == CONSOLIDATION_TARGET_MODULE_ID + assert migrator.targetModuleId() == CURATED_V2_STAKING_MODULE_ID + + def test_initialize(self, migrator): + with reverts(encode_error("InvalidInitialization()")): + migrator.initialize.call(AGENT, {"from": contracts.voting}) + + def test_petrified(self): + impl = interface.ConsolidationMigrator(CONSOLIDATION_MIGRATOR_IMPL) + with reverts(encode_error("InvalidInitialization()")): + impl.initialize.call(AGENT, {"from": contracts.voting}) + + def test_roles(self, migrator): + allow_pair_role = web3.keccak(text="ALLOW_PAIR_ROLE") + disallow_pair_role = web3.keccak(text="DISALLOW_PAIR_ROLE") + + assert migrator.getRoleMemberCount(DEFAULT_ADMIN_ROLE) == 1 + assert migrator.getRoleMember(DEFAULT_ADMIN_ROLE, 0) == AGENT + + # ALLOW_PAIR_ROLE: only the EasyTrack EVMScript executor + # (pairs are allowed via the AllowConsolidationPair ET factory, vote item 5) + assert migrator.getRoleMemberCount(allow_pair_role) == 1 + assert migrator.getRoleMember(allow_pair_role, 0) == EASYTRACK_EVMSCRIPT_EXECUTOR + + # DISALLOW_PAIR_ROLE: only the CMC committee + assert migrator.getRoleMemberCount(disallow_pair_role) == 1 + assert migrator.getRoleMember(disallow_pair_role, 0) == CONSOLIDATION_COMMITTEE + + def test_acl(self, migrator, stranger): + # granted to the EasyTrack EVMScript executor only + with reverts(unauthorized(stranger, "ALLOW_PAIR_ROLE")): + migrator.allowPair.call(1, 1, stranger, {"from": stranger}) + + # granted to the CMC committee only + with reverts(unauthorized(stranger, "DISALLOW_PAIR_ROLE")): + migrator.disallowPair.call(1, 1, {"from": stranger}) diff --git a/tests/acceptance/test_csm.py b/tests/acceptance/test_csm.py index 15bc0703..e7cc2e78 100644 --- a/tests/acceptance/test_csm.py +++ b/tests/acceptance/test_csm.py @@ -27,8 +27,10 @@ CS_PARAMS_REGISTRY_ADDRESS, CS_EXIT_PENALTIES_ADDRESS, CS_STRIKES_ADDRESS, - CS_EJECTOR_ADDRESS + CS_EJECTOR_ADDRESS, + CS_FEE_ORACLE_CONSENSUS_VERSION, ) +from utils.evm_script import encode_error contracts: ContractsLazyLoader = contracts @@ -143,14 +145,13 @@ def test_initial_state(self, accounting): assert not accounting.isPaused() def test_allowances(self, lido): - uin256_max = 2 ** 256 - 1 + uin256_max = 2**256 - 1 assert lido.allowance(CS_ACCOUNTING_ADDRESS, WSTETH_TOKEN) == uin256_max 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 @@ -159,20 +160,29 @@ def test_initial_state(self, fee_distributor): 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.getContractVersion() == 3 # SRv3: finalizeUpgradeV3 -> INITIALIZED_VERSION assert fee_oracle.getConsensusContract() == CS_ORACLE_HASH_CONSENSUS_ADDRESS - assert fee_oracle.getConsensusVersion() == 3 + assert fee_oracle.getConsensusVersion() == CS_FEE_ORACLE_CONSENSUS_VERSION assert not fee_oracle.isPaused() + def test_finalize_upgrade_v3_reverts_when_already_finalized(self, fee_oracle): + # The vote already ran finalizeUpgradeV3, so the FeeOracle is at contract version 3. + # finalizeUpgradeV3 has no reinitializer/access-control guard; re-calling it must + # revert because _updateContractVersion(INITIALIZED_VERSION=3) rejects a bump when + # already at 3. Pass a different consensus version so we reach the contract-version + # check (the same version would revert earlier in _setConsensusVersion with + # VersionCannotBeSame). State rolls back on revert. + # .call() — anvil does not surface custom-error data for reverted txs. + with reverts(encode_error("InvalidContractVersionIncrement()")): + fee_oracle.finalizeUpgradeV3.call(CS_FEE_ORACLE_CONSENSUS_VERSION + 1, {"from": contracts.agent}) -class TestHashConsensus: +class TestHashConsensus: def test_initial_state(self, hash_consensus): chain_config = hash_consensus.getChainConfig() assert chain_config["slotsPerEpoch"] == CHAIN_SLOTS_PER_EPOCH @@ -207,7 +217,10 @@ def test_vetted_gate_state(vetted_gate): def test_ejector_state(ejector): assert ejector.MODULE() == CSM_ADDRESS assert ejector.STRIKES() == CS_STRIKES_ADDRESS - assert ejector.STAKING_MODULE_ID() == 3 + # v3: the immutable STAKING_MODULE_ID() getter is gone. stakingModuleId is now a mutable + # storage slot lazily filled from StakingRouter on the first ejection (_getOrCacheStakingModuleId), + # so right after enactment it is still 0 (will resolve to CS_MODULE_ID == 3 on first use). + assert ejector.stakingModuleId() == 0 def test_strikes_state(strikes): @@ -226,7 +239,10 @@ def test_exit_penalties_state(exit_penalties): def test_parameters_registry_state(parameters_registry): assert parameters_registry.QUEUE_LOWEST_PRIORITY() == 5 - assert parameters_registry.QUEUE_LEGACY_PRIORITY() == 4 + # v3: QUEUE_LEGACY_PRIORITY was removed (chore: remove legacy code). Queue priority is now + # per-curve via defaultQueueConfig (priority, maxDeposits). + priority, _max_deposits = parameters_registry.defaultQueueConfig() + assert priority <= parameters_registry.QUEUE_LOWEST_PRIORITY() def test_verifier_state(verifier): @@ -234,14 +250,30 @@ def test_verifier_state(verifier): assert verifier.MODULE() == CSM_ADDRESS assert verifier.SLOTS_PER_EPOCH() == CHAIN_SLOTS_PER_EPOCH - 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("0x0000000000000000000000000000000000000000000000000096000000000028", "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.GI_FIRST_WITHDRAWAL_PREV() == HexString( + "0x000000000000000000000000000000000000000000000000000000000161c004", "bytes" + ) + assert verifier.GI_FIRST_WITHDRAWAL_CURR() == HexString( + "0x000000000000000000000000000000000000000000000000000000000161c004", "bytes" + ) + assert verifier.GI_FIRST_VALIDATOR_PREV() == HexString( + "0x0000000000000000000000000000000000000000000000000096000000000028", "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() diff --git a/tests/acceptance/test_dsm.py b/tests/acceptance/test_dsm.py index 9cc514dd..9e9b8eb3 100644 --- a/tests/acceptance/test_dsm.py +++ b/tests/acceptance/test_dsm.py @@ -20,14 +20,16 @@ def dsm() -> interface.DepositSecurityModule: def test_owner(dsm): assert dsm.getOwner() == contracts.agent + def test_versioned(dsm): - assert dsm.VERSION() == 3 + assert dsm.VERSION() == 4 + def test_deposit_paused(dsm): assert dsm.isDepositsPaused() == False + def test_links(dsm): - assert dsm.LIDO() == contracts.lido assert dsm.STAKING_ROUTER() == contracts.staking_router assert dsm.DEPOSIT_CONTRACT() == CHAIN_DEPOSIT_CONTRACT diff --git a/tests/acceptance/test_lido.py b/tests/acceptance/test_lido.py index d348e902..2b744315 100644 --- a/tests/acceptance/test_lido.py +++ b/tests/acceptance/test_lido.py @@ -9,12 +9,14 @@ INITIAL_DEAD_TOKEN_HOLDER, LIDO_ARAGON_APP_ID, LIDO_MAX_STAKE_LIMIT_ETH, + LIDO_DEPOSITS_RESERVE_TARGET, ) last_seen_deposited_validators = 176018 last_seen_total_rewards_collected = 50327973200740183385860 last_seen_beacon_validators = 175906 + @pytest.fixture(scope="module") def contract() -> interface.Lido: return interface.Lido(LIDO) @@ -34,10 +36,7 @@ def test_role_keccaks(contract): assert contract.RESUME_ROLE() == web3.keccak(text="RESUME_ROLE").hex() assert contract.STAKING_PAUSE_ROLE() == web3.keccak(text="STAKING_PAUSE_ROLE").hex() assert contract.STAKING_CONTROL_ROLE() == web3.keccak(text="STAKING_CONTROL_ROLE").hex() - assert ( - contract.UNSAFE_CHANGE_DEPOSITED_VALIDATORS_ROLE() - == web3.keccak(text="UNSAFE_CHANGE_DEPOSITED_VALIDATORS_ROLE").hex() - ) + assert contract.BUFFER_RESERVE_MANAGER_ROLE() == web3.keccak(text="BUFFER_RESERVE_MANAGER_ROLE").hex() def test_pausable(contract): @@ -45,29 +44,49 @@ def test_pausable(contract): def test_versioned(contract): - assert contract.getContractVersion() == 3 + assert contract.getContractVersion() == 4 def test_initialize(contract): + # v4 signature: initialize(lidoLocator, eip712StETH, depositsReserveTarget) with reverts("INIT_ALREADY_INITIALIZED"): - contract.initialize(contracts.lido_locator, contracts.eip712_steth, {"from": contracts.voting}) + contract.initialize( + contracts.lido_locator, + contracts.eip712_steth, + LIDO_DEPOSITS_RESERVE_TARGET, + {"from": contracts.voting}, + ) def test_finalize_upgrade(contract): - with reverts("UNEXPECTED_CONTRACT_VERSION"): - contract.finalizeUpgrade_v3(contracts.burner, [contracts.eip712_steth], 0, {"from": contracts.voting}) + # Re-calling finalizeUpgrade_v4 reverts: NO_REPORT if the current oracle frame + # has no submitted report, UNEXPECTED_CONTRACT_VERSION otherwise. + main_data_submitted = contracts.accounting_oracle.getProcessingState()["mainDataSubmitted"] + expected_error = "UNEXPECTED_CONTRACT_VERSION" if main_data_submitted else "NO_REPORT" + with reverts(expected_error): + contract.finalizeUpgrade_v4(LIDO_DEPOSITS_RESERVE_TARGET, {"from": contracts.voting}) + + +def test_deposits_reserve_target(contract): + assert contract.getDepositsReserveTarget() == LIDO_DEPOSITS_RESERVE_TARGET def test_petrified(): impl = interface.Lido(LIDO_IMPL) + with reverts("INIT_ALREADY_INITIALIZED"): - impl.initialize(contracts.lido_locator, contracts.eip712_steth, {"from": contracts.voting}) + impl.initialize( + contracts.lido_locator, + contracts.eip712_steth, + LIDO_DEPOSITS_RESERVE_TARGET, + {"from": contracts.voting}, + ) # For petrified implementation, hasInitialized() returns false because # AragonApp (LIDO) sets initializationBlock to PETRIFIED_BLOCK = uint256(-1) # and hasInitialized() requires getBlockNumber() >= initializationBlock. with reverts("NOT_INITIALIZED"): - impl.finalizeUpgrade_v3(contracts.burner, [contracts.eip712_steth], 0, {"from": contracts.voting}) + impl.finalizeUpgrade_v4(LIDO_DEPOSITS_RESERVE_TARGET, {"from": contracts.voting}) def test_links(contract): @@ -90,10 +109,9 @@ def test_lido_state(contract): stake_limit = contract.getStakeLimitFullInfo() modules = contracts.staking_router.getStakingModules() - total_exited_validators = sum( - contracts.staking_router.getStakingModuleSummary(module[0])[0] - for module in modules - ) + module_summaries = [contracts.staking_router.getStakingModuleSummary(module[0]) for module in modules] + total_exited_validators = sum(s["totalExitedValidators"] for s in module_summaries) + total_deposited_validators = sum(s["totalDepositedValidators"] for s in module_summaries) assert stake_limit["isStakingPaused_"] == False assert stake_limit["isStakingLimitSet"] == True @@ -102,11 +120,32 @@ def test_lido_state(contract): assert contract.getBufferedEther() > 0 beacon_stat = contract.getBeaconStat() + # beaconValidators == depositedValidators + assert beacon_stat["depositedValidators"] == beacon_stat["beaconValidators"] assert beacon_stat["depositedValidators"] >= last_seen_deposited_validators - assert beacon_stat["beaconValidators"] >= last_seen_beacon_validators - # might break once enough exited validators registered - # they are not excluded from the 'beaconValidators' counter even though have zero balance - assert beacon_stat["beaconBalance"] >= 32 * 1e18 * (beacon_stat["beaconValidators"] - total_exited_validators), "no full withdrawals happened" - assert beacon_stat["depositedValidators"] >= beacon_stat["beaconValidators"] + + # counters cross-check: Lido's global deposited counter (seedDepositsCount after + # the v3->v4 storage migration) equals the sum of per-module counters in the SR + assert beacon_stat["depositedValidators"] == total_deposited_validators + # exited validators can never exceed ever-deposited + assert total_exited_validators <= beacon_stat["depositedValidators"] assert contract.getTotalELRewardsCollected() >= last_seen_total_rewards_collected + + +def test_balance_stats(contract): + ( + cl_validators_balance, + cl_pending_balance, + deposited_since_last_report, + deposited_for_current_report, + ) = contract.getBalanceStats() + + assert cl_validators_balance > 0 + + # getBeaconStat().beaconBalance is exactly active + pending + assert contract.getBeaconStat()["beaconBalance"] == cl_validators_balance + cl_pending_balance + + # deposits attributable to the current report are a subset of all deposits + # made since the last report + assert deposited_for_current_report <= deposited_since_last_report diff --git a/tests/acceptance/test_locator.py b/tests/acceptance/test_locator.py index b3961900..c1c4cc5f 100644 --- a/tests/acceptance/test_locator.py +++ b/tests/acceptance/test_locator.py @@ -29,6 +29,11 @@ def test_addresses(contract): assert contract.withdrawalQueue() == contracts.withdrawal_queue assert contract.withdrawalVault() == contracts.withdrawal_vault assert contract.oracleDaemonConfig() == contracts.oracle_daemon_config + # todo: add topUpGateway + assert contract.topUpGateway() == contracts.top_up_gateway + # todo: consolidation contracts + assert contract.consolidationGateway() == contracts.consolidation_gateway + assert contract.triggerableWithdrawalsGateway() == contracts.triggerable_withdrawals_gateway assert contract.coreComponents() == ( contracts.execution_layer_rewards_vault, diff --git a/tests/acceptance/test_node_operators_registry.py b/tests/acceptance/test_node_operators_registry.py index 1df8d75d..421e387c 100644 --- a/tests/acceptance/test_node_operators_registry.py +++ b/tests/acceptance/test_node_operators_registry.py @@ -14,14 +14,17 @@ CURATED_STAKING_MODULE_TYPE, ) + @pytest.fixture def voting(accounts): return accounts.at(contracts.voting.address, force=True) + @pytest.fixture(scope="module") def agent_eoa(accounts): return accounts.at(contracts.agent.address, force=True) + @pytest.fixture(scope="module") def contract() -> interface.NodeOperatorsRegistry: return interface.NodeOperatorsRegistry(NODE_OPERATORS_REGISTRY) @@ -41,10 +44,20 @@ def test_aragon(contract): def test_role_keccaks(contract): - assert contract.MANAGE_SIGNING_KEYS() == web3.keccak(text="MANAGE_SIGNING_KEYS").hex() - assert contract.SET_NODE_OPERATOR_LIMIT_ROLE() == web3.keccak(text="SET_NODE_OPERATOR_LIMIT_ROLE").hex() - assert contract.MANAGE_NODE_OPERATOR_ROLE() == web3.keccak(text="MANAGE_NODE_OPERATOR_ROLE").hex() - assert contract.STAKING_ROUTER_ROLE() == web3.keccak(text="STAKING_ROUTER_ROLE").hex() + assert ( + contract.MANAGE_SIGNING_KEYS() == web3.keccak(text="MANAGE_SIGNING_KEYS").hex() + ) + assert ( + contract.SET_NODE_OPERATOR_LIMIT_ROLE() + == web3.keccak(text="SET_NODE_OPERATOR_LIMIT_ROLE").hex() + ) + assert ( + contract.MANAGE_NODE_OPERATOR_ROLE() + == web3.keccak(text="MANAGE_NODE_OPERATOR_ROLE").hex() + ) + assert ( + contract.STAKING_ROUTER_ROLE() == web3.keccak(text="STAKING_ROUTER_ROLE").hex() + ) def test_versioned(contract): @@ -52,8 +65,9 @@ def test_versioned(contract): def test_initialize(contract): + # .call() — anvil does not surface revert strings for reverted txs (see test_staking_router) with reverts("INIT_ALREADY_INITIALIZED"): - contract.initialize( + contract.initialize.call( contracts.lido_locator, CURATED_STAKING_MODULE_TYPE, NOR_EXIT_DEADLINE_IN_SEC, @@ -63,7 +77,7 @@ def test_initialize(contract): def test_finalize_upgrade(contract): with reverts("UNEXPECTED_CONTRACT_VERSION"): - contract.finalizeUpgrade_v4( + contract.finalizeUpgrade_v4.call( NOR_EXIT_DEADLINE_IN_SEC, {"from": contracts.voting}, ) @@ -72,7 +86,7 @@ def test_finalize_upgrade(contract): def test_petrified(): contract = interface.NodeOperatorsRegistry(NODE_OPERATORS_REGISTRY_IMPL) with reverts("INIT_ALREADY_INITIALIZED"): - contract.initialize( + contract.initialize.call( contracts.lido_locator, CURATED_STAKING_MODULE_TYPE, NOR_EXIT_DEADLINE_IN_SEC, @@ -80,13 +94,18 @@ def test_petrified(): ) with reverts("CONTRACT_NOT_INITIALIZED"): - contract.finalizeUpgrade_v4(NOR_EXIT_DEADLINE_IN_SEC, {"from": contracts.voting}) + contract.finalizeUpgrade_v4.call( + NOR_EXIT_DEADLINE_IN_SEC, {"from": contracts.voting} + ) def test_nor_state(contract): node_operators_count = contract.getNodeOperatorsCount() assert node_operators_count == CURATED_STAKING_MODULE_OPERATORS_COUNT - assert contract.getActiveNodeOperatorsCount() == CURATED_STAKING_MODULE_OPERATORS_ACTIVE_COUNT + assert ( + contract.getActiveNodeOperatorsCount() + == CURATED_STAKING_MODULE_OPERATORS_ACTIVE_COUNT + ) assert contract.getNonce() >= 7315 assert contract.getStuckPenaltyDelay() == CURATED_STAKING_MODULE_STUCK_PENALTY_DELAY assert contract.getType() == _str_to_bytes32("curated-onchain-v1") @@ -99,7 +118,12 @@ def test_nor_state(contract): for id in range(node_operators_count): node_operator = contract.getNodeOperator(id, True) - deactivated_node_operators = [12, 1, 32, 3] # on vote 24-01-16, NO id 32 deactivated on vote 26-04-08, NO id 3 (Chorus One) deactivated on vote 26-06-17 + deactivated_node_operators = [ + 12, + 1, + 32, + 3, + ] # on vote 24-01-16, NO id 32 deactivated on vote 26-04-08, NO id 3 (Chorus One) deactivated on vote 26-06-17 assert node_operator["active"] == (id not in deactivated_node_operators) assert node_operator["name"] is not None @@ -109,14 +133,31 @@ def test_nor_state(contract): # Invariant check # https://github.com/lidofinance/lido-dao/blob/cadffa46a2b8ed6cfa1127fca2468bae1a82d6bf/contracts/0.4.24/nos/NodeOperatorsRegistry.sol#L168 assert node_operator["totalExitedValidators"] >= 0 - assert node_operator["totalExitedValidators"] <= node_operator["totalDepositedValidators"] - assert node_operator["totalDepositedValidators"] <= node_operator["totalVettedValidators"] - assert node_operator["totalVettedValidators"] <= node_operator["totalAddedValidators"] + assert ( + node_operator["totalExitedValidators"] + <= node_operator["totalDepositedValidators"] + ) + assert ( + node_operator["totalDepositedValidators"] + <= node_operator["totalVettedValidators"] + ) + assert ( + node_operator["totalVettedValidators"] + <= node_operator["totalAddedValidators"] + ) node_operator_summary = contract.getNodeOperatorSummary(id) - exited_node_operators = [12, 1] # NO id 12 was added on vote 23-05-23, NO id 1 was added on vote 23-10-03 - soft_limit_0_node_operators = [32, 3] # NO id 32 was added on vote 25-12-15, NO id 3 was added on vote 26-04-08 - assert node_operator_summary["targetLimitMode"] == (1 if id in exited_node_operators or id in soft_limit_0_node_operators else 0) + exited_node_operators = [ + 12, + 1, + ] # NO id 12 was added on vote 23-05-23, NO id 1 was added on vote 23-10-03 + soft_limit_0_node_operators = [ + 32, + 3, + ] # NO id 32 was added on vote 25-12-15, NO id 3 was added on vote 26-04-08 + assert node_operator_summary["targetLimitMode"] == ( + 1 if id in exited_node_operators or id in soft_limit_0_node_operators else 0 + ) assert node_operator_summary["targetValidatorsCount"] == 0 # Can be more than 0 in regular protocol operations # assert node_operator_summary["stuckValidatorsCount"] == 0 @@ -127,20 +168,34 @@ def test_nor_state(contract): # Invariant check # https://github.com/lidofinance/lido-dao/blob/cadffa46a2b8ed6cfa1127fca2468bae1a82d6bf/contracts/0.4.24/nos/NodeOperatorsRegistry.sol#L168 assert node_operator_summary["totalExitedValidators"] >= 0 - assert node_operator_summary["totalExitedValidators"] <= node_operator_summary["totalDepositedValidators"] + assert ( + node_operator_summary["totalExitedValidators"] + <= node_operator_summary["totalDepositedValidators"] + ) assert node_operator_summary["depositableValidatorsCount"] is not None - assert node_operator["totalExitedValidators"] == node_operator_summary["totalExitedValidators"] - assert node_operator["totalDepositedValidators"] == node_operator_summary["totalDepositedValidators"] + assert ( + node_operator["totalExitedValidators"] + == node_operator_summary["totalExitedValidators"] + ) + assert ( + node_operator["totalDepositedValidators"] + == node_operator_summary["totalDepositedValidators"] + ) if id in soft_limit_0_node_operators: assert node_operator_summary["depositableValidatorsCount"] == 0 else: no_depositable_validators_count = ( - node_operator["totalVettedValidators"] - node_operator["totalDepositedValidators"] + node_operator["totalVettedValidators"] + - node_operator["totalDepositedValidators"] + ) + assert ( + node_operator_summary["depositableValidatorsCount"] + == no_depositable_validators_count ) - assert node_operator_summary["depositableValidatorsCount"] == no_depositable_validators_count + def _str_to_bytes32(s: str) -> str: return "0x{:0<64}".format(s.encode("utf-8").hex()) diff --git a/tests/acceptance/test_oracle_report_sanity_checker.py b/tests/acceptance/test_oracle_report_sanity_checker.py index c9d5f2ce..80bcabdf 100644 --- a/tests/acceptance/test_oracle_report_sanity_checker.py +++ b/tests/acceptance/test_oracle_report_sanity_checker.py @@ -4,35 +4,64 @@ from utils.config import ( contracts, ORACLE_REPORT_SANITY_CHECKER, - EXITED_VALIDATORS_PER_DAY_LIMIT, - APPEARED_VALIDATORS_PER_DAY_LIMIT, + # EXITED_VALIDATORS_PER_DAY_LIMIT, + # APPEARED_VALIDATORS_PER_DAY_LIMIT, ANNUAL_BALANCE_INCREASE_BP_LIMIT, SIMULATED_SHARE_RATE_DEVIATION_BP_LIMIT, - MAX_VALIDATOR_EXIT_REQUESTS_PER_REPORT, + # MAX_VALIDATOR_EXIT_REQUESTS_PER_REPORT, MAX_ITEMS_PER_EXTRA_DATA_TRANSACTION, MAX_NODE_OPERATORS_PER_EXTRA_DATA_ITEM, REQUEST_TIMESTAMP_MARGIN, MAX_POSITIVE_TOKEN_REBASE, - INITIAL_SLASHING_AMOUNT_PWEI, - INACTIVITY_PENALTIES_AMOUNT_PWEI, - CL_BALANCE_ORACLES_ERROR_UPPER_BP_LIMIT + # INITIAL_SLASHING_AMOUNT_PWEI, + # INACTIVITY_PENALTIES_AMOUNT_PWEI, + CL_BALANCE_ORACLES_ERROR_UPPER_BP_LIMIT, + EXITED_ETH_AMOUNT_PER_DAY_LIMIT, + APPEARED_ETH_AMOUNT_PER_DAY_LIMIT, + MAX_BALANCE_EXIT_REQUESTED_PER_REPORT_IN_ETH, + MAX_EFFECTIVE_BALANCE_WEIGHT_WC_TYPE_01, + MAX_EFFECTIVE_BALANCE_WEIGHT_WC_TYPE_02, + MAX_CL_BALANCE_DECREASE_BP, + CONSOLIDATION_ETH_AMOUNT_PER_DAY_LIMIT, + EXITED_VALIDATOR_ETH_AMOUNT_LIMIT, + EXTERNAL_PENDING_BALANCE_CAP_ETH, ) from utils.test.helpers import ZERO_ADDRESS # Source of truth: https://hackmd.io/pdix1r4yR46fXUqiHaNKyw?view +# expected_report_limits = { +# "exitedValidatorsPerDayLimit": EXITED_VALIDATORS_PER_DAY_LIMIT, +# "appearedValidatorsPerDayLimit": APPEARED_VALIDATORS_PER_DAY_LIMIT, +# "annualBalanceIncreaseBPLimit": ANNUAL_BALANCE_INCREASE_BP_LIMIT, +# "simulatedShareRateDeviationBPLimit": SIMULATED_SHARE_RATE_DEVIATION_BP_LIMIT, +# "maxValidatorExitRequestsPerReport": MAX_VALIDATOR_EXIT_REQUESTS_PER_REPORT, +# "maxAccountingExtraDataListItemsCount": MAX_ITEMS_PER_EXTRA_DATA_TRANSACTION, +# "maxNodeOperatorsPerExtraDataItemCount": MAX_NODE_OPERATORS_PER_EXTRA_DATA_ITEM, +# "requestTimestampMargin": REQUEST_TIMESTAMP_MARGIN, +# "maxPositiveTokenRebase": MAX_POSITIVE_TOKEN_REBASE, +# "initialSlashingAmountPWei": INITIAL_SLASHING_AMOUNT_PWEI, +# "inactivityPenaltiesAmountPWei": INACTIVITY_PENALTIES_AMOUNT_PWEI, +# "clBalanceOraclesErrorUpperBPLimit": CL_BALANCE_ORACLES_ERROR_UPPER_BP_LIMIT, +# } + + expected_report_limits = { - "exitedValidatorsPerDayLimit": EXITED_VALIDATORS_PER_DAY_LIMIT, - "appearedValidatorsPerDayLimit": APPEARED_VALIDATORS_PER_DAY_LIMIT, + "exitedEthAmountPerDayLimit": EXITED_ETH_AMOUNT_PER_DAY_LIMIT, + "appearedEthAmountPerDayLimit": APPEARED_ETH_AMOUNT_PER_DAY_LIMIT, "annualBalanceIncreaseBPLimit": ANNUAL_BALANCE_INCREASE_BP_LIMIT, "simulatedShareRateDeviationBPLimit": SIMULATED_SHARE_RATE_DEVIATION_BP_LIMIT, - "maxValidatorExitRequestsPerReport": MAX_VALIDATOR_EXIT_REQUESTS_PER_REPORT, - "maxAccountingExtraDataListItemsCount": MAX_ITEMS_PER_EXTRA_DATA_TRANSACTION, - "maxNodeOperatorsPerExtraDataItemCount": MAX_NODE_OPERATORS_PER_EXTRA_DATA_ITEM, + "maxBalanceExitRequestedPerReportInEth": MAX_BALANCE_EXIT_REQUESTED_PER_REPORT_IN_ETH, + "maxEffectiveBalanceWeightWCType01": MAX_EFFECTIVE_BALANCE_WEIGHT_WC_TYPE_01, + "maxEffectiveBalanceWeightWCType02": MAX_EFFECTIVE_BALANCE_WEIGHT_WC_TYPE_02, + "maxItemsPerExtraDataTransaction": MAX_ITEMS_PER_EXTRA_DATA_TRANSACTION, + "maxNodeOperatorsPerExtraDataItem": MAX_NODE_OPERATORS_PER_EXTRA_DATA_ITEM, "requestTimestampMargin": REQUEST_TIMESTAMP_MARGIN, "maxPositiveTokenRebase": MAX_POSITIVE_TOKEN_REBASE, - "initialSlashingAmountPWei": INITIAL_SLASHING_AMOUNT_PWEI, - "inactivityPenaltiesAmountPWei": INACTIVITY_PENALTIES_AMOUNT_PWEI, + "maxCLBalanceDecreaseBP": MAX_CL_BALANCE_DECREASE_BP, "clBalanceOraclesErrorUpperBPLimit": CL_BALANCE_ORACLES_ERROR_UPPER_BP_LIMIT, + "consolidationEthAmountPerDayLimit": CONSOLIDATION_ETH_AMOUNT_PER_DAY_LIMIT, + "exitedValidatorEthAmountLimit": EXITED_VALIDATOR_ETH_AMOUNT_LIMIT, + "externalPendingBalanceCapEth": EXTERNAL_PENDING_BALANCE_CAP_ETH, } @@ -51,5 +80,6 @@ def test_limits(contract): assert dict(zip(expected_report_limits.keys(), limits)) == expected_report_limits + def test_second_opinion_is_empty(contract): assert contract.secondOpinionOracle() == ZERO_ADDRESS diff --git a/tests/acceptance/test_simple_dvt_module.py b/tests/acceptance/test_simple_dvt_module.py index a2a7e75a..236e8879 100644 --- a/tests/acceptance/test_simple_dvt_module.py +++ b/tests/acceptance/test_simple_dvt_module.py @@ -59,8 +59,9 @@ def test_versioned(contract): def test_initialize(contract): + # .call() — anvil does not surface revert strings for reverted txs (see test_staking_router) with reverts("INIT_ALREADY_INITIALIZED"): - contract.initialize( + contract.initialize.call( contracts.lido_locator, SIMPLE_DVT_MODULE_TYPE, NOR_EXIT_DEADLINE_IN_SEC, @@ -70,7 +71,7 @@ def test_initialize(contract): def test_finalize_upgrade(contract): with reverts("UNEXPECTED_CONTRACT_VERSION"): - contract.finalizeUpgrade_v4( + contract.finalizeUpgrade_v4.call( NOR_EXIT_DEADLINE_IN_SEC, {"from": contracts.voting}, ) @@ -79,7 +80,7 @@ def test_finalize_upgrade(contract): def test_petrified(): contract = interface.SimpleDVT(SIMPLE_DVT_IMPL) with reverts("INIT_ALREADY_INITIALIZED"): - contract.initialize( + contract.initialize.call( contracts.lido_locator, SIMPLE_DVT_MODULE_TYPE, NOR_EXIT_DEADLINE_IN_SEC, @@ -87,7 +88,7 @@ def test_petrified(): ) with reverts("CONTRACT_NOT_INITIALIZED"): - contract.finalizeUpgrade_v4( + contract.finalizeUpgrade_v4.call( NOR_EXIT_DEADLINE_IN_SEC, {"from": contracts.voting}, ) @@ -126,9 +127,7 @@ def test_simple_dvt_state(contract): node_operator_summary = contract.getNodeOperatorSummary(id) if id in exited_node_operators: - assert ( - node_operator_summary["targetLimitMode"] > 0 - ), f"targetLimitMode is 0 for exited node operator {id}" + assert node_operator_summary["targetLimitMode"] > 0, f"targetLimitMode is 0 for exited node operator {id}" assert node_operator_summary["depositableValidatorsCount"] == 0 @@ -164,9 +163,7 @@ def test_simple_dvt_permissions(contract): assert contracts.acl.getPermissionManager(contract.address, MANAGE_NODE_OPERATOR_ROLE) == contracts.agent.address assert contract.canPerform(EASYTRACK_EVMSCRIPT_EXECUTOR, MANAGE_NODE_OPERATOR_ROLE, []) - assert ( - contracts.acl.getPermissionManager(contract.address, SET_NODE_OPERATOR_LIMIT_ROLE) == contracts.agent.address - ) + assert contracts.acl.getPermissionManager(contract.address, SET_NODE_OPERATOR_LIMIT_ROLE) == contracts.agent.address assert contract.canPerform(EASYTRACK_EVMSCRIPT_EXECUTOR, SET_NODE_OPERATOR_LIMIT_ROLE, []) assert contracts.acl.getPermissionManager(contract.address, MANAGE_SIGNING_KEYS) == EASYTRACK_EVMSCRIPT_EXECUTOR diff --git a/tests/acceptance/test_staking_router.py b/tests/acceptance/test_staking_router.py index 9a5da1d5..d1212d34 100644 --- a/tests/acceptance/test_staking_router.py +++ b/tests/acceptance/test_staking_router.py @@ -2,15 +2,22 @@ from brownie import interface, reverts # type: ignore from configs.config_mainnet import ( - CS_MODULE_ID, CS_MODULE_MODULE_FEE_BP, - CS_MODULE_TREASURY_FEE_BP, CS_MODULE_TARGET_SHARE_BP, CS_MODULE_NAME, CS_MODULE_PRIORITY_EXIT_SHARE_THRESHOLD, - CS_MODULE_MAX_DEPOSITS_PER_BLOCK, CS_MODULE_MIN_DEPOSIT_BLOCK_DISTANCE, + CS_MODULE_ID, + CS_MODULE_MODULE_FEE_BP, + CS_MODULE_TREASURY_FEE_BP, + CS_MODULE_TARGET_SHARE_BP, + CS_MODULE_NAME, + CS_MODULE_PRIORITY_EXIT_SHARE_THRESHOLD, + CS_MODULE_MAX_DEPOSITS_PER_BLOCK, + CS_MODULE_MIN_DEPOSIT_BLOCK_DISTANCE, ) from utils.config import ( contracts, STAKING_ROUTER, STAKING_ROUTER_IMPL, STAKING_ROUTER_VERSION, + STAKING_ROUTER_MAX_TOP_UP_PER_BLOCK_GWEI, + LIDO_LOCATOR, CHAIN_DEPOSIT_CONTRACT, WITHDRAWAL_VAULT, SR_MODULES_FEE_BP, @@ -34,8 +41,16 @@ SIMPLE_DVT_MODULE_TREASURY_FEE_BP, SIMPLE_DVT_MODULE_PRIORITY_EXIT_SHARE_THRESHOLD, SIMPLE_DVT_MODULE_MAX_DEPOSITS_PER_BLOCK, - SIMPLE_DVT_MODULE_MIN_DEPOSITS_BLOCK_DISTANCE - + SIMPLE_DVT_MODULE_MIN_DEPOSITS_BLOCK_DISTANCE, + CURATED_V2_STAKING_MODULE_ID, + CURATED_V2_STAKING_MODULE_ADDRESS, + CURATED_V2_STAKING_MODULE_NAME, + CURATED_V2_STAKING_MODULE_TARGET_SHARE_BP, + CURATED_V2_STAKING_MODULE_MODULE_FEE_BP, + CURATED_V2_STAKING_MODULE_TREASURY_FEE_BP, + CURATED_V2_STAKING_MODULE_PRIORITY_EXIT_SHARE_THRESHOLD, + CURATED_V2_STAKING_MODULE_MAX_DEPOSITS_PER_BLOCK, + CURATED_V2_STAKING_MODULE_MIN_DEPOSITS_BLOCK_DISTANCE, ) from utils.evm_script import encode_error @@ -52,8 +67,15 @@ def test_proxy(contract): def test_links(contract): - assert contract.getLido() == contracts.lido assert contract.DEPOSIT_CONTRACT() == CHAIN_DEPOSIT_CONTRACT + assert contract.LIDO() == contracts.lido + assert contract.LIDO_LOCATOR() == contracts.lido_locator + assert contract.LIDO_LOCATOR() == LIDO_LOCATOR + + +def test_max_top_up_per_block(contract): + # Global per-block top-up cap set by finalizeUpgrade_v4 + assert contract.getMaxTopUpPerBlockGwei() == STAKING_ROUTER_MAX_TOP_UP_PER_BLOCK_GWEI def test_versioned(contract): @@ -61,30 +83,31 @@ def test_versioned(contract): def test_initialize(contract): - with reverts(encode_error("NonZeroContractVersionOnInit()")): - contract.initialize( + # NB: use .call() (eth_call) rather than a tx — anvil does not surface custom-error + # data for reverted transactions, so brownie's revert_msg would be None; eth_call does. + with reverts(encode_error("InvalidInitialization()")): + contract.initialize.call( contract.getRoleMember(contract.DEFAULT_ADMIN_ROLE(), 0), - contracts.lido, WITHDRAWAL_CREDENTIALS, + 0, {"from": contracts.voting}, ) + def test_finalize_upgrade(contract): - with reverts(encode_error( - "UnexpectedContractVersion(uint256,uint256)", - [3, 2], - )): - contract.finalizeUpgrade_v3( - {"from": contracts.voting}, - ) + # finalizeUpgrade_v4 is reinitializer(4); the upgrade already advanced _initialized to 4, + # so calling it again must revert. Use .call() (eth_call) — see test_initialize note. + with reverts(encode_error("InvalidInitialization()")): + contract.finalizeUpgrade_v4.call(0, {"from": contracts.voting}) + def test_petrified(contract): impl = interface.StakingRouter(STAKING_ROUTER_IMPL) - with reverts(encode_error("NonZeroContractVersionOnInit()")): - impl.initialize( + with reverts(encode_error("InvalidInitialization()")): + impl.initialize.call( contract.getRoleMember(contract.DEFAULT_ADMIN_ROLE(), 0), - contracts.lido, WITHDRAWAL_CREDENTIALS, + 0, {"from": contracts.voting}, ) @@ -97,9 +120,14 @@ def test_constants(contract): def test_staking_modules(contract): - assert contract.getStakingModulesCount() == 3 - - assert contract.getStakingModuleIds() == [CURATED_STAKING_MODULE_ID, SIMPLE_DVT_MODULE_ID, CS_MODULE_ID] + assert contract.getStakingModulesCount() == 4 + + assert contract.getStakingModuleIds() == [ + CURATED_STAKING_MODULE_ID, + SIMPLE_DVT_MODULE_ID, + CS_MODULE_ID, + CURATED_V2_STAKING_MODULE_ID, + ] assert contract.getStakingModuleIsActive(CURATED_STAKING_MODULE_ID) == True assert contract.getStakingModuleIsStopped(CURATED_STAKING_MODULE_ID) == False assert contract.getStakingModuleIsDepositsPaused(CURATED_STAKING_MODULE_ID) == False @@ -118,6 +146,12 @@ def test_staking_modules(contract): assert contract.getStakingModuleNonce(CS_MODULE_ID) >= 0 assert contract.getStakingModuleStatus(CS_MODULE_ID) == 0 + assert contract.getStakingModuleIsActive(CURATED_V2_STAKING_MODULE_ID) == True + assert contract.getStakingModuleIsStopped(CURATED_V2_STAKING_MODULE_ID) == False + assert contract.getStakingModuleIsDepositsPaused(CURATED_V2_STAKING_MODULE_ID) == False + assert contract.getStakingModuleNonce(CURATED_V2_STAKING_MODULE_ID) >= 0 + assert contract.getStakingModuleStatus(CURATED_V2_STAKING_MODULE_ID) == 0 + curated_module = contract.getStakingModule(CURATED_STAKING_MODULE_ID) assert curated_module["id"] == CURATED_STAKING_MODULE_ID assert curated_module["stakingModuleAddress"] == contracts.node_operators_registry @@ -163,6 +197,23 @@ def test_staking_modules(contract): assert community_staking_module["maxDepositsPerBlock"] == CS_MODULE_MAX_DEPOSITS_PER_BLOCK assert community_staking_module["minDepositBlockDistance"] == CS_MODULE_MIN_DEPOSIT_BLOCK_DISTANCE + curated_module_v2 = contract.getStakingModule(CURATED_V2_STAKING_MODULE_ID) + assert curated_module_v2["id"] == CURATED_V2_STAKING_MODULE_ID + assert curated_module_v2["stakingModuleAddress"] == CURATED_V2_STAKING_MODULE_ADDRESS + assert curated_module_v2["stakingModuleFee"] == CURATED_V2_STAKING_MODULE_MODULE_FEE_BP + assert curated_module_v2["treasuryFee"] == CURATED_V2_STAKING_MODULE_TREASURY_FEE_BP + assert curated_module_v2["stakeShareLimit"] == CURATED_V2_STAKING_MODULE_TARGET_SHARE_BP + assert curated_module_v2["status"] == 0 + assert curated_module_v2["name"] == CURATED_V2_STAKING_MODULE_NAME + # Module was just added during the upgrade: addStakingModule() calls _updateModuleLastDepositState, + # which sets lastDepositAt/lastDepositBlock to the enact block.timestamp/block.number; exited = 0. + assert curated_module_v2["lastDepositAt"] > 0 + assert curated_module_v2["lastDepositBlock"] > 0 + assert curated_module_v2["exitedValidatorsCount"] == 0 + assert curated_module_v2["priorityExitShareThreshold"] == CURATED_V2_STAKING_MODULE_PRIORITY_EXIT_SHARE_THRESHOLD + assert curated_module_v2["maxDepositsPerBlock"] == CURATED_V2_STAKING_MODULE_MAX_DEPOSITS_PER_BLOCK + assert curated_module_v2["minDepositBlockDistance"] == CURATED_V2_STAKING_MODULE_MIN_DEPOSITS_BLOCK_DISTANCE + fee_aggregate_distribution = contract.getStakingFeeAggregateDistribution() assert fee_aggregate_distribution["modulesFee"] <= SR_MODULES_FEE_E20 assert fee_aggregate_distribution["treasuryFee"] >= SR_TREASURY_FEE_E20 diff --git a/tests/acceptance/test_top_up_gateway.py b/tests/acceptance/test_top_up_gateway.py new file mode 100644 index 00000000..81bf1922 --- /dev/null +++ b/tests/acceptance/test_top_up_gateway.py @@ -0,0 +1,171 @@ +""" +Acceptance tests for TopUpGateway — a new contract added by the SRv3 upgrade +(deployed as an OssifiableProxy, wired into the upgraded LidoLocator). + +Vote impact: +- coreUpgrade deploys the proxy with the UpgradeTemporaryAdmin as initial admin; + initialize() sets the limits from upgrade-params-mainnet.toml [topUpGateway]; +- UpgradeTemporaryAdmin grants PAUSE_ROLE to the CircuitBreaker and ResealManager, + RESUME_ROLE to the ResealManager, TOP_UP_ROLE to the depositor, then hands + DEFAULT_ADMIN_ROLE over to the Agent (see UpgradeTemplate._assert* checks); +- the vote registers the CircuitBreaker pauser for the gateway (item 1.18-adjacent, + "Register CircuitBreaker pauser for TopUpGateway"). +""" +import pytest +from brownie import interface, reverts, web3 # type: ignore +from brownie.convert.datatypes import HexString + +from utils.config import ( + contracts, + AGENT, + CIRCUIT_BREAKER, + RESEAL_MANAGER, + CHAIN_SLOTS_PER_EPOCH, + TOP_UP_GATEWAY, + TOP_UP_GATEWAY_IMPL, + TOP_UP_GATEWAY_DEPOSITOR, + TOP_UP_GATEWAY_MAX_VALIDATORS_PER_TOP_UP, + TOP_UP_GATEWAY_MIN_BLOCK_DISTANCE, + TOP_UP_GATEWAY_MAX_ROOT_AGE, + TOP_UP_GATEWAY_TARGET_BALANCE_GWEI, + TOP_UP_GATEWAY_MIN_TOP_UP_GWEI, +) +from utils.evm_script import encode_error +from utils.test.helpers import access_control_unauthorized as unauthorized + +DEFAULT_ADMIN_ROLE = "0x" + "00" * 32 + +# An empty TopUpData tuple, field order per the ABI: +# (moduleId, keyIndices, operatorIds, validatorIndices, beaconRootData, validatorWitness, pendingBalanceGwei) +EMPTY_TOP_UP_DATA = (0, [], [], [], (0, 0, 0), [], []) + + +@pytest.fixture(scope="module") +def contract() -> interface.TopUpGateway: + return interface.TopUpGateway(TOP_UP_GATEWAY) + + +def test_proxy(contract): + proxy = interface.OssifiableProxy(contract) + assert proxy.proxy__getImplementation() == TOP_UP_GATEWAY_IMPL + assert proxy.proxy__getAdmin() == AGENT + + +def test_immutables(contract): + # constructor args (impl): locator, gIndices, pivot slot, slots per epoch + assert contract.SLOTS_PER_EPOCH() == CHAIN_SLOTS_PER_EPOCH + assert contract.PIVOT_SLOT() == 0 + assert contract.GI_FIRST_VALIDATOR_PREV() == HexString( + "0x0000000000000000000000000000000000000000000000000056000000000028", "bytes" + ) + assert contract.GI_FIRST_VALIDATOR_CURR() == HexString( + "0x0000000000000000000000000000000000000000000000000096000000000028", "bytes" + ) + + +def test_locator_wiring(contract): + assert contracts.lido_locator.topUpGateway() == contract.address + + +def test_initialize(contract): + # already initialized by the proxy constructor calldata + # .call() — anvil does not surface custom-error data for reverted txs + with reverts(encode_error("InvalidInitialization()")): + contract.initialize.call( + AGENT, + TOP_UP_GATEWAY_MAX_VALIDATORS_PER_TOP_UP, + TOP_UP_GATEWAY_MIN_BLOCK_DISTANCE, + TOP_UP_GATEWAY_MAX_ROOT_AGE, + TOP_UP_GATEWAY_TARGET_BALANCE_GWEI, + TOP_UP_GATEWAY_MIN_TOP_UP_GWEI, + {"from": contracts.voting}, + ) + + +def test_petrified(contract): + # the implementation calls _disableInitializers() in the constructor + impl = interface.TopUpGateway(TOP_UP_GATEWAY_IMPL) + with reverts(encode_error("InvalidInitialization()")): + impl.initialize.call( + AGENT, + TOP_UP_GATEWAY_MAX_VALIDATORS_PER_TOP_UP, + TOP_UP_GATEWAY_MIN_BLOCK_DISTANCE, + TOP_UP_GATEWAY_MAX_ROOT_AGE, + TOP_UP_GATEWAY_TARGET_BALANCE_GWEI, + TOP_UP_GATEWAY_MIN_TOP_UP_GWEI, + {"from": contracts.voting}, + ) + + +def test_limits(contract): + # values set by initialize() from upgrade-params-mainnet.toml [topUpGateway] + assert contract.getMaxValidatorsPerTopUp() == TOP_UP_GATEWAY_MAX_VALIDATORS_PER_TOP_UP + assert contract.getMinBlockDistance() == TOP_UP_GATEWAY_MIN_BLOCK_DISTANCE + assert contract.getMaxRootAge() == TOP_UP_GATEWAY_MAX_ROOT_AGE + assert contract.getTargetBalanceGwei() == TOP_UP_GATEWAY_TARGET_BALANCE_GWEI + assert contract.getMinTopUpGwei() == TOP_UP_GATEWAY_MIN_TOP_UP_GWEI + + +def test_initial_state(contract): + assert not contract.isPaused() + # no top-ups have happened yet + assert contract.getLastTopUpTimestamp() == 0 + assert contract.isBlockDistancePassed() + + +def test_roles(contract): + """Mirrors UpgradeTemplate post-upgrade checks (_assertSingleOZRoleHolder & co).""" + top_up_role = web3.keccak(text="TOP_UP_ROLE") + manage_limits_role = web3.keccak(text="MANAGE_LIMITS_ROLE") + pause_role = web3.keccak(text="PAUSE_ROLE") + resume_role = web3.keccak(text="RESUME_ROLE") + + # DEFAULT_ADMIN_ROLE: only the Agent (temporary admin renounced) + assert contract.getRoleMemberCount(DEFAULT_ADMIN_ROLE) == 1 + assert contract.getRoleMember(DEFAULT_ADMIN_ROLE, 0) == AGENT + + # PAUSE_ROLE: CircuitBreaker + ResealManager + assert contract.getRoleMemberCount(pause_role) == 2 + assert { + contract.getRoleMember(pause_role, 0), + contract.getRoleMember(pause_role, 1), + } == {CIRCUIT_BREAKER, RESEAL_MANAGER} + + # RESUME_ROLE: only the ResealManager + assert contract.getRoleMemberCount(resume_role) == 1 + assert contract.getRoleMember(resume_role, 0) == RESEAL_MANAGER + + # TOP_UP_ROLE: only the depositor + assert contract.getRoleMemberCount(top_up_role) == 1 + assert contract.getRoleMember(top_up_role, 0) == TOP_UP_GATEWAY_DEPOSITOR + + # MANAGE_LIMITS_ROLE: not granted to anyone by the upgrade + assert contract.getRoleMemberCount(manage_limits_role) == 0 + + +def test_acl(contract, stranger): + # .call() — anvil does not surface custom-error data for reverted txs + # the main gated entry point (TOP_UP_ROLE, depositor-only) + with reverts(unauthorized(stranger, "TOP_UP_ROLE")): + contract.topUp.call(EMPTY_TOP_UP_DATA, {"from": stranger}) + + # NB: MANAGE_LIMITS_ROLE has no holders, so these revert for anyone; + # kept as a smoke check that the setters are not open + with reverts(unauthorized(stranger, "MANAGE_LIMITS_ROLE")): + contract.setMaxValidatorsPerTopUp.call(1, {"from": stranger}) + + with reverts(unauthorized(stranger, "MANAGE_LIMITS_ROLE")): + contract.setMinBlockDistance.call(1, {"from": stranger}) + + with reverts(unauthorized(stranger, "MANAGE_LIMITS_ROLE")): + contract.setTopUpBalanceLimits.call(1, 1, {"from": stranger}) + + with reverts(unauthorized(stranger, "MANAGE_LIMITS_ROLE")): + contract.setMaxRootAge.call(1, {"from": stranger}) + + # 1 sec: a zero duration would revert with ZeroPauseDuration instead + with reverts(unauthorized(stranger, "PAUSE_ROLE")): + contract.pauseFor.call(1, {"from": stranger}) + + with reverts(unauthorized(stranger, "RESUME_ROLE")): + contract.resume.call({"from": stranger}) diff --git a/tests/acceptance/test_veb_negative.py b/tests/acceptance/test_veb_negative.py index c690d36d..df9e72c6 100644 --- a/tests/acceptance/test_veb_negative.py +++ b/tests/acceptance/test_veb_negative.py @@ -44,14 +44,19 @@ def test_submit_report_data_checks(contract, ref_slot, stranger): ) with reverts(encode_error("SenderNotAllowed()")): - contract.submitReportData(report, contract_version, {"from": stranger}) + contract.submitReportData.call(report, contract_version, {"from": stranger}) - with reverts(encode_error("UnexpectedContractVersion(uint256,uint256)", (contract_version, contract_version + 1))): - contract.submitReportData(report, contract_version + 1, {"from": submitter}) + with reverts( + encode_error( + "UnexpectedContractVersion(uint256,uint256)", + (contract_version, contract_version + 1), + ) + ): + contract.submitReportData.call(report, contract_version + 1, {"from": submitter}) with reverts(encode_error("UnexpectedRefSlot(uint256,uint256)", (ref_slot, ref_slot - 1))): wrong_report = (report[0], ref_slot - 1, report[2], report[3], report[4]) - contract.submitReportData(wrong_report, contract_version, {"from": submitter}) + contract.submitReportData.call(wrong_report, contract_version, {"from": submitter}) with reverts( encode_error( @@ -59,10 +64,16 @@ def test_submit_report_data_checks(contract, ref_slot, stranger): (consensus_version, consensus_version + 1), ) ): - wrong_report = (consensus_version + 1, report[1], report[2], report[3], report[4]) - contract.submitReportData(wrong_report, contract_version, {"from": submitter}) + wrong_report = ( + consensus_version + 1, + report[1], + report[2], + report[3], + report[4], + ) + contract.submitReportData.call(wrong_report, contract_version, {"from": submitter}) - with reverts(): # encode_error("UnexpectedDataHash(bytes32,bytes32)",(report_hash, report_hash)) + with (reverts()): # encode_error("UnexpectedDataHash(bytes32,bytes32)",(report_hash, report_hash)) wrong_report = ( report[0], report[1], @@ -70,7 +81,7 @@ def test_submit_report_data_checks(contract, ref_slot, stranger): report[3], HexBytes(42).hex(), ) - contract.submitReportData(wrong_report, contract_version, {"from": submitter}) + contract.submitReportData.call(wrong_report, contract_version, {"from": submitter}) def test_submit_report_data_processing(contract, ref_slot): @@ -89,14 +100,15 @@ def test_submit_report_data_processing(contract, ref_slot): contract.submitReportData(report, contract_version, {"from": submitter}) with reverts(encode_error("RefSlotAlreadyProcessing()")): - contract.submitReportData(report, contract_version, {"from": submitter}) + contract.submitReportData.call(report, contract_version, {"from": submitter}) def test_handle_consensus_report_data_wrong_format(contract, ref_slot): no_global_index = (_, no_id) = (1, 1) - validator_id = 1 - validator_key = contracts.node_operators_registry.getSigningKey(no_id, validator_id)[0] - validator = LidoValidator(validator_id, validator_key) + validator_index = 1 # mock value + key_index = 1 + validator_key = contracts.node_operators_registry.getSigningKey(no_id, key_index)[0] + validator = LidoValidator(validator_index, validator_key, key_index) contract_version = contract.getContractVersion() consensus_version = contract.getConsensusVersion() @@ -119,14 +131,15 @@ def test_handle_consensus_report_data_wrong_format(contract, ref_slot): ) with reverts(encode_error("UnsupportedRequestsDataFormat(uint256)", [data_format + 1])): - contract.submitReportData(report, contract_version, {"from": submitter}) + contract.submitReportData.call(report, contract_version, {"from": submitter}) def test_handle_consensus_report_data_wrong_data_length(contract, ref_slot): no_global_index = (_, no_id) = (1, 1) - validator_id = 1 - validator_key = contracts.node_operators_registry.getSigningKey(no_id, validator_id)[0] - validator = LidoValidator(validator_id, validator_key) + validator_index = 1 # mock value + key_index = 1 + validator_key = contracts.node_operators_registry.getSigningKey(no_id, key_index)[0] + validator = LidoValidator(validator_index, validator_key, key_index) contract_version = contract.getContractVersion() consensus_version = contract.getConsensusVersion() @@ -149,23 +162,25 @@ def test_handle_consensus_report_data_wrong_data_length(contract, ref_slot): ) with reverts(encode_error("InvalidRequestsDataLength()")): - contract.submitReportData(report, contract_version, {"from": submitter}) + contract.submitReportData.call(report, contract_version, {"from": submitter}) def test_handle_consensus_report_data_wrong_request_length(contract, ref_slot): no_global_index = (_, no_id) = (1, 1) - validator_id = 1 - validator_key = contracts.node_operators_registry.getSigningKey(no_id, validator_id)[0] - validator = LidoValidator(validator_id, validator_key) + validator_index = 1 # mock value + key_index = 1 + validator_key = contracts.node_operators_registry.getSigningKey(no_id, key_index)[0] + validator = LidoValidator(validator_index, validator_key, key_index) contract_version = contract.getContractVersion() consensus_version = contract.getConsensusVersion() data, data_format = encode_data([(no_global_index, validator)]) + requests_count = 0 # deliberately mismatched: data actually holds 1 request report = ( consensus_version, ref_slot, - 0, + requests_count, data_format, data, ) @@ -179,14 +194,15 @@ def test_handle_consensus_report_data_wrong_request_length(contract, ref_slot): ) with reverts(encode_error("UnexpectedRequestsDataLength()")): - contract.submitReportData(report, contract_version, {"from": submitter}) + contract.submitReportData.call(report, contract_version, {"from": submitter}) def test_handle_consensus_report_data_wrong_module_id(contract, ref_slot): no_global_index = (_, no_id) = (0, 1) - validator_id = 1 - validator_key = contracts.node_operators_registry.getSigningKey(no_id, validator_id)[0] - validator = LidoValidator(validator_id, validator_key) + validator_index = 1 # mock value + key_index = 1 + validator_key = contracts.node_operators_registry.getSigningKey(no_id, key_index)[0] + validator = LidoValidator(validator_index, validator_key, key_index) contract_version = contract.getContractVersion() consensus_version = contract.getConsensusVersion() @@ -209,7 +225,7 @@ def test_handle_consensus_report_data_wrong_module_id(contract, ref_slot): ) with reverts(encode_error("InvalidModuleId()")): - contract.submitReportData(report, contract_version, {"from": submitter}) + contract.submitReportData.call(report, contract_version, {"from": submitter}) def test_handle_consensus_report_data_invalid_request_order(contract, ref_slot): @@ -219,8 +235,10 @@ def test_handle_consensus_report_data_invalid_request_order(contract, ref_slot): validator_2_key = contracts.node_operators_registry.getSigningKey(no_id, 2)[0] # set validator index to the next one to avoid NodeOpValidatorIndexMustIncrease error - validator = LidoValidator(index=unreachable_cl_validator_index, pubkey=validator_key) - validator_2 = LidoValidator(index=unreachable_cl_validator_index + 1, pubkey=validator_2_key) + validator = LidoValidator(index=unreachable_cl_validator_index, pubkey=validator_key, key_index=1) + validator_2 = LidoValidator(index=unreachable_cl_validator_index + 1, pubkey=validator_2_key, key_index=2) + + request_count = 2 contract_version = contract.getContractVersion() consensus_version = contract.getConsensusVersion() @@ -229,7 +247,7 @@ def test_handle_consensus_report_data_invalid_request_order(contract, ref_slot): report = ( consensus_version, ref_slot, - 2, + request_count, data_format, data, ) @@ -243,4 +261,4 @@ def test_handle_consensus_report_data_invalid_request_order(contract, ref_slot): ) with reverts(encode_error("InvalidRequestsDataSortOrder()")): - contract.submitReportData(report, contract_version, {"from": submitter}) + contract.submitReportData.call(report, contract_version, {"from": submitter}) diff --git a/tests/acceptance/test_veb_oracle.py b/tests/acceptance/test_veb_oracle.py index ced8dfaa..17ea5712 100644 --- a/tests/acceptance/test_veb_oracle.py +++ b/tests/acceptance/test_veb_oracle.py @@ -19,6 +19,8 @@ EXITS_PER_FRAME, FRAME_DURATION_IN_SEC, VEBO_CONSENSUS_VERSION, + VEBO_MAX_EXIT_BALANCE_ETH, + VEBO_BALANCE_PER_FRAME_ETH, ) from utils.evm_script import encode_error @@ -42,12 +44,12 @@ def test_immutables(contract): def test_versioned(contract): - assert contract.getContractVersion() == 2 + assert contract.getContractVersion() == 3 # SRv3: finalizeUpgrade_v3 def test_initialize(contract): with reverts(encode_error("NonZeroContractVersionOnInit()")): - contract.initialize( + contract.initialize.call( contract.getRoleMember(contract.DEFAULT_ADMIN_ROLE(), 0), HASH_CONSENSUS_FOR_AO, 1, @@ -63,7 +65,7 @@ def test_initialize(contract): def test_petrified(contract): impl = interface.ValidatorsExitBusOracle(VALIDATORS_EXIT_BUS_ORACLE_IMPL) with reverts(encode_error("NonZeroContractVersionOnInit()")): - impl.initialize( + impl.initialize.call( contract.getRoleMember(contract.DEFAULT_ADMIN_ROLE(), 0), HASH_CONSENSUS_FOR_AO, 1, @@ -81,6 +83,23 @@ def test_consensus(contract): assert contract.getConsensusContract() == HASH_CONSENSUS_FOR_VEBO +def test_finalize_upgrade_v3(contract): + # Values set by finalizeUpgrade_v3 (upgrade-params-mainnet.toml [validatorsExitBusOracle]). + # Version (3) and consensus version are covered by test_versioned / test_consensus. + assert contract.getMaxValidatorsPerReport() == MAX_VALIDATORS_PER_REPORT + + ( + max_exit_balance_eth, + balance_per_frame_eth, + frame_duration_in_sec, + _prev_exit_balance_eth, + _current_exit_balance_eth, + ) = contract.getExitRequestLimitFullInfo() + assert max_exit_balance_eth == VEBO_MAX_EXIT_BALANCE_ETH + assert balance_per_frame_eth == VEBO_BALANCE_PER_FRAME_ETH + assert frame_duration_in_sec == FRAME_DURATION_IN_SEC + + def test_vebo_hash_consensus_synced_with_accounting_one(contract): consensus = interface.HashConsensus(contract.getConsensusContract()) frameConfig = consensus.getFrameConfig() diff --git a/tests/acceptance/test_withdrawal_queue.py b/tests/acceptance/test_withdrawal_queue.py index f41bf852..3ade708b 100644 --- a/tests/acceptance/test_withdrawal_queue.py +++ b/tests/acceptance/test_withdrawal_queue.py @@ -11,6 +11,7 @@ ) from utils.evm_script import encode_error + @pytest.fixture(scope="module") def contract() -> interface.WithdrawalQueueERC721: return interface.WithdrawalQueueERC721(WITHDRAWAL_QUEUE) @@ -28,13 +29,19 @@ def test_versioned(contract): def test_initialize(contract): with reverts(encode_error("NonZeroContractVersionOnInit()")): - contract.initialize(contract.getRoleMember(contract.DEFAULT_ADMIN_ROLE(), 0), {"from": contracts.voting}) + contract.initialize.call( + contract.getRoleMember(contract.DEFAULT_ADMIN_ROLE(), 0), + {"from": contracts.voting}, + ) def test_petrified(contract): impl = interface.WithdrawalQueueERC721(WITHDRAWAL_QUEUE_IMPL) with reverts(encode_error("NonZeroContractVersionOnInit()")): - impl.initialize(contract.getRoleMember(contract.DEFAULT_ADMIN_ROLE(), 0), {"from": contracts.voting}) + impl.initialize.call( + contract.getRoleMember(contract.DEFAULT_ADMIN_ROLE(), 0), + {"from": contracts.voting}, + ) def test_pausable_until(contract): diff --git a/tests/acceptance/test_withdrawal_vault.py b/tests/acceptance/test_withdrawal_vault.py index 8e6bb120..b668b388 100644 --- a/tests/acceptance/test_withdrawal_vault.py +++ b/tests/acceptance/test_withdrawal_vault.py @@ -17,19 +17,27 @@ def test_proxy(contract): def test_versioned(contract): - assert contract.getContractVersion() == 2 + assert contract.getContractVersion() == 3 # SRv3: finalizeUpgrade_v3 def test_initialize(contract): - with reverts(encode_error("UnexpectedContractVersion(uint256,uint256)", (2, 0))): - contract.initialize({"from": contracts.voting}) + # initialize() does _checkContractVersion(0); post-upgrade version is 3 -> reverts (3, 0). + # .call() — anvil does not surface custom-error data for reverted txs. + with reverts(encode_error("UnexpectedContractVersion(uint256,uint256)", (3, 0))): + contract.initialize.call({"from": contracts.voting}) + + +def test_finalize_upgrade_v3(contract): + # finalizeUpgrade_v3 does _checkContractVersion(2); already at 3 -> reverts (3, 2). + with reverts(encode_error("UnexpectedContractVersion(uint256,uint256)", (3, 2))): + contract.finalizeUpgrade_v3.call({"from": contracts.voting}) def test_petrified(): dummy_version = 115792089237316195423570985008687907853269984665640564039457584007913129639935 impl = interface.WithdrawalVault(WITHDRAWAL_VAULT_IMPL) with reverts(encode_error("UnexpectedContractVersion(uint256,uint256)", (dummy_version, 0))): - impl.initialize({"from": contracts.voting}) + impl.initialize.call({"from": contracts.voting}) def test_withdrawals_vault(contract): diff --git a/tests/acceptance/test_withdrawals_negative.py b/tests/acceptance/test_withdrawals_negative.py index 6d5e368f..88657d09 100644 --- a/tests/acceptance/test_withdrawals_negative.py +++ b/tests/acceptance/test_withdrawals_negative.py @@ -4,12 +4,16 @@ from utils.config import WITHDRAWAL_QUEUE, contracts from utils.evm_script import encode_error -from utils.test.oracle_report_helpers import oracle_report, wait_to_next_available_report_time +from utils.test.oracle_report_helpers import ( + oracle_report, + wait_to_next_available_report_time, +) MIN_STETH_WITHDRAWAL_AMOUNT = Wei(100) MAX_STETH_WITHDRAWAL_AMOUNT = Wei(1000 * 10**18) UINT256_MAX = 2**256 - 1 + def test_request_withdrawals_steth(wq: Contract, steth_whale: Account): too_small_amount = MIN_STETH_WITHDRAWAL_AMOUNT - 10 too_large_amount = MAX_STETH_WITHDRAWAL_AMOUNT + 10 @@ -21,7 +25,7 @@ def test_request_withdrawals_steth(wq: Contract, steth_whale: Account): [too_small_amount], ) ): - wq.requestWithdrawals( + wq.requestWithdrawals.call( [ normal_amount, too_small_amount, @@ -36,7 +40,7 @@ def test_request_withdrawals_steth(wq: Contract, steth_whale: Account): [too_large_amount], ) ): - wq.requestWithdrawals( + wq.requestWithdrawals.call( [ normal_amount, too_large_amount, @@ -57,7 +61,7 @@ def test_request_withdrawals_wsteth(wq: Contract, wsteth_whale: Account): [wsteth_to_steth(too_small_amount)], ) ): - wq.requestWithdrawalsWstETH( + wq.requestWithdrawalsWstETH.call( [ normal_amount, too_small_amount, @@ -72,7 +76,7 @@ def test_request_withdrawals_wsteth(wq: Contract, wsteth_whale: Account): [wsteth_to_steth(too_large_amount)], ) ): - wq.requestWithdrawalsWstETH( + wq.requestWithdrawalsWstETH.call( [ normal_amount, too_large_amount, @@ -100,7 +104,11 @@ def test_wq_prefinalize(wq: Contract, steth_whale: Account): with reverts(encode_error("ZeroShareRate()")): oracle_report( - withdrawalFinalizationBatches=[last_finalized_id + 1, last_finalized_id + 2], simulatedShareRate=0 + withdrawalFinalizationBatches=[ + last_finalized_id + 1, + last_finalized_id + 2, + ], + simulatedShareRate=0, ) diff --git a/utils/config.py b/utils/config.py index 42e03e72..9c004697 100644 --- a/utils/config.py +++ b/utils/config.py @@ -25,19 +25,19 @@ def network_name() -> Optional[str]: if network_name() in ("goerli", "goerli-fork"): - print(f'Using {color("cyan")}config_goerli.py{color} addresses') + print(f"Using {color('cyan')}config_goerli.py{color} addresses") from configs.config_goerli import * elif network_name() in ("holesky", "holesky-fork"): - print(f'Using {color("cyan")}config_holesky.py{color} addresses') + print(f"Using {color('cyan')}config_holesky.py{color} addresses") from configs.config_holesky import * elif network_name() in ("sepolia", "sepolia-fork"): - print(f'Using {color("yellow")}config_sepolia.py{color} addresses') + print(f"Using {color('yellow')}config_sepolia.py{color} addresses") from configs.config_sepolia import * elif network_name() in ("hoodi", "hoodi-fork"): - print(f'Using {color("cyan")}config_hoodi.py{color} addresses') + print(f"Using {color('cyan')}config_hoodi.py{color} addresses") from configs.config_hoodi import * else: - print(f'Using {color("magenta")}config_mainnet.py{color} addresses') + print(f"Using {color('magenta')}config_mainnet.py{color} addresses") from configs.config_mainnet import * @@ -479,8 +479,12 @@ def emergency_governance(self) -> interface.EmergencyGovernance: return interface.EmergencyGovernance(DAO_EMERGENCY_GOVERNANCE) @property - def triggerable_withdrawals_gateway(self) -> interface.TriggerableWithdrawalsGateway: - return interface.TriggerableWithdrawalsGateway(TRIGGERABLE_WITHDRAWALS_GATEWAY) + def top_up_gateway(self) -> interface.TopUpGateway: + return interface.TopUpGateway(TOP_UP_GATEWAY) + + @property + def consolidation_gateway(self) -> interface.ConsolidationGateway: + return interface.ConsolidationGateway(CONSOLIDATION_GATEWAY) def __getattr__(name: str) -> Any: diff --git a/utils/dual_governance.py b/utils/dual_governance.py index c4e02f93..b328ea82 100644 --- a/utils/dual_governance.py +++ b/utils/dual_governance.py @@ -1,6 +1,8 @@ -from brownie import accounts, chain +from brownie import accounts, chain, web3 from typing import Tuple, Sequence +from eth_abi.abi import encode + from utils.config import contracts from tests.conftest import get_active_proposals_from_env @@ -41,9 +43,7 @@ def submit_proposals(items: Sequence[Tuple[Sequence[Tuple[str, str]], str]]) -> proposal_list.append( ( contracts.dual_governance.address, - contracts.dual_governance.submitProposal.encode_input( - proposal_calldata, description - ), + contracts.dual_governance.submitProposal.encode_input(proposal_calldata, description), ) ) return proposal_list @@ -90,13 +90,105 @@ def process_proposals(proposal_ids: Sequence[int]): chain.sleep(after_schedule_delay + 1) wait_for_target_time_to_satisfy_time_constrains() + # The SRv3/CMv2 upgrade calls Lido.finalizeUpgrade_v4, which reverts with "NO_REPORT" + # unless the current AccountingOracle frame already has a submitted main report. + # The DG submit/schedule delays above advance time by ~4 days, rolling the oracle frame + # over and invalidating any prior report. On real mainnet a fresh daily report naturally + # exists by execution time; on a fork we reproduce that by pushing one right before execute. + # The report goes through the OLD (pre-upgrade, v4) oracle, so it is built in the legacy + # v4 format, self-contained below. Once the AO is at v5+ (the upgrade is already enacted + # on the forked chain / future votes), no report is needed at all. + # Test/fork-only scaffolding for this specific vote: delete together with archiving + # scripts/upgrade_2026_04_30_srv3_cmv2.py. + if contracts.accounting_oracle.getContractVersion() < 5: + # Mine a block first so the latest block timestamp absorbs the accumulated + # chain.sleep offset from the DG delays above; otherwise the frame math (which + # mixes a pending-state getCurrentFrame() with the latest mined block time) + # overshoots the frame. + chain.mine(1) + _push_legacy_v4_oracle_report() + for proposal_id in scheduled_proposals: contracts.emergency_protected_timelock.execute(proposal_id, {"from": stranger}) (_, _, _, _, proposal_status) = contracts.emergency_protected_timelock.getProposalDetails(proposal_id) assert proposal_status == PROPOSAL_STATUS["executed"], f"Proposal {proposal_id} execution failed" if len(proposals_to_be_processed): - raise Exception(f"Unable to process proposals: {proposals_to_be_processed}. Proposals are already processed or cancelled.") + raise Exception( + f"Unable to process proposals: {proposals_to_be_processed}. Proposals are already processed or cancelled." + ) + + +# Legacy (pre-SRv3) AccountingOracle ReportData tuple — 17 fields, v4 layout with +# numValidators/clBalanceGwei. Hardcoded on purpose: interfaces/AccountingOracle.json +# holds the v5 ABI, while this report targets the OLD implementation before the vote +# is executed. Self-contained so the main oracle helpers can stay v5-only. +# Delete together with archiving scripts/upgrade_2026_04_30_srv3_cmv2.py. +_LEGACY_V4_REPORT_ABI = ( + "(uint256,uint256,uint256,uint256,uint256[],uint256[],uint256,uint256,uint256," + "uint256[],uint256,bool,bytes32,string,uint256,bytes32,uint256)" +) + + +def _push_legacy_v4_oracle_report(): + """Push a minimal v4-format accounting report so the current frame has + mainDataSubmitted == true (required by Lido.finalizeUpgrade_v4). No withdrawal + finalization, no extra data — just enough for the NO_REPORT check to pass.""" + from utils.test.helpers import eth_balance + from utils.test.oracle_report_helpers import ( + ZERO_BYTES32, + MOCK_VAULTS_DATA_TREE_ROOT, + MOCK_VAULTS_DATA_TREE_CID, + reach_consensus, + wait_to_next_available_report_time, + ) + + consensus = contracts.hash_consensus_for_accounting_oracle + oracle = contracts.accounting_oracle + + wait_to_next_available_report_time(consensus) + (ref_slot, _) = consensus.getCurrentFrame() + + # version getters are identical in the v4 and v5 ABIs — safe via the interface + contract_version = oracle.getContractVersion() + consensus_version = oracle.getConsensusVersion() + (_, beacon_validators, beacon_balance) = contracts.lido.getBeaconStat() + (cover_shares, non_cover_shares) = contracts.burner.getSharesRequestedToBurn() + + report = ( + int(consensus_version), + int(ref_slot), + int(beacon_validators), + int(beacon_balance) // 10**9, # clBalanceGwei + [], # stakingModuleIdsWithNewlyExitedValidators + [], # numExitedValidatorsByStakingModule + int(eth_balance(contracts.withdrawal_vault.address)), + int(eth_balance(contracts.execution_layer_rewards_vault.address)), + int(cover_shares + non_cover_shares), + [], # withdrawalFinalizationBatches (skip withdrawals) + 0, # simulatedShareRate (unchecked when batches are empty) + False, # isBunkerMode + bytes(MOCK_VAULTS_DATA_TREE_ROOT), + MOCK_VAULTS_DATA_TREE_CID, + 0, # extraDataFormat: EXTRA_DATA_FORMAT_EMPTY + bytes(ZERO_BYTES32), + 0, # extraDataItemsCount + ) + + encoded_report = encode([_LEGACY_V4_REPORT_ABI], [report]) + report_hash = web3.keccak(encoded_report) + + submitter = reach_consensus(ref_slot, report_hash, consensus_version, consensus, silent=True) + accounts[0].transfer(submitter, 10**19) + + # raw calls: the loaded interface carries the v5 ABI, the old impl needs v4 encoding + submit_calldata = web3.keccak(text=f"submitReportData({_LEGACY_V4_REPORT_ABI},uint256)")[:4] + encode( + [_LEGACY_V4_REPORT_ABI, "uint256"], [report, int(contract_version)] + ) + accounts.at(submitter, force=True).transfer(to=oracle.address, data=submit_calldata) + + extra_data_calldata = web3.keccak(text="submitReportExtraDataEmpty()")[:4] + accounts.at(submitter, force=True).transfer(to=oracle.address, data=extra_data_calldata) def process_pending_proposals(): @@ -179,7 +271,7 @@ def wait_for_time_window(from_hour_utc: int, to_hour_utc: int): def wait_for_target_time_to_satisfy_time_constrains(): current_time = chain.time() - target_time = 16 * 60 * 60 # 16:00 UTC + target_time = 16 * 60 * 60 # 16:00 UTC seconds_per_day = 24 * 60 * 60 day_start = current_time - (current_time % seconds_per_day) diff --git a/utils/test/exit_bus_data.py b/utils/test/exit_bus_data.py index 33d57281..faa1efb5 100644 --- a/utils/test/exit_bus_data.py +++ b/utils/test/exit_bus_data.py @@ -1,33 +1,49 @@ from dataclasses import dataclass from typing import Tuple, NewType -StakingModuleId = NewType('StakingModuleId', int) -NodeOperatorId = NewType('NodeOperatorId', int) +StakingModuleId = NewType("StakingModuleId", int) +NodeOperatorId = NewType("NodeOperatorId", int) NodeOperatorGlobalIndex = Tuple[StakingModuleId, NodeOperatorId] + @dataclass class LidoValidator: index: int pubkey: str + key_index: int = 0 # position of the key in the module registry; only used for DATA_FORMAT_LIST_WITH_KEY_INDEX + +# Mirrors ValidatorsExitBus.sol: format 1 (no keyIndex) and format 2 (with keyIndex). DATA_FORMAT_LIST = 1 +DATA_FORMAT_LIST_WITH_KEY_INDEX = 2 MODULE_ID_LENGTH = 3 NODE_OPERATOR_ID_LENGTH = 5 VALIDATOR_INDEX_LENGTH = 8 +KEY_INDEX_LENGTH = 8 VALIDATOR_PUB_KEY_LENGTH = 48 def encode_data( - validators_to_eject: list[tuple[NodeOperatorGlobalIndex, LidoValidator]], sort=True + validators_to_eject: list[tuple[NodeOperatorGlobalIndex, LidoValidator]], + sort=True, + data_format=DATA_FORMAT_LIST_WITH_KEY_INDEX, ): """ - Encodes report data for Exit Bus Contract into bytes. + Encodes report data for Exit Bus Contract into bytes, matching the packing in + ValidatorsExitBus.sol. The `data_format` selects the layout (contract's + submitReportData accepts only DATA_FORMAT_LIST_WITH_KEY_INDEX). - MSB <------------------------------------------------------- LSB - | 3 bytes | 5 bytes | 8 bytes | 48 bytes | - | moduleId | nodeOpId | validatorIndex | validatorPubkey | + Format 1 (DATA_FORMAT_LIST, 64 bytes/request): + | 3 bytes | 5 bytes | 8 bytes | 48 bytes | + | moduleId | nodeOpId | validatorIndex | validatorPubkey | + + Format 2 (DATA_FORMAT_LIST_WITH_KEY_INDEX, 72 bytes/request): + | 3 bytes | 5 bytes | 8 bytes | 8 bytes | 48 bytes | + | moduleId | nodeOpId | validatorIndex | keyIndex | validatorPubkey | """ + if data_format not in (DATA_FORMAT_LIST, DATA_FORMAT_LIST_WITH_KEY_INDEX): + raise ValueError(f"Unsupported data_format: {data_format}") if sort: validators = sort_validators_to_eject(validators_to_eject) @@ -41,14 +57,17 @@ def encode_data( result += op_id.to_bytes(NODE_OPERATOR_ID_LENGTH, "big") result += int(validator.index).to_bytes(VALIDATOR_INDEX_LENGTH, "big") + if data_format == DATA_FORMAT_LIST_WITH_KEY_INDEX: + result += int(validator.key_index).to_bytes(KEY_INDEX_LENGTH, "big") + pubkey_bytes = bytes.fromhex(str(validator.pubkey)[2:]) if len(pubkey_bytes) != VALIDATOR_PUB_KEY_LENGTH: - raise ValueError(f'Unexpected size of validator pub key. Pub key size: {len(validator.pubkey)}') + raise ValueError(f"Unexpected size of validator pub key. Pub key size: {len(validator.pubkey)}") result += pubkey_bytes - return result, DATA_FORMAT_LIST + return result, data_format def sort_validators_to_eject( diff --git a/utils/test/helpers.py b/utils/test/helpers.py index 7e1bfbee..a6648e56 100644 --- a/utils/test/helpers.py +++ b/utils/test/helpers.py @@ -5,6 +5,7 @@ from web3.types import BlockIdentifier # type: ignore from utils.config import contracts +from utils.evm_script import encode_error ZERO_ADDRESS = "0x0000000000000000000000000000000000000000" GWEI = 10**9 @@ -40,7 +41,18 @@ def shares_balance(account): def almostEqWithDiff(b1, b2, diff): return abs(b1 - b2) <= diff + def round_to_gwei(amount: int) -> int: """Round amount to gwei""" return amount // GWEI * GWEI + +def access_control_unauthorized(account, role_name: str) -> str: + """OZ v5 AccessControl revert: AccessControlUnauthorizedAccount(account, neededRole). + To match the brownie decoder output the address must be lowercase (the decoder does + not checksum it) and the role must be passed to encode_error as bytes.""" + address = str(getattr(account, "address", account)).lower() + return encode_error( + "AccessControlUnauthorizedAccount(address,bytes32)", + [address, bytes(web3.keccak(text=role_name))], + ) diff --git a/utils/test/oracle_report_helpers.py b/utils/test/oracle_report_helpers.py index e584f147..fb13a828 100644 --- a/utils/test/oracle_report_helpers.py +++ b/utils/test/oracle_report_helpers.py @@ -9,14 +9,14 @@ from hexbytes import HexBytes from utils.config import contracts, AO_CONSENSUS_VERSION -from utils.test.exit_bus_data import encode_data +from utils.test.exit_bus_data import encode_data, DATA_FORMAT_LIST_WITH_KEY_INDEX from utils.test.helpers import ETH, GWEI, eth_balance from utils.test.merkle_tree import RewardsTree ZERO_HASH = bytes([0] * 32) ZERO_BYTES32 = HexBytes(ZERO_HASH) ONE_DAY = 1 * 24 * 60 * 60 -SHARE_RATE_PRECISION = 10 ** 27 +SHARE_RATE_PRECISION = 10**27 EXTRA_DATA_FORMAT_EMPTY = 0 EXTRA_DATA_FORMAT_LIST = 1 @@ -26,14 +26,18 @@ @dataclass class AccountingReport: - """Accounting oracle ReportData struct""" + """Accounting oracle ReportData struct (v5, SRv3): numValidators/clBalanceGwei were + replaced with clValidatorsBalanceGwei/clPendingBalanceGwei, plus two new arrays for + per-module balance updates""" consensusVersion: int refSlot: int - numValidators: int - clBalanceGwei: int + clValidatorsBalanceGwei: int + clPendingBalanceGwei: int stakingModuleIdsWithNewlyExitedValidators: list[int] numExitedValidatorsByStakingModule: list[int] + stakingModuleIdsWithUpdatedBalance: list[int] + validatorBalancesGweiByStakingModule: list[int] withdrawalVaultBalance: int elRewardsVaultBalance: int sharesRequestedToBurn: int @@ -67,14 +71,16 @@ def copy(self) -> "AccountingReport": def prepare_accounting_report( *, refSlot, - clBalance, - numValidators, + clValidatorsBalance, # wei; active validators balance (v5: replaces clBalance+numValidators) + clPendingBalance, # wei; pending deposits balance on the CL withdrawalVaultBalance, elRewardsVaultBalance, sharesRequestedToBurn, simulatedShareRate, stakingModuleIdsWithNewlyExitedValidators=[], numExitedValidatorsByStakingModule=[], + stakingModuleIdsWithUpdatedBalance=[], + validatorBalancesGweiByStakingModule=[], consensusVersion=AO_CONSENSUS_VERSION, withdrawalFinalizationBatches=[], isBunkerMode=False, @@ -85,10 +91,12 @@ def prepare_accounting_report( report = AccountingReport( int(consensusVersion), int(refSlot), - int(numValidators), - int(clBalance // GWEI), + int(clValidatorsBalance // GWEI), + int(clPendingBalance // GWEI), [int(i) for i in stakingModuleIdsWithNewlyExitedValidators], [int(i) for i in numExitedValidatorsByStakingModule], + [int(i) for i in stakingModuleIdsWithUpdatedBalance], + [int(i) for i in validatorBalancesGweiByStakingModule], int(withdrawalVaultBalance), int(elRewardsVaultBalance), int(sharesRequestedToBurn), @@ -105,9 +113,9 @@ def prepare_accounting_report( return (report.items, report.hash) -def prepare_exit_bus_report(validators_to_exit, ref_slot): +def prepare_exit_bus_report(validators_to_exit, ref_slot, data_format=DATA_FORMAT_LIST_WITH_KEY_INDEX): consensus_version = contracts.validators_exit_bus_oracle.getConsensusVersion() - data, data_format = encode_data(validators_to_exit) + data, data_format = encode_data(validators_to_exit, data_format=data_format) report = (consensus_version, ref_slot, len(validators_to_exit), data_format, data) report_data = encode_data_from_abi(report, contracts.validators_exit_bus_oracle.abi, "submitReportData") @@ -120,7 +128,7 @@ def prepare_csm_report(node_operators_rewards: dict, ref_slot, distributed_share shares = node_operators_rewards.copy() if len(shares) < 2: # put a stone - shares[2 ** 64 - 1] = 0 + shares[2**64 - 1] = 0 tree = RewardsTree.new(tuple((no_id, amount) for (no_id, amount) in shares.items())) # semi-random values @@ -153,20 +161,9 @@ def encode_data_from_abi(data, abi, func_name): def get_finalization_batches( share_rate: int, limited_withdrawal_vault_balance, limited_el_rewards_vault_balance ) -> list[int]: - ( - _, - _, - _, - _, - _, - _, - _, - requestTimestampMargin, - _, - _, - _, - _, - ) = contracts.oracle_report_sanity_checker.getOracleReportLimits() + # access by field name — the LimitsList struct changes between upgrades (12 -> 16 fields in SRv3) + limits = contracts.oracle_report_sanity_checker.getOracleReportLimits() + requestTimestampMargin = limits["requestTimestampMargin"] buffered_ether = contracts.lido.getBufferedEther() unfinalized_steth = contracts.withdrawal_queue.unfinalizedStETH() reserved_buffer = min(buffered_ether, unfinalized_steth) @@ -203,14 +200,16 @@ def reach_consensus(slot, report, version, oracle_contract, silent=False): def push_oracle_report( *, refSlot, - clBalance, - numValidators, + clValidatorsBalance, # wei (v5: replaces clBalance+numValidators) + clPendingBalance=0, # wei withdrawalVaultBalance, elRewardsVaultBalance, sharesRequestedToBurn, simulatedShareRate, stakingModuleIdsWithNewlyExitedValidators=[], numExitedValidatorsByStakingModule=[], + stakingModuleIdsWithUpdatedBalance=[], + validatorBalancesGweiByStakingModule=[], withdrawalFinalizationBatches=[], isBunkerMode=False, extraDataFormat=0, @@ -225,14 +224,16 @@ def push_oracle_report( oracleVersion = contracts.accounting_oracle.getContractVersion() (items, hash) = prepare_accounting_report( refSlot=refSlot, - clBalance=clBalance, - numValidators=numValidators, + clValidatorsBalance=clValidatorsBalance, + clPendingBalance=clPendingBalance, withdrawalVaultBalance=withdrawalVaultBalance, elRewardsVaultBalance=elRewardsVaultBalance, sharesRequestedToBurn=sharesRequestedToBurn, simulatedShareRate=simulatedShareRate, stakingModuleIdsWithNewlyExitedValidators=stakingModuleIdsWithNewlyExitedValidators, numExitedValidatorsByStakingModule=numExitedValidatorsByStakingModule, + stakingModuleIdsWithUpdatedBalance=stakingModuleIdsWithUpdatedBalance, + validatorBalancesGweiByStakingModule=validatorBalancesGweiByStakingModule, consensusVersion=consensusVersion, withdrawalFinalizationBatches=withdrawalFinalizationBatches, isBunkerMode=isBunkerMode, @@ -241,7 +242,7 @@ def push_oracle_report( extraDataItemsCount=extraDataItemsCount, ) submitter = reach_consensus(refSlot, hash, consensusVersion, contracts.hash_consensus_for_accounting_oracle, silent) - accounts[0].transfer(submitter, 10 ** 19) + accounts[0].transfer(submitter, 10**19) # print(contracts.oracle_report_sanity_checker.getOracleReportLimits()) report_tx = contracts.accounting_oracle.submitReportData(items, oracleVersion, {"from": submitter}) if not silent: @@ -282,8 +283,17 @@ def push_oracle_report( def simulate_report( - *, refSlot, beaconValidators, postCLBalance, withdrawalVaultBalance, elRewardsVaultBalance, block_identifier=None + *, + refSlot, + clValidatorsBalance, + clPendingBalance, + withdrawalVaultBalance, + elRewardsVaultBalance, + block_identifier=None, ): + """Dry-runs the report via Accounting.simulateOracleReport (v5 ReportValues: + balances instead of the validator count) and returns + (postTotalPooledEther, postTotalShares, withdrawalsVaultTransfer, elRewardsVaultTransfer).""" (_, SECONDS_PER_SLOT, GENESIS_TIME) = contracts.hash_consensus_for_accounting_oracle.getChainConfig() reportTime = GENESIS_TIME + refSlot * SECONDS_PER_SLOT @@ -297,45 +307,34 @@ def simulate_report( # The code is taken from the current production `lido-oracle` implementation # source: https://github.com/lidofinance/lido-oracle/blob/da393bf06250344a4d06dce6d1ac6a3ddcb9c7a3/src/providers/execution/contracts/lido.py#L93-L95 "stateDiff": { - override_slot: '0x' + refSlot.to_bytes(32, "big").hex(), + override_slot: "0x" + refSlot.to_bytes(32, "big").hex(), }, }, } - try: - calculatedValues = contracts.accounting.simulateOracleReport.call( - [ - reportTime, - ONE_DAY, - beaconValidators, - postCLBalance, - withdrawalVaultBalance, - elRewardsVaultBalance, - 0, - [], - 0, - ], - {"from": contracts.accounting_oracle.address}, - block_identifier=block_identifier, - override=state_override, - ) - return (calculatedValues[14], calculatedValues[13], calculatedValues[0], calculatedValues[1]) - except VirtualMachineError: - # workaround for empty revert message from ganache on eth_call - - # override storage value of the processing reference slot to make the simulation sound - # Since it's not possible to pass an override as a part of the state-changing transaction - web3.provider.make_request( - # can assume ganache only here - "evm_setAccountStorageAt", - [contracts.accounting_oracle.address, override_slot, refSlot], - ) - - contracts.accounting.handleOracleReport( - [reportTime, ONE_DAY, beaconValidators, postCLBalance, withdrawalVaultBalance, elRewardsVaultBalance, 0, [], 0], - {"from": contracts.accounting_oracle.address}, - ) - raise # unreachable, for static analysis only + calculated = contracts.accounting.simulateOracleReport.call( + [ + reportTime, + ONE_DAY, + clValidatorsBalance, + clPendingBalance, + withdrawalVaultBalance, + elRewardsVaultBalance, + 0, # sharesRequestedToBurn + [], # withdrawalFinalizationBatches + 0, # simulatedShareRate + ], + {"from": contracts.accounting_oracle.address}, + block_identifier=block_identifier, + override=state_override, + ) + # named access: the CalculatedValues struct layout changes between upgrades + return ( + calculated["postTotalPooledEther"], + calculated["postTotalShares"], + calculated["withdrawalsVaultTransfer"], + calculated["elRewardsVaultTransfer"], + ) def wait_to_next_available_report_time(consensus_contract): @@ -384,6 +383,8 @@ def oracle_report( silent=False, sharesRequestedToBurn=None, withdrawalFinalizationBatches=[], + stakingModuleIdsWithUpdatedBalance=None, + validatorBalancesGweiByStakingModule=None, simulatedShareRate=None, dry_run: Literal[False] = False, ) -> tuple[TransactionReceipt, TransactionReceipt]: @@ -412,6 +413,8 @@ def oracle_report( silent=False, sharesRequestedToBurn=None, withdrawalFinalizationBatches=[], + stakingModuleIdsWithUpdatedBalance=None, + validatorBalancesGweiByStakingModule=None, simulatedShareRate=None, refSlot=None, dry_run: Literal[True], @@ -440,6 +443,8 @@ def oracle_report( silent=False, sharesRequestedToBurn=None, withdrawalFinalizationBatches=[], + stakingModuleIdsWithUpdatedBalance=None, + validatorBalancesGweiByStakingModule=None, simulatedShareRate=None, refSlot=None, dry_run=False, @@ -450,10 +455,22 @@ def oracle_report( if refSlot is None: (refSlot, _) = contracts.hash_consensus_for_accounting_oracle.getCurrentFrame() - (_, beaconValidators, beaconBalance) = contracts.lido.getBeaconStat() - - postCLBalance = beaconBalance + cl_diff - postBeaconValidators = beaconValidators + cl_appeared_validators + # v5: the report carries CL balances, not validator counts. getBalanceStats returns + # the active/pending balances as of the last report plus the deposits made since. + ( + clValidatorsBalance, + clPendingBalance, + _deposited_since_last_report, + deposited_for_current_report, + ) = contracts.lido.getBalanceStats() + + postCLBalance = clValidatorsBalance + cl_diff + # deposits made since the last report and up to the refSlot surface as pending on the CL + postCLPendingBalance = clPendingBalance + deposited_for_current_report + if cl_appeared_validators: + # deprecated with SRv3: the v5 report format has no validator count field; + # kept in the signature so pre-SRv3 callers don't break at the call site + warnings.warn("cl_appeared_validators is a no-op since the SRv3 (v5) report format") elRewardsVaultBalance = ( eth_balance(contracts.execution_layer_rewards_vault.address) @@ -482,13 +499,30 @@ def oracle_report( (coverShares, nonCoverShares) = contracts.burner.getSharesRequestedToBurn() sharesRequestedToBurn = coverShares + nonCoverShares + # v5: the report must list balances for ALL modules in registration order, summing + # exactly to clValidatorsBalanceGwei (the checker validates the report against itself). + # SR-stored values are migration-seeded (32 ETH x active, overstated), so distribute + # the reported total proportionally to them instead of copying them. + if stakingModuleIdsWithUpdatedBalance is None: + stakingModuleIdsWithUpdatedBalance = list(contracts.staking_router.getStakingModuleIds()) + target_gwei = postCLBalance // GWEI + stored_gwei = [ + contracts.staking_router.getModuleValidatorsBalance(module_id) // GWEI + for module_id in stakingModuleIdsWithUpdatedBalance + ] + total_stored_gwei = sum(stored_gwei) + assert total_stored_gwei > 0, "staking router has no validator balances" + validatorBalancesGweiByStakingModule = [balance * target_gwei // total_stored_gwei for balance in stored_gwei] + # return the integer-division remainder to the first module: the sum must match exactly + validatorBalancesGweiByStakingModule[0] += target_gwei - sum(validatorBalancesGweiByStakingModule) + is_bunker = False if not skip_withdrawals: (postTotalPooledEther, postTotalShares, withdrawals, elRewards) = simulate_report( refSlot=refSlot, - beaconValidators=postBeaconValidators, - postCLBalance=postCLBalance, + clValidatorsBalance=postCLBalance, + clPendingBalance=postCLPendingBalance, withdrawalVaultBalance=withdrawalVaultBalance, elRewardsVaultBalance=elRewardsVaultBalance, block_identifier=simulation_block_identifier, @@ -511,10 +545,12 @@ def oracle_report( return AccountingReport( consensusVersion=contracts.accounting_oracle.getConsensusVersion(), refSlot=refSlot, - numValidators=postBeaconValidators, - clBalanceGwei=postCLBalance // GWEI, + clValidatorsBalanceGwei=postCLBalance // GWEI, + clPendingBalanceGwei=postCLPendingBalance // GWEI, stakingModuleIdsWithNewlyExitedValidators=stakingModuleIdsWithNewlyExitedValidators, numExitedValidatorsByStakingModule=numExitedValidatorsByStakingModule, + stakingModuleIdsWithUpdatedBalance=stakingModuleIdsWithUpdatedBalance, + validatorBalancesGweiByStakingModule=validatorBalancesGweiByStakingModule, withdrawalVaultBalance=withdrawalVaultBalance, elRewardsVaultBalance=elRewardsVaultBalance, sharesRequestedToBurn=sharesRequestedToBurn, @@ -530,8 +566,8 @@ def oracle_report( return push_oracle_report( refSlot=refSlot, - clBalance=postCLBalance, - numValidators=postBeaconValidators, + clValidatorsBalance=postCLBalance, + clPendingBalance=postCLPendingBalance, withdrawalVaultBalance=withdrawalVaultBalance, sharesRequestedToBurn=sharesRequestedToBurn, withdrawalFinalizationBatches=withdrawalFinalizationBatches, @@ -543,6 +579,8 @@ def oracle_report( extraDataList=extraDataList, stakingModuleIdsWithNewlyExitedValidators=stakingModuleIdsWithNewlyExitedValidators, numExitedValidatorsByStakingModule=numExitedValidatorsByStakingModule, + stakingModuleIdsWithUpdatedBalance=stakingModuleIdsWithUpdatedBalance, + validatorBalancesGweiByStakingModule=validatorBalancesGweiByStakingModule, silent=silent, isBunkerMode=is_bunker, ) From d90f91d6826a892f17d3d950d8887217ec40d3f1 Mon Sep 17 00:00:00 2001 From: Anna Mukharram Date: Tue, 7 Jul 2026 14:03:52 +0400 Subject: [PATCH 02/30] fix: circuit_breaker tests fix --- configs/config_mainnet.py | 114 ++++++----------- ...mv2.py => upgrade_2026_07_15_srv3_cmv2.py} | 2 +- tests/acceptance/test_accounting_oracle.py | 3 - .../test_accounting_oracle_negative.py | 88 ++++--------- .../test_circuit_breaker_acceptance.py | 119 +++++++++++------- tests/acceptance/test_consolidation.py | 13 -- 6 files changed, 131 insertions(+), 208 deletions(-) rename scripts/{upgrade_2026_04_30_srv3_cmv2.py => upgrade_2026_07_15_srv3_cmv2.py} (99%) diff --git a/configs/config_mainnet.py b/configs/config_mainnet.py index aef4e75f..d69c68aa 100644 --- a/configs/config_mainnet.py +++ b/configs/config_mainnet.py @@ -32,9 +32,7 @@ LIDO_IMPL_V1 = "0x47EbaB13B806773ec2A2d16873e2dF770D130b50" LEGACY_ORACLE_IMPL_V1 = "0x1430194905301504e8830ce4B0b0df7187E84AbD" -NODE_OPERATORS_REGISTRY_IMPL_V1 = ( - "0x5d39ABaa161e622B99D45616afC8B837E9F19a25" # was used in archived tests -) +NODE_OPERATORS_REGISTRY_IMPL_V1 = "0x5d39ABaa161e622B99D45616afC8B837E9F19a25" # was used in archived tests VALIDATOR_EXIT_VERIFIER = "0xbDb567672c867DB533119C2dcD4FB9d8b44EC82f" # Aragon APM Repos @@ -66,46 +64,22 @@ EASYTRACK = "0xF0211b7660680B49De1A7E9f25C65660F0a13Fea" EASYTRACK_EVMSCRIPT_EXECUTOR = "0xFE5986E06210aC1eCC1aDCafc0cc7f8D63B3F977" -EASYTRACK_INCREASE_NOP_STAKING_LIMIT_FACTORY = ( - "0xFeBd8FAC16De88206d4b18764e826AF38546AfE0" -) +EASYTRACK_INCREASE_NOP_STAKING_LIMIT_FACTORY = "0xFeBd8FAC16De88206d4b18764e826AF38546AfE0" EASYTRACK_SIMPLE_DVT_TRUSTED_CALLER = "0x08637515E85A4633E23dfc7861e2A9f53af640f7" -EASYTRACK_SIMPLE_DVT_ADD_NODE_OPERATORS_FACTORY = ( - "0xcAa3AF7460E83E665EEFeC73a7a542E5005C9639" -) -EASYTRACK_SIMPLE_DVT_ACTIVATE_NODE_OPERATORS_FACTORY = ( - "0xCBb418F6f9BFd3525CE6aADe8F74ECFEfe2DB5C8" -) -EASYTRACK_SIMPLE_DVT_DEACTIVATE_NODE_OPERATORS_FACTORY = ( - "0x8B82C1546D47330335a48406cc3a50Da732672E7" -) -EASYTRACK_SIMPLE_DVT_SET_VETTED_VALIDATORS_LIMITS_FACTORY = ( - "0xD75778b855886Fc5e1eA7D6bFADA9EB68b35C19D" -) -EASYTRACK_SIMPLE_DVT_SET_NODE_OPERATOR_NAMES_FACTORY = ( - "0x7d509BFF310d9460b1F613e4e40d342201a83Ae4" -) -EASYTRACK_SIMPLE_DVT_SET_NODE_OPERATOR_REWARD_ADDRESSES_FACTORY = ( - "0x589e298964b9181D9938B84bB034C3BB9024E2C0" -) -EASYTRACK_SIMPLE_DVT_UPDATE_TARGET_VALIDATOR_LIMITS_FACTORY = ( - "0x161a4552A625844c822954C5AcBac928ee0f399B" -) -EASYTRACK_SIMPLE_DVT_CHANGE_NODE_OPERATOR_MANAGERS_FACTORY = ( - "0xE31A0599A6772BCf9b2bFc9e25cf941e793c9a7D" -) -EASYTRACK_CSM_SETTLE_EL_REWARDS_STEALING_PENALTY_FACTORY = ( - "0xF6B6E7997338C48Ea3a8BCfa4BB64a315fDa76f4" -) +EASYTRACK_SIMPLE_DVT_ADD_NODE_OPERATORS_FACTORY = "0xcAa3AF7460E83E665EEFeC73a7a542E5005C9639" +EASYTRACK_SIMPLE_DVT_ACTIVATE_NODE_OPERATORS_FACTORY = "0xCBb418F6f9BFd3525CE6aADe8F74ECFEfe2DB5C8" +EASYTRACK_SIMPLE_DVT_DEACTIVATE_NODE_OPERATORS_FACTORY = "0x8B82C1546D47330335a48406cc3a50Da732672E7" +EASYTRACK_SIMPLE_DVT_SET_VETTED_VALIDATORS_LIMITS_FACTORY = "0xD75778b855886Fc5e1eA7D6bFADA9EB68b35C19D" +EASYTRACK_SIMPLE_DVT_SET_NODE_OPERATOR_NAMES_FACTORY = "0x7d509BFF310d9460b1F613e4e40d342201a83Ae4" +EASYTRACK_SIMPLE_DVT_SET_NODE_OPERATOR_REWARD_ADDRESSES_FACTORY = "0x589e298964b9181D9938B84bB034C3BB9024E2C0" +EASYTRACK_SIMPLE_DVT_UPDATE_TARGET_VALIDATOR_LIMITS_FACTORY = "0x161a4552A625844c822954C5AcBac928ee0f399B" +EASYTRACK_SIMPLE_DVT_CHANGE_NODE_OPERATOR_MANAGERS_FACTORY = "0xE31A0599A6772BCf9b2bFc9e25cf941e793c9a7D" +EASYTRACK_CSM_SETTLE_EL_REWARDS_STEALING_PENALTY_FACTORY = "0xF6B6E7997338C48Ea3a8BCfa4BB64a315fDa76f4" EASYTRACK_MEV_BOOST_ADD_RELAYS_FACTORY = "0x00A3D6260f70b1660c8646Ef25D0820EFFd7bE60" EASYTRACK_MEV_BOOST_REMOVE_RELAYS_FACTORY = "0x9721c0f77E3Ea40eD592B9DCf3032DaF269c0306" EASYTRACK_MEV_BOOST_EDIT_RELAYS_FACTORY = "0x6b7863f2c7dEE99D3b744fDAEDbEB1aeCC025535" -EASYTRACK_CURATED_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY = ( - "0x4F716AD3Cc7A3A5cdA2359e5B2c84335c171dCde" -) -EASYTRACK_SIMPLE_DVT_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY = ( - "0x58A59dDC6Aea9b1D5743D024E15DfA4badB56E37" -) +EASYTRACK_CURATED_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY = "0x4F716AD3Cc7A3A5cdA2359e5B2c84335c171dCde" +EASYTRACK_SIMPLE_DVT_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY = "0x58A59dDC6Aea9b1D5743D024E15DfA4badB56E37" EASYTRACK_CS_SET_VETTED_GATE_TREE_FACTORY = "0xBc5642bDD6F2a54b01A75605aAe9143525D97308" # Liquidity Observation Lab (LOL) stETH AllowedRecipientsRegistry @@ -152,16 +126,12 @@ DEPLOYER_EOA = "0x8Ea83AD72396f1E0cD2f8E72b1461db8Eb6aF7B5" # 0x01...withdrawal_vault or Lido.getWithdrawalCredentials() -WITHDRAWAL_CREDENTIALS = ( - "0x010000000000000000000000b9d7934878b5fb9610b3fe8a5e441e8fad7e293f" -) +WITHDRAWAL_CREDENTIALS = "0x010000000000000000000000b9d7934878b5fb9610b3fe8a5e441e8fad7e293f" # Lido LIDO_IMPL = "0x59deCAF1289BbF615Ac8b1024127eC7FF842aB01" # SRV3 # see Lido's proxy appId() -LIDO_ARAGON_APP_ID = ( - "0x3ca7c3e38968823ccb4c78ea688df41356f182ae1d159e4ee608d30d68cef320" -) +LIDO_ARAGON_APP_ID = "0x3ca7c3e38968823ccb4c78ea688df41356f182ae1d159e4ee608d30d68cef320" LIDO_MAX_STAKE_LIMIT_ETH = 150_000 # set by finalizeUpgrade_v4 (upgrade-params-mainnet.toml [lido].depositsReserveTarget) LIDO_DEPOSITS_RESERVE_TARGET = 1_500 * 10**18 # 1500 ETH # SRV3 @@ -170,16 +140,12 @@ ## address is LIDO_LEGACY_ORACLE LEGACY_ORACLE_IMPL = "0xa29b819654cE6224A222bb5f586920105E2D7E0E" ## see LidoOracle's proxy appId() -ORACLE_ARAGON_APP_ID = ( - "0x8b47ba2a8454ec799cd91646e7ec47168e91fd139b23f017455f3e5898aaba93" -) +ORACLE_ARAGON_APP_ID = "0x8b47ba2a8454ec799cd91646e7ec47168e91fd139b23f017455f3e5898aaba93" # NodeOperatorsRegistry aka Curated Staking Module NODE_OPERATORS_REGISTRY_IMPL = "0x6828b023e737f96B168aCd0b5c6351971a4F81aE" ## see NodeOperatorsRegistry's proxy appId() -NODE_OPERATORS_REGISTRY_ARAGON_APP_ID = ( - "0x7071f283424072341f856ac9e947e7ec0eb68719f757a7e785979b6b8717579d" -) +NODE_OPERATORS_REGISTRY_ARAGON_APP_ID = "0x7071f283424072341f856ac9e947e7ec0eb68719f757a7e785979b6b8717579d" NODE_OPERATORS_REGISTRY_VERSION = 4 NOR_EXIT_DEADLINE_IN_SEC = 172800 @@ -212,6 +178,12 @@ CURATED_V2_STAKING_MODULE_MAX_DEPOSITS_PER_BLOCK = 100 CURATED_V2_STAKING_MODULE_MIN_DEPOSITS_BLOCK_DISTANCE = 75 CURATED_V2_ACCOUNTING = "0xFfFEF82624cf7ad1300D084aA547DDa828a95eAd" # SRV3 +CURATED_V2_FEE_ORACLE = "0xB4214247C3A64d780Ae4e42e1441863B7Af0f73A" # SRV3 +CURATED_V2_VERIFIER = "0x4A19e9496B21c438c7f264F0fEF8A168DF297633" # SRV3 +CURATED_V2_EJECTOR = "0xdC9058e6D8b71Adc71306De8d8E7335e414aB7A1" # SRV3 +# CuratedModuleConfig.circuitBreakerPauser — the vote registers it as pauser +# for all five CM v2 pausables on the CircuitBreaker +CURATED_V2_CIRCUIT_BREAKER_PAUSER = "0x2570e0b22AD904501dfB0d49575991ACB801dD91" # SRV3 # SRv3/CMv2 upgrade omnibus (UpgradeVoteScript) — the vote script reads its items # from this contract. Fork-deployed, synced from core/deployed-local.json. @@ -222,9 +194,7 @@ SIMPLE_DVT_REPO = "0x2325b0a607808dE42D918DB07F925FFcCfBb2968" ## see SimpleDVT's proxy appId() SIMPLE_DVT_ARAGON_APP_NAME = "simple-dvt" -SIMPLE_DVT_ARAGON_APP_ID = ( - "0xe1635b63b5f7b5e545f2a637558a4029dea7905361a2f0fc28c66e9136cf86a4" -) +SIMPLE_DVT_ARAGON_APP_ID = "0xe1635b63b5f7b5e545f2a637558a4029dea7905361a2f0fc28c66e9136cf86a4" SIMPLE_DVT_MODULE_STUCK_PENALTY_DELAY = 0 SIMPLE_DVT_MODULE_TARGET_SHARE_BP = 430 SIMPLE_DVT_MODULE_MODULE_FEE_BP = 800 @@ -242,9 +212,7 @@ # CSM CS_ORACLE_EPOCHS_PER_FRAME = 225 * 28 # 28 days -CS_FEE_ORACLE_CONSENSUS_VERSION = ( - 4 # SRV3: set by FeeOracle.finalizeUpgradeV3(consensusVersion) -) +CS_FEE_ORACLE_CONSENSUS_VERSION = 4 # SRV3: set by FeeOracle.finalizeUpgradeV3(consensusVersion) CS_MODULE_ID = 3 CS_MODULE_NAME = "Community Staking" CS_MODULE_MODULE_FEE_BP = 600 @@ -301,9 +269,7 @@ # DepositSecurityModule DEPOSIT_SECURITY_MODULE = "0x53fa102681e10C680cb1EdEe1A15ea5630e61Ac5" # SRV3 -DEPOSIT_SECURITY_MODULE_V2 = ( - "0xC77F8768774E1c9244BEed705C4354f2113CFc09" # dsm address before SR V2 enact -) +DEPOSIT_SECURITY_MODULE_V2 = "0xC77F8768774E1c9244BEed705C4354f2113CFc09" # dsm address before SR V2 enact DSM_MAX_OPERATORS_PER_UNVETTING = 200 DSM_PAUSE_INTENT_VALIDITY_PERIOD_BLOCKS = 6646 ## Migrated from LIDO_DEPOSIT_SECURITY_MODULE_V1 @@ -397,9 +363,7 @@ TOP_UP_GATEWAY_MAX_VALIDATORS_PER_TOP_UP = 32 TOP_UP_GATEWAY_MIN_BLOCK_DISTANCE = 75 TOP_UP_GATEWAY_MAX_ROOT_AGE = 600 # seconds -TOP_UP_GATEWAY_TARGET_BALANCE_GWEI = ( - 2_046_750_000_000 # 2046.75 ETH (1.25 ETH margin below MaxEB) -) +TOP_UP_GATEWAY_TARGET_BALANCE_GWEI = 2_046_750_000_000 # 2046.75 ETH (1.25 ETH margin below MaxEB) TOP_UP_GATEWAY_MIN_TOP_UP_GWEI = 2_000_000_000 # 2 ETH # sole TOP_UP_ROLE holder (coreUpgrade.topUpGatewayDepositor, stable deploy input) TOP_UP_GATEWAY_DEPOSITOR = "0xF82aC5937A20dC862F9bc0668779031E06000f17" @@ -437,30 +401,26 @@ # + cs_module_fee * cs_module_share SR_MODULES_FEE_BP = ( - CURATED_STAKING_MODULE_MODULE_FEE_BP - * (100_00 - SIMPLE_DVT_MODULE_TARGET_SHARE_BP - CS_MODULE_TARGET_SHARE_BP) + CURATED_STAKING_MODULE_MODULE_FEE_BP * (100_00 - SIMPLE_DVT_MODULE_TARGET_SHARE_BP - CS_MODULE_TARGET_SHARE_BP) + SIMPLE_DVT_MODULE_MODULE_FEE_BP * SIMPLE_DVT_MODULE_TARGET_SHARE_BP + CS_MODULE_MODULE_FEE_BP * CS_MODULE_TARGET_SHARE_BP ) // 100_00 SR_TREASURY_FEE_BP = ( - CURATED_STAKING_MODULE_TREASURY_FEE_BP - * (100_00 - SIMPLE_DVT_MODULE_TARGET_SHARE_BP - CS_MODULE_TARGET_SHARE_BP) + CURATED_STAKING_MODULE_TREASURY_FEE_BP * (100_00 - SIMPLE_DVT_MODULE_TARGET_SHARE_BP - CS_MODULE_TARGET_SHARE_BP) + SIMPLE_DVT_MODULE_TREASURY_FEE_BP * SIMPLE_DVT_MODULE_TARGET_SHARE_BP + CS_MODULE_TREASURY_FEE_BP * CS_MODULE_TARGET_SHARE_BP ) // 100_00 SR_MODULES_FEE_E20 = ( - CURATED_STAKING_MODULE_MODULE_FEE_BP - * (100_00 - SIMPLE_DVT_MODULE_TARGET_SHARE_BP - CS_MODULE_TARGET_SHARE_BP) + CURATED_STAKING_MODULE_MODULE_FEE_BP * (100_00 - SIMPLE_DVT_MODULE_TARGET_SHARE_BP - CS_MODULE_TARGET_SHARE_BP) + SIMPLE_DVT_MODULE_MODULE_FEE_BP * SIMPLE_DVT_MODULE_TARGET_SHARE_BP + CS_MODULE_MODULE_FEE_BP * CS_MODULE_TARGET_SHARE_BP ) * 10**12 # same as for SR_MODULES_FEE_E20 SR_TREASURY_FEE_E20 = ( - CURATED_STAKING_MODULE_TREASURY_FEE_BP - * (100_00 - SIMPLE_DVT_MODULE_TARGET_SHARE_BP - CS_MODULE_TARGET_SHARE_BP) + CURATED_STAKING_MODULE_TREASURY_FEE_BP * (100_00 - SIMPLE_DVT_MODULE_TARGET_SHARE_BP - CS_MODULE_TARGET_SHARE_BP) + SIMPLE_DVT_MODULE_TREASURY_FEE_BP * SIMPLE_DVT_MODULE_TARGET_SHARE_BP + CS_MODULE_TREASURY_FEE_BP * CS_MODULE_TARGET_SHARE_BP ) * 10**12 @@ -481,6 +441,9 @@ # CircuitBreaker CIRCUIT_BREAKER = "0x6019CB557978296BA3C08a7B73225C0975DFB2F7" +# GlobalConfig.circuitBreakerCommittee — the vote registers it as pauser for +# ConsolidationGateway / TopUpGateway +CIRCUIT_BREAKER_COMMITTEE = "0x8772E3a2D86B9347A2688f9bc1808A6d8917760C" # SRV3 CIRCUIT_BREAKER_MIN_PAUSE_DURATION = 432000 # 5 days CIRCUIT_BREAKER_MAX_PAUSE_DURATION = 5184000 # 60 days CIRCUIT_BREAKER_PAUSE_DURATION = 1814400 # 21 days @@ -545,19 +508,16 @@ CS_STRIKES_ADDRESS = "0xaa328816027F2D32B9F56d190BC9Fa4A5C07637f" CS_EJECTOR_ADDRESS = "0x2cB8510b0A30A38427E7e9555e8584b1a90c1BF7" # SRV3 CS_VETTED_GATE_ADDRESS = "0xB314D4A76C457c93150d308787939063F4Cc67E0" -CS_PERMISSIONLESS_GATE_ADDRESS = ( - "0xe29eaE1f3A3D0eDD45Bd6D4248A38F603f1F4d1A" # SRV3 newPermissionlessGate -) +CS_PERMISSIONLESS_GATE_ADDRESS = "0xe29eaE1f3A3D0eDD45Bd6D4248A38F603f1F4d1A" # SRV3 newPermissionlessGate CS_VERIFIER_V2_ADDRESS = "0xdC5FE1782B6943f318E05230d688713a560063DC" +CS_IDENTIFIED_DVT_CLUSTER_GATE_ADDRESS = "0x8d2b4aCDa9717847F739fa1c5e78BF47ca99a024" # SRV3 CS_GATE_SEAL_V2_ADDRESS = "0xE1686C2E90eb41a48356c1cC7FaA17629af3ADB3" TWO_PHASE_FRAME_CONFIG_UPDATE = "0xb2B4DB1491cbe949ae85EfF01E0d3ee239f110C1" # DualGovernance DUAL_GOVERNANCE = "0xC1db28B3301331277e307FDCfF8DE28242A4486E" TIMELOCK = "0xCE0425301C85c5Ea2A0873A2dEe44d78E02D2316" -DUAL_GOVERNANCE_EXECUTORS = [ - "0x23E0B465633FF5178808F4A75186E2F2F9537021" -] # Executor #1 is admin executor +DUAL_GOVERNANCE_EXECUTORS = ["0x23E0B465633FF5178808F4A75186E2F2F9537021"] # Executor #1 is admin executor RESEAL_MANAGER = "0x7914b5a1539b97Bd0bbd155757F25FD79A522d24" DAO_EMERGENCY_GOVERNANCE = "0x553337946F2FAb8911774b20025fa776B76a7CcE" ROLES_VALIDATOR = "0x31534e3aFE219B609da3715a00a1479D2A2d7981" diff --git a/scripts/upgrade_2026_04_30_srv3_cmv2.py b/scripts/upgrade_2026_07_15_srv3_cmv2.py similarity index 99% rename from scripts/upgrade_2026_04_30_srv3_cmv2.py rename to scripts/upgrade_2026_07_15_srv3_cmv2.py index 0e7fe30b..1e7e365c 100644 --- a/scripts/upgrade_2026_04_30_srv3_cmv2.py +++ b/scripts/upgrade_2026_07_15_srv3_cmv2.py @@ -1,5 +1,5 @@ """ -Vote 2026_04_30 +Vote 2026_07_15 1. Submit a Dual Governance proposal to activate Staking Router v3 + Curated Module v2 + Community Staking Module v3 # ======================== Core ======================== diff --git a/tests/acceptance/test_accounting_oracle.py b/tests/acceptance/test_accounting_oracle.py index 65c9a239..a7440304 100644 --- a/tests/acceptance/test_accounting_oracle.py +++ b/tests/acceptance/test_accounting_oracle.py @@ -80,9 +80,6 @@ def test_consensus(contract): def test_processing_state(contract): - # Absolute values (deadline, hashes, submitted flags) depend on whether a report - # has landed in the current frame — they change with the fork block / fixture - # timing, so only frame-independent invariants are asserted. consensus = interface.HashConsensus(contract.getConsensusContract()) state = contract.getProcessingState() diff --git a/tests/acceptance/test_accounting_oracle_negative.py b/tests/acceptance/test_accounting_oracle_negative.py index 4a17e056..a0d82824 100644 --- a/tests/acceptance/test_accounting_oracle_negative.py +++ b/tests/acceptance/test_accounting_oracle_negative.py @@ -34,9 +34,7 @@ def chain_time_with_offset(offset: int) -> int: return chain.time() + offset -def test_sender_not_allowed( - accounting_oracle: Contract, oracle_version: int, stranger: Account -) -> None: +def test_sender_not_allowed(accounting_oracle: Contract, oracle_version: int, stranger: Account) -> None: report = oracle_report(dry_run=True) with reverts(encode_error("SenderNotAllowed()")): @@ -46,22 +44,16 @@ def test_sender_not_allowed( accounting_oracle.submitReportExtraDataList(b"", {"from": stranger}) with reverts(encode_error("SenderNotAllowed()")): - accounting_oracle.submitReportData( - report.items, oracle_version, {"from": stranger} - ) + accounting_oracle.submitReportData(report.items, oracle_version, {"from": stranger}) with reverts(encode_error("SenderIsNotTheConsensusContract()")): - accounting_oracle.submitConsensusReport( - report.hash, report.refSlot, chain.time(), {"from": stranger} - ) + accounting_oracle.submitConsensusReport(report.hash, report.refSlot, chain.time(), {"from": stranger}) with reverts(encode_error("SenderIsNotTheConsensusContract()")): accounting_oracle.discardConsensusReport(report.refSlot, {"from": stranger}) -def test_submitConsensusReport( - accounting_oracle: Contract, hash_consensus: Contract -) -> None: +def test_submitConsensusReport(accounting_oracle: Contract, hash_consensus: Contract) -> None: report_if_processing_not_started(accounting_oracle) last_processing_ref_slot = accounting_oracle.getLastProcessingRefSlot() @@ -109,9 +101,7 @@ def test_submitConsensusReport( ) -def test_discardConsensusReport( - accounting_oracle: Contract, hash_consensus: Contract -) -> None: +def test_discardConsensusReport(accounting_oracle: Contract, hash_consensus: Contract) -> None: report_if_processing_not_started(accounting_oracle) last_processing_ref_slot = accounting_oracle.getLastProcessingRefSlot() @@ -133,9 +123,7 @@ def test_discardConsensusReport( ) -def test_setConsensusVersion( - accounting_oracle: Contract, aragon_agent: Account -) -> None: +def test_setConsensusVersion(accounting_oracle: Contract, aragon_agent: Account) -> None: # There is no role holder after upgrade accounting_oracle.grantRole( accounting_oracle.MANAGE_CONSENSUS_VERSION_ROLE(), @@ -150,9 +138,7 @@ def test_setConsensusVersion( ) -def test_setConsensusContract( - accounting_oracle: Contract, aragon_agent: Account, deployer: Account -) -> None: +def test_setConsensusContract(accounting_oracle: Contract, aragon_agent: Account, deployer: Account) -> None: # There is no role holder after upgrade accounting_oracle.grantRole( accounting_oracle.MANAGE_CONSENSUS_CONTRACT_ROLE(), @@ -205,8 +191,7 @@ def test_setConsensusContract( def test_finalize_upgrade(accounting_oracle: Contract, stranger: Account): - # SRv3: finalizeUpgrade_v4 was removed; the contract is already at version 5, - # so re-calling finalizeUpgrade_v5 reverts on the version bump (5 != 5 + 1) + # re-calling finalizeUpgrade_v5 reverts on the version bump (5 != 5 + 1) with reverts(encode_error("InvalidContractVersionIncrement()")): accounting_oracle.finalizeUpgrade_v5( 1, @@ -235,15 +220,11 @@ def get_nor_operator_exited_keys(self, operator_id: int) -> int: def test_too_short_extra_data_item(self): extra_data = self.build_extra_data( [ - build_extra_data_item( - 0, ItemType.EXTRA_DATA_TYPE_EXITED_VALIDATORS, 2, [2], [2] - )[:36], + build_extra_data_item(0, ItemType.EXTRA_DATA_TYPE_EXITED_VALIDATORS, 2, [2], [2])[:36], ] ) - (_, _, _, _, _, totalExitedValidators, _, _) = ( - contracts.node_operators_registry.getNodeOperatorSummary(2) - ) + (_, _, _, _, _, totalExitedValidators, _, _) = contracts.node_operators_registry.getNodeOperatorSummary(2) with reverts(encode_error("InvalidExtraDataItem(uint256)", [0])): self.report(extra_data) @@ -272,9 +253,7 @@ def test_too_short_extra_data_item(self): def test_nos_count_zero(self): extra_data = self.build_extra_data( [ - build_extra_data_item( - 0, ItemType.EXTRA_DATA_TYPE_EXITED_VALIDATORS, 2, [], [1] - ), + build_extra_data_item(0, ItemType.EXTRA_DATA_TYPE_EXITED_VALIDATORS, 2, [], [1]), ] ) @@ -284,12 +263,8 @@ def test_nos_count_zero(self): def test_module_id_zero(self): extra_data = self.build_extra_data( [ - build_extra_data_item( - 0, ItemType.EXTRA_DATA_TYPE_EXITED_VALIDATORS, 0, [2], [1] - ), - build_extra_data_item( - 1, ItemType.EXTRA_DATA_TYPE_EXITED_VALIDATORS, 0, [2], [2] - ), + build_extra_data_item(0, ItemType.EXTRA_DATA_TYPE_EXITED_VALIDATORS, 0, [2], [1]), + build_extra_data_item(1, ItemType.EXTRA_DATA_TYPE_EXITED_VALIDATORS, 0, [2], [2]), ] ) @@ -299,12 +274,8 @@ def test_module_id_zero(self): def test_unexpected_extra_data_index(self): extra_data = self.build_extra_data( [ - build_extra_data_item( - 1, ItemType.EXTRA_DATA_TYPE_EXITED_VALIDATORS, 1, [2], [1] - ), - build_extra_data_item( - 2, ItemType.EXTRA_DATA_TYPE_EXITED_VALIDATORS, 2, [2], [1] - ), + build_extra_data_item(1, ItemType.EXTRA_DATA_TYPE_EXITED_VALIDATORS, 1, [2], [1]), + build_extra_data_item(2, ItemType.EXTRA_DATA_TYPE_EXITED_VALIDATORS, 2, [2], [1]), ] ) @@ -360,9 +331,7 @@ def test_unexpected_extra_data_index(self): self.report(extra_data) def test_unsupported_extra_data_type(self): - extra_data = self.build_extra_data( - [build_extra_data_item(0, ItemType.UNSUPPORTED, 1, [1], [1])] - ) + extra_data = self.build_extra_data([build_extra_data_item(0, ItemType.UNSUPPORTED, 1, [1], [1])]) with reverts( encode_error( @@ -430,10 +399,7 @@ def test_invalid_extra_data_sort_order_on_same_operator(self): def test_invalid_extra_data_sort_order_on_exited(self): module_id = 1 unsorted_operator_ids = [33, 35, 34] - current_exited_keys = [ - self.get_nor_operator_exited_keys(operator_id) - for operator_id in unsorted_operator_ids - ] + current_exited_keys = [self.get_nor_operator_exited_keys(operator_id) for operator_id in unsorted_operator_ids] new_exited_keys = [keys + 1 for keys in current_exited_keys] extra_data = self.build_extra_data( @@ -451,9 +417,7 @@ def test_invalid_extra_data_sort_order_on_exited(self): with reverts(encode_error("InvalidExtraDataSortOrder(uint256)", [0])): self.report(extra_data) - def test_unexpected_extra_data_item( - self, extra_data_service: ExtraDataService - ) -> None: + def test_unexpected_extra_data_item(self, extra_data_service: ExtraDataService) -> None: extra_data = extra_data_service.collect( { (1, 2): self.get_nor_operator_exited_keys(2) + 1, @@ -797,9 +761,7 @@ def hash_consensus() -> Contract: @pytest.fixture(scope="module") -def push_report( - accounting_oracle: Contract, hash_consensus: Contract -) -> Callable[[AccountingReport], int]: +def push_report(accounting_oracle: Contract, hash_consensus: Contract) -> Callable[[AccountingReport], int]: def wrapped(report: AccountingReport) -> int: deadline = chain.time() + 100 accounting_oracle.submitConsensusReport( @@ -814,9 +776,7 @@ def wrapped(report: AccountingReport) -> int: @pytest.fixture(scope="module") -def submit_main_data( - accounting_oracle: Contract, consensus_member: Account -) -> Callable[[AccountingReport], None]: +def submit_main_data(accounting_oracle: Contract, consensus_member: Account) -> Callable[[AccountingReport], None]: def wrapped(report: AccountingReport) -> None: accounting_oracle.submitReportData( report.items, @@ -852,11 +812,7 @@ def build_extra_data_item( type_.value.to_bytes(FIELDS_WIDTH.ITEM_TYPE, **opts), module_id.to_bytes(FIELDS_WIDTH.MODULE_ID, **opts), len(nos_ids).to_bytes(FIELDS_WIDTH.NODE_OPS_COUNT, **opts), - b"".join( - i.to_bytes(FIELDS_WIDTH.NODE_OPERATOR_IDS, **opts) for i in nos_ids - ), - b"".join( - i.to_bytes(FIELDS_WIDTH.EXITED_VALS_COUNT, **opts) for i in vals_count - ), + b"".join(i.to_bytes(FIELDS_WIDTH.NODE_OPERATOR_IDS, **opts) for i in nos_ids), + b"".join(i.to_bytes(FIELDS_WIDTH.EXITED_VALS_COUNT, **opts) for i in vals_count), ) ) diff --git a/tests/acceptance/test_circuit_breaker_acceptance.py b/tests/acceptance/test_circuit_breaker_acceptance.py index 420ffcae..6f844246 100644 --- a/tests/acceptance/test_circuit_breaker_acceptance.py +++ b/tests/acceptance/test_circuit_breaker_acceptance.py @@ -4,22 +4,32 @@ from utils.config import ( AGENT, CIRCUIT_BREAKER, + CIRCUIT_BREAKER_COMMITTEE, CIRCUIT_BREAKER_HEARTBEAT_INTERVAL, CIRCUIT_BREAKER_MAX_HEARTBEAT_INTERVAL, CIRCUIT_BREAKER_MAX_PAUSE_DURATION, CIRCUIT_BREAKER_MIN_HEARTBEAT_INTERVAL, CIRCUIT_BREAKER_MIN_PAUSE_DURATION, CIRCUIT_BREAKER_PAUSE_DURATION, + CONSOLIDATION_GATEWAY, CS_ACCOUNTING_ADDRESS, CS_EJECTOR_ADDRESS, CS_FEE_ORACLE_ADDRESS, - CS_VERIFIER_V2_ADDRESS, + CS_IDENTIFIED_DVT_CLUSTER_GATE_ADDRESS, + CS_VERIFIER_ADDRESS, CS_VETTED_GATE_ADDRESS, CSM_ADDRESS, CSM_COMMITTEE_MS, + CURATED_V2_ACCOUNTING, + CURATED_V2_CIRCUIT_BREAKER_PAUSER, + CURATED_V2_EJECTOR, + CURATED_V2_FEE_ORACLE, + CURATED_V2_STAKING_MODULE_ADDRESS, + CURATED_V2_VERIFIER, GATE_SEAL_COMMITTEE, PREDEPOSIT_GUARANTEE, RESEAL_MANAGER, + TOP_UP_GATEWAY, TRIGGERABLE_WITHDRAWALS_GATEWAY, VALIDATORS_EXIT_BUS_ORACLE, VAULT_HUB, @@ -33,12 +43,20 @@ (TRIGGERABLE_WITHDRAWALS_GATEWAY, GATE_SEAL_COMMITTEE), (VAULT_HUB, GATE_SEAL_COMMITTEE), (PREDEPOSIT_GUARANTEE, GATE_SEAL_COMMITTEE), + (CONSOLIDATION_GATEWAY, CIRCUIT_BREAKER_COMMITTEE), + (TOP_UP_GATEWAY, CIRCUIT_BREAKER_COMMITTEE), (CSM_ADDRESS, CSM_COMMITTEE_MS), (CS_ACCOUNTING_ADDRESS, CSM_COMMITTEE_MS), (CS_FEE_ORACLE_ADDRESS, CSM_COMMITTEE_MS), - (CS_VERIFIER_V2_ADDRESS, CSM_COMMITTEE_MS), + (CS_VERIFIER_ADDRESS, CSM_COMMITTEE_MS), (CS_VETTED_GATE_ADDRESS, CSM_COMMITTEE_MS), (CS_EJECTOR_ADDRESS, CSM_COMMITTEE_MS), + (CS_IDENTIFIED_DVT_CLUSTER_GATE_ADDRESS, CSM_COMMITTEE_MS), + (CURATED_V2_STAKING_MODULE_ADDRESS, CURATED_V2_CIRCUIT_BREAKER_PAUSER), + (CURATED_V2_ACCOUNTING, CURATED_V2_CIRCUIT_BREAKER_PAUSER), + (CURATED_V2_FEE_ORACLE, CURATED_V2_CIRCUIT_BREAKER_PAUSER), + (CURATED_V2_VERIFIER, CURATED_V2_CIRCUIT_BREAKER_PAUSER), + (CURATED_V2_EJECTOR, CURATED_V2_CIRCUIT_BREAKER_PAUSER), ] @@ -48,36 +66,41 @@ def circuit_breaker(): def test_initial_values(circuit_breaker): - assert circuit_breaker.ADMIN() == AGENT, ( - f"ADMIN: expected {AGENT}, got {circuit_breaker.ADMIN()}" - ) - - assert circuit_breaker.MIN_PAUSE_DURATION() == CIRCUIT_BREAKER_MIN_PAUSE_DURATION, ( - f"MIN_PAUSE_DURATION: expected {CIRCUIT_BREAKER_MIN_PAUSE_DURATION}, got {circuit_breaker.MIN_PAUSE_DURATION()}" - ) - assert circuit_breaker.MAX_PAUSE_DURATION() == CIRCUIT_BREAKER_MAX_PAUSE_DURATION, ( - f"MAX_PAUSE_DURATION: expected {CIRCUIT_BREAKER_MAX_PAUSE_DURATION}, got {circuit_breaker.MAX_PAUSE_DURATION()}" - ) - assert circuit_breaker.MIN_HEARTBEAT_INTERVAL() == CIRCUIT_BREAKER_MIN_HEARTBEAT_INTERVAL, ( - f"MIN_HEARTBEAT_INTERVAL: expected {CIRCUIT_BREAKER_MIN_HEARTBEAT_INTERVAL}, got {circuit_breaker.MIN_HEARTBEAT_INTERVAL()}" - ) - assert circuit_breaker.MAX_HEARTBEAT_INTERVAL() == CIRCUIT_BREAKER_MAX_HEARTBEAT_INTERVAL, ( - f"MAX_HEARTBEAT_INTERVAL: expected {CIRCUIT_BREAKER_MAX_HEARTBEAT_INTERVAL}, got {circuit_breaker.MAX_HEARTBEAT_INTERVAL()}" - ) - assert circuit_breaker.pauseDuration() == CIRCUIT_BREAKER_PAUSE_DURATION, ( - f"pauseDuration: expected {CIRCUIT_BREAKER_PAUSE_DURATION}, got {circuit_breaker.pauseDuration()}" - ) - assert circuit_breaker.heartbeatInterval() == CIRCUIT_BREAKER_HEARTBEAT_INTERVAL, ( - f"heartbeatInterval: expected {CIRCUIT_BREAKER_HEARTBEAT_INTERVAL}, got {circuit_breaker.heartbeatInterval()}" - ) - - assert 0 < CIRCUIT_BREAKER_MIN_PAUSE_DURATION <= CIRCUIT_BREAKER_PAUSE_DURATION <= CIRCUIT_BREAKER_MAX_PAUSE_DURATION, ( + assert circuit_breaker.ADMIN() == AGENT, f"ADMIN: expected {AGENT}, got {circuit_breaker.ADMIN()}" + + assert ( + circuit_breaker.MIN_PAUSE_DURATION() == CIRCUIT_BREAKER_MIN_PAUSE_DURATION + ), f"MIN_PAUSE_DURATION: expected {CIRCUIT_BREAKER_MIN_PAUSE_DURATION}, got {circuit_breaker.MIN_PAUSE_DURATION()}" + assert ( + circuit_breaker.MAX_PAUSE_DURATION() == CIRCUIT_BREAKER_MAX_PAUSE_DURATION + ), f"MAX_PAUSE_DURATION: expected {CIRCUIT_BREAKER_MAX_PAUSE_DURATION}, got {circuit_breaker.MAX_PAUSE_DURATION()}" + assert ( + circuit_breaker.MIN_HEARTBEAT_INTERVAL() == CIRCUIT_BREAKER_MIN_HEARTBEAT_INTERVAL + ), f"MIN_HEARTBEAT_INTERVAL: expected {CIRCUIT_BREAKER_MIN_HEARTBEAT_INTERVAL}, got {circuit_breaker.MIN_HEARTBEAT_INTERVAL()}" + assert ( + circuit_breaker.MAX_HEARTBEAT_INTERVAL() == CIRCUIT_BREAKER_MAX_HEARTBEAT_INTERVAL + ), f"MAX_HEARTBEAT_INTERVAL: expected {CIRCUIT_BREAKER_MAX_HEARTBEAT_INTERVAL}, got {circuit_breaker.MAX_HEARTBEAT_INTERVAL()}" + assert ( + circuit_breaker.pauseDuration() == CIRCUIT_BREAKER_PAUSE_DURATION + ), f"pauseDuration: expected {CIRCUIT_BREAKER_PAUSE_DURATION}, got {circuit_breaker.pauseDuration()}" + assert ( + circuit_breaker.heartbeatInterval() == CIRCUIT_BREAKER_HEARTBEAT_INTERVAL + ), f"heartbeatInterval: expected {CIRCUIT_BREAKER_HEARTBEAT_INTERVAL}, got {circuit_breaker.heartbeatInterval()}" + + assert ( + 0 < CIRCUIT_BREAKER_MIN_PAUSE_DURATION <= CIRCUIT_BREAKER_PAUSE_DURATION <= CIRCUIT_BREAKER_MAX_PAUSE_DURATION + ), ( f"pause duration bounds broken: " f"min={CIRCUIT_BREAKER_MIN_PAUSE_DURATION}, " f"initial={CIRCUIT_BREAKER_PAUSE_DURATION}, " f"max={CIRCUIT_BREAKER_MAX_PAUSE_DURATION}" ) - assert 0 < CIRCUIT_BREAKER_MIN_HEARTBEAT_INTERVAL <= CIRCUIT_BREAKER_HEARTBEAT_INTERVAL <= CIRCUIT_BREAKER_MAX_HEARTBEAT_INTERVAL, ( + assert ( + 0 + < CIRCUIT_BREAKER_MIN_HEARTBEAT_INTERVAL + <= CIRCUIT_BREAKER_HEARTBEAT_INTERVAL + <= CIRCUIT_BREAKER_MAX_HEARTBEAT_INTERVAL + ), ( f"heartbeat interval bounds broken: " f"min={CIRCUIT_BREAKER_MIN_HEARTBEAT_INTERVAL}, " f"initial={CIRCUIT_BREAKER_HEARTBEAT_INTERVAL}, " @@ -96,9 +119,9 @@ def test_pausables_set(circuit_breaker): @pytest.mark.parametrize("pausable, expected_pauser", EXPECTED_PAUSABLES) def test_pauser_assignment(circuit_breaker, pausable, expected_pauser): - assert circuit_breaker.getPauser(pausable).lower() == expected_pauser.lower(), ( - f"pauser for {pausable}: expected {expected_pauser}, got {circuit_breaker.getPauser(pausable)}" - ) + assert ( + circuit_breaker.getPauser(pausable).lower() == expected_pauser.lower() + ), f"pauser for {pausable}: expected {expected_pauser}, got {circuit_breaker.getPauser(pausable)}" def test_pausable_counts_per_pauser(circuit_breaker): @@ -107,38 +130,38 @@ def test_pausable_counts_per_pauser(circuit_breaker): expected_counts[pauser.lower()] = expected_counts.get(pauser.lower(), 0) + 1 for pauser, expected in expected_counts.items(): - assert circuit_breaker.getPausableCount(pauser) == expected, ( - f"pausable count for pauser {pauser}: expected {expected}, got {circuit_breaker.getPausableCount(pauser)}" - ) + assert ( + circuit_breaker.getPausableCount(pauser) == expected + ), f"pausable count for pauser {pauser}: expected {expected}, got {circuit_breaker.getPausableCount(pauser)}" @pytest.mark.parametrize("pausable, _pauser", EXPECTED_PAUSABLES) def test_pause_role_holders(_pauser, pausable): pausable_contract = interface.IPausableUntilWithRoles(pausable) pause_role = str(pausable_contract.PAUSE_ROLE()) - assert pausable_contract.getRoleMemberCount(pause_role) == 2, ( - f"PAUSE_ROLE holder count on {pausable}: expected 2, got {pausable_contract.getRoleMemberCount(pause_role)}" - ) + assert ( + pausable_contract.getRoleMemberCount(pause_role) == 2 + ), f"PAUSE_ROLE holder count on {pausable}: expected 2, got {pausable_contract.getRoleMemberCount(pause_role)}" holders = { pausable_contract.getRoleMember(pause_role, 0).lower(), pausable_contract.getRoleMember(pause_role, 1).lower(), } expected_holders = {CIRCUIT_BREAKER.lower(), RESEAL_MANAGER.lower()} - assert holders == expected_holders, ( - f"PAUSE_ROLE holders on {pausable}: expected {sorted(expected_holders)}, got {sorted(holders)}" - ) + assert ( + holders == expected_holders + ), f"PAUSE_ROLE holders on {pausable}: expected {sorted(expected_holders)}, got {sorted(holders)}" @pytest.mark.parametrize("pausable, _pauser", EXPECTED_PAUSABLES) def test_resume_role_holder(_pauser, pausable): pausable_contract = interface.IPausableUntilWithRoles(pausable) resume_role = str(pausable_contract.RESUME_ROLE()) - assert pausable_contract.getRoleMemberCount(resume_role) == 1, ( - f"RESUME_ROLE holder count on {pausable}: expected 1, got {pausable_contract.getRoleMemberCount(resume_role)}" - ) - assert pausable_contract.getRoleMember(resume_role, 0).lower() == RESEAL_MANAGER.lower(), ( - f"RESUME_ROLE holder on {pausable}: expected {RESEAL_MANAGER}, got {pausable_contract.getRoleMember(resume_role, 0)}" - ) + assert ( + pausable_contract.getRoleMemberCount(resume_role) == 1 + ), f"RESUME_ROLE holder count on {pausable}: expected 1, got {pausable_contract.getRoleMemberCount(resume_role)}" + assert ( + pausable_contract.getRoleMember(resume_role, 0).lower() == RESEAL_MANAGER.lower() + ), f"RESUME_ROLE holder on {pausable}: expected {RESEAL_MANAGER}, got {pausable_contract.getRoleMember(resume_role, 0)}" @pytest.mark.parametrize("pauser", sorted({p for _, p in EXPECTED_PAUSABLES})) @@ -146,6 +169,6 @@ def test_pauser_is_live(circuit_breaker, pauser): assert circuit_breaker.isPauserLive(pauser), f"pauser {pauser} not live" expiry = circuit_breaker.heartbeatExpiry(pauser) block_timestamp = web3.eth.get_block("latest")["timestamp"] - assert expiry > block_timestamp, ( - f"pauser {pauser} heartbeat expired: expiry={expiry}, block.timestamp={block_timestamp}" - ) + assert ( + expiry > block_timestamp + ), f"pauser {pauser} heartbeat expired: expiry={expiry}, block.timestamp={block_timestamp}" diff --git a/tests/acceptance/test_consolidation.py b/tests/acceptance/test_consolidation.py index 4eb2353e..cf55c9c7 100644 --- a/tests/acceptance/test_consolidation.py +++ b/tests/acceptance/test_consolidation.py @@ -1,16 +1,3 @@ -""" -Acceptance tests for the consolidation pipeline added by the SRv3 upgrade: - -- ConsolidationGateway — entry point for consolidation requests; deployed directly - (no proxy), admin and limits are set in the constructor; wired into the upgraded - LidoLocator; the vote registers a CircuitBreaker pauser for it (item 1.18). -- ConsolidationBus (OssifiableProxy) — queue/batch layer between the migrator and - the gateway. -- ConsolidationMigrator (OssifiableProxy) — migrates Curated (module id 1) - validators into Curated Module v2 (id 4); pairs are allowed via the EasyTrack - AllowConsolidationPair factory and disallowed by the CMC committee. -""" - import pytest from brownie import interface, reverts, web3 # type: ignore from brownie.convert.datatypes import HexString From 9315d3600d461cbe416534005d7ae6c342608e5a Mon Sep 17 00:00:00 2001 From: KRogLA Date: Thu, 9 Jul 2026 15:15:38 +0200 Subject: [PATCH 03/30] fix: add new interfaces --- interfaces/IValidatorStrikesV3.json | 28 + interfaces/OneShotCurveSetup.json | 505 +++++++++++ interfaces/UpgradeConfig.json | 1156 +++++++++++++++++++++++++ interfaces/UpgradeTemplate.json | 1211 +++++++++++++++++++++++++++ interfaces/UpgradeVoteScript.json | 5 + 5 files changed, 2905 insertions(+) create mode 100644 interfaces/IValidatorStrikesV3.json create mode 100644 interfaces/OneShotCurveSetup.json create mode 100644 interfaces/UpgradeConfig.json create mode 100644 interfaces/UpgradeTemplate.json diff --git a/interfaces/IValidatorStrikesV3.json b/interfaces/IValidatorStrikesV3.json new file mode 100644 index 00000000..0bad3888 --- /dev/null +++ b/interfaces/IValidatorStrikesV3.json @@ -0,0 +1,28 @@ +[ + { + "inputs": [], + "name": "ejector", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newEjector", + "type": "address" + } + ], + "name": "setEjector", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/interfaces/OneShotCurveSetup.json b/interfaces/OneShotCurveSetup.json new file mode 100644 index 00000000..83f62e94 --- /dev/null +++ b/interfaces/OneShotCurveSetup.json @@ -0,0 +1,505 @@ +[ + { + "type": "constructor", + "inputs": [ + { "name": "accounting_", "type": "address", "internalType": "address" }, + { "name": "registry_", "type": "address", "internalType": "address" }, + { + "name": "params", + "type": "tuple", + "internalType": "struct IOneShotCurveSetup.ConstructorParams", + "components": [ + { + "name": "bondCurve", + "type": "tuple[]", + "internalType": "struct IBondCurve.BondCurveIntervalInput[]", + "components": [ + { + "name": "minKeysCount", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "trend", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "name": "keyRemovalCharge", + "type": "tuple", + "internalType": "struct IOneShotCurveSetup.ScalarOverride", + "components": [ + { "name": "isSet", "type": "bool", "internalType": "bool" }, + { + "name": "value", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "name": "generalDelayedPenaltyFine", + "type": "tuple", + "internalType": "struct IOneShotCurveSetup.ScalarOverride", + "components": [ + { "name": "isSet", "type": "bool", "internalType": "bool" }, + { + "name": "value", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "name": "keysLimit", + "type": "tuple", + "internalType": "struct IOneShotCurveSetup.ScalarOverride", + "components": [ + { "name": "isSet", "type": "bool", "internalType": "bool" }, + { + "name": "value", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "name": "queueConfig", + "type": "tuple", + "internalType": "struct IOneShotCurveSetup.QueueConfigOverride", + "components": [ + { "name": "isSet", "type": "bool", "internalType": "bool" }, + { + "name": "priority", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "maxDeposits", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "name": "rewardShareData", + "type": "tuple", + "internalType": "struct IOneShotCurveSetup.KeyNumberValueIntervalsOverride", + "components": [ + { "name": "isSet", "type": "bool", "internalType": "bool" }, + { + "name": "data", + "type": "tuple[]", + "internalType": "struct IParametersRegistry.KeyNumberValueInterval[]", + "components": [ + { + "name": "minKeyNumber", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "value", + "type": "uint256", + "internalType": "uint256" + } + ] + } + ] + }, + { + "name": "performanceLeewayData", + "type": "tuple", + "internalType": "struct IOneShotCurveSetup.KeyNumberValueIntervalsOverride", + "components": [ + { "name": "isSet", "type": "bool", "internalType": "bool" }, + { + "name": "data", + "type": "tuple[]", + "internalType": "struct IParametersRegistry.KeyNumberValueInterval[]", + "components": [ + { + "name": "minKeyNumber", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "value", + "type": "uint256", + "internalType": "uint256" + } + ] + } + ] + }, + { + "name": "strikesParams", + "type": "tuple", + "internalType": "struct IOneShotCurveSetup.StrikesOverride", + "components": [ + { "name": "isSet", "type": "bool", "internalType": "bool" }, + { + "name": "lifetime", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "threshold", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "name": "badPerformancePenalty", + "type": "tuple", + "internalType": "struct IOneShotCurveSetup.ScalarOverride", + "components": [ + { "name": "isSet", "type": "bool", "internalType": "bool" }, + { + "name": "value", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "name": "performanceCoefficients", + "type": "tuple", + "internalType": "struct IOneShotCurveSetup.PerformanceCoefficientsOverride", + "components": [ + { "name": "isSet", "type": "bool", "internalType": "bool" }, + { + "name": "attestationsWeight", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "blocksWeight", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "syncWeight", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "name": "allowedExitDelay", + "type": "tuple", + "internalType": "struct IOneShotCurveSetup.ScalarOverride", + "components": [ + { "name": "isSet", "type": "bool", "internalType": "bool" }, + { + "name": "value", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "name": "exitDelayFee", + "type": "tuple", + "internalType": "struct IOneShotCurveSetup.ScalarOverride", + "components": [ + { "name": "isSet", "type": "bool", "internalType": "bool" }, + { + "name": "value", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "name": "maxElWithdrawalRequestFee", + "type": "tuple", + "internalType": "struct IOneShotCurveSetup.ScalarOverride", + "components": [ + { "name": "isSet", "type": "bool", "internalType": "bool" }, + { + "name": "value", + "type": "uint256", + "internalType": "uint256" + } + ] + } + ] + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "ACCOUNTING", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "contract IAccounting" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "REGISTRY", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "contract IParametersRegistry" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "allowedExitDelayOverride", + "inputs": [], + "outputs": [ + { "name": "isSet", "type": "bool", "internalType": "bool" }, + { "name": "value", "type": "uint256", "internalType": "uint256" } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "badPerformancePenaltyOverride", + "inputs": [], + "outputs": [ + { "name": "isSet", "type": "bool", "internalType": "bool" }, + { "name": "value", "type": "uint256", "internalType": "uint256" } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "bondCurve", + "inputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], + "outputs": [ + { + "name": "minKeysCount", + "type": "uint256", + "internalType": "uint256" + }, + { "name": "trend", "type": "uint256", "internalType": "uint256" } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "deployedCurveId", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], + "stateMutability": "view" + }, + { + "type": "function", + "name": "execute", + "inputs": [], + "outputs": [ + { "name": "curveId", "type": "uint256", "internalType": "uint256" } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "executed", + "inputs": [], + "outputs": [{ "name": "", "type": "bool", "internalType": "bool" }], + "stateMutability": "view" + }, + { + "type": "function", + "name": "exitDelayFeeOverride", + "inputs": [], + "outputs": [ + { "name": "isSet", "type": "bool", "internalType": "bool" }, + { "name": "value", "type": "uint256", "internalType": "uint256" } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "generalDelayedPenaltyFineOverride", + "inputs": [], + "outputs": [ + { "name": "isSet", "type": "bool", "internalType": "bool" }, + { "name": "value", "type": "uint256", "internalType": "uint256" } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getBondCurve", + "inputs": [], + "outputs": [ + { + "name": "bondCurve_", + "type": "tuple[]", + "internalType": "struct IBondCurve.BondCurveIntervalInput[]", + "components": [ + { + "name": "minKeysCount", + "type": "uint256", + "internalType": "uint256" + }, + { "name": "trend", "type": "uint256", "internalType": "uint256" } + ] + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getPerformanceLeewayDataOverride", + "inputs": [], + "outputs": [ + { "name": "isSet", "type": "bool", "internalType": "bool" }, + { + "name": "data", + "type": "tuple[]", + "internalType": "struct IParametersRegistry.KeyNumberValueInterval[]", + "components": [ + { + "name": "minKeyNumber", + "type": "uint256", + "internalType": "uint256" + }, + { "name": "value", "type": "uint256", "internalType": "uint256" } + ] + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getRewardShareDataOverride", + "inputs": [], + "outputs": [ + { "name": "isSet", "type": "bool", "internalType": "bool" }, + { + "name": "data", + "type": "tuple[]", + "internalType": "struct IParametersRegistry.KeyNumberValueInterval[]", + "components": [ + { + "name": "minKeyNumber", + "type": "uint256", + "internalType": "uint256" + }, + { "name": "value", "type": "uint256", "internalType": "uint256" } + ] + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "keyRemovalChargeOverride", + "inputs": [], + "outputs": [ + { "name": "isSet", "type": "bool", "internalType": "bool" }, + { "name": "value", "type": "uint256", "internalType": "uint256" } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "keysLimitOverride", + "inputs": [], + "outputs": [ + { "name": "isSet", "type": "bool", "internalType": "bool" }, + { "name": "value", "type": "uint256", "internalType": "uint256" } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "maxElWithdrawalRequestFeeOverride", + "inputs": [], + "outputs": [ + { "name": "isSet", "type": "bool", "internalType": "bool" }, + { "name": "value", "type": "uint256", "internalType": "uint256" } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "performanceCoefficientsOverride", + "inputs": [], + "outputs": [ + { "name": "isSet", "type": "bool", "internalType": "bool" }, + { + "name": "attestationsWeight", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "blocksWeight", + "type": "uint256", + "internalType": "uint256" + }, + { "name": "syncWeight", "type": "uint256", "internalType": "uint256" } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "performanceLeewayDataOverride", + "inputs": [], + "outputs": [{ "name": "isSet", "type": "bool", "internalType": "bool" }], + "stateMutability": "view" + }, + { + "type": "function", + "name": "queueConfigOverride", + "inputs": [], + "outputs": [ + { "name": "isSet", "type": "bool", "internalType": "bool" }, + { "name": "priority", "type": "uint256", "internalType": "uint256" }, + { "name": "maxDeposits", "type": "uint256", "internalType": "uint256" } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "rewardShareDataOverride", + "inputs": [], + "outputs": [{ "name": "isSet", "type": "bool", "internalType": "bool" }], + "stateMutability": "view" + }, + { + "type": "function", + "name": "strikesParamsOverride", + "inputs": [], + "outputs": [ + { "name": "isSet", "type": "bool", "internalType": "bool" }, + { "name": "lifetime", "type": "uint256", "internalType": "uint256" }, + { "name": "threshold", "type": "uint256", "internalType": "uint256" } + ], + "stateMutability": "view" + }, + { + "type": "event", + "name": "BondCurveDeployed", + "inputs": [ + { + "name": "curveId", + "type": "uint256", + "indexed": true, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { "type": "error", "name": "AlreadyExecuted", "inputs": [] }, + { "type": "error", "name": "EmptyBondCurve", "inputs": [] }, + { "type": "error", "name": "ZeroAccountingAddress", "inputs": [] }, + { "type": "error", "name": "ZeroRegistryAddress", "inputs": [] } +] diff --git a/interfaces/UpgradeConfig.json b/interfaces/UpgradeConfig.json new file mode 100644 index 00000000..cb9efb61 --- /dev/null +++ b/interfaces/UpgradeConfig.json @@ -0,0 +1,1156 @@ +[ + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "locator", + "type": "address" + }, + { + "internalType": "address", + "name": "agent", + "type": "address" + }, + { + "internalType": "address", + "name": "voting", + "type": "address" + }, + { + "internalType": "address", + "name": "dualGovernance", + "type": "address" + }, + { + "internalType": "address", + "name": "circuitBreaker", + "type": "address" + }, + { + "internalType": "address", + "name": "circuitBreakerCommittee", + "type": "address" + }, + { + "internalType": "address", + "name": "easyTrack", + "type": "address" + }, + { + "components": [ + { + "internalType": "address", + "name": "UpdateStakingModuleShareLimits", + "type": "address" + }, + { + "internalType": "address", + "name": "AllowConsolidationPair", + "type": "address" + }, + { + "internalType": "address", + "name": "SetMerkleGateTreeForCSM", + "type": "address" + }, + { + "internalType": "address", + "name": "ReportWithdrawalsForSlashedValidatorsForCSM", + "type": "address" + }, + { + "internalType": "address", + "name": "SettleGeneralDelayedPenaltyForCSM", + "type": "address" + }, + { + "internalType": "address", + "name": "SetMerkleGateTreeForCM", + "type": "address" + }, + { + "internalType": "address", + "name": "ReportWithdrawalsForSlashedValidatorsForCM", + "type": "address" + }, + { + "internalType": "address", + "name": "SettleGeneralDelayedPenaltyForCM", + "type": "address" + }, + { + "internalType": "address", + "name": "CreateOrUpdateOperatorGroupForCM", + "type": "address" + } + ], + "internalType": "struct EasyTrackNewFactories", + "name": "newFactories", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "address", + "name": "CSMSettleElStealingPenalty", + "type": "address" + }, + { + "internalType": "address", + "name": "CSMSetVettedGateTree", + "type": "address" + } + ], + "internalType": "struct EasyTrackOldFactories", + "name": "oldFactories", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "address", + "name": "newLocatorImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "newLidoImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "newAccountingImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "newAccountingOracleImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "newStakingRouterImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "newWithdrawalVaultImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "newValidatorsExitBusOracleImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "consolidationBusImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "consolidationMigratorImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "topUpGatewayImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "consolidationBus", + "type": "address" + }, + { + "internalType": "address", + "name": "consolidationMigrator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "lidoDepositsReserveTarget", + "type": "uint256" + }, + { + "internalType": "address", + "name": "consolidationCommittee", + "type": "address" + }, + { + "internalType": "address", + "name": "topUpGatewayDepositor", + "type": "address" + }, + { + "internalType": "uint256", + "name": "twMaxExitRequestsLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "twExitsPerFrame", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "twFrameDurationInSec", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "aoConsensusVersion", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "veboMaxValidatorsPerReport", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "veboMaxExitBalanceEth", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "veboBalancePerFrameEth", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "veboFrameDurationInSec", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "veboConsensusVersion", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxTopUpPerBlockGwei", + "type": "uint256" + } + ], + "internalType": "struct CoreUpgradeParams", + "name": "coreUpgrade", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "address", + "name": "csmProxy", + "type": "address" + }, + { + "internalType": "address", + "name": "csmImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "vettedGateProxy", + "type": "address" + }, + { + "internalType": "address", + "name": "identifiedDVTClusterGate", + "type": "address" + }, + { + "internalType": "address", + "name": "identifiedDVTClusterCurveSetup", + "type": "address" + }, + { + "internalType": "uint256", + "name": "identifiedDVTClusterBondCurveId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "parametersRegistryImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "feeOracleImpl", + "type": "address" + }, + { + "internalType": "uint256", + "name": "feeOracleConsensusVersion", + "type": "uint256" + }, + { + "internalType": "address", + "name": "vettedGateImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "accountingImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "feeDistributorImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "exitPenaltiesImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "strikesImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "oldPermissionlessGate", + "type": "address" + }, + { + "internalType": "address", + "name": "newPermissionlessGate", + "type": "address" + }, + { + "internalType": "address", + "name": "oldVerifier", + "type": "address" + }, + { + "internalType": "address", + "name": "newVerifier", + "type": "address" + }, + { + "internalType": "address", + "name": "newEjector", + "type": "address" + }, + { + "internalType": "address", + "name": "csmCommittee", + "type": "address" + } + ], + "internalType": "struct CSMUpgradeParams", + "name": "csmUpgrade", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "address", + "name": "module", + "type": "address" + }, + { + "internalType": "address[]", + "name": "curatedGates", + "type": "address[]" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "address", + "name": "circuitBreakerPauser", + "type": "address" + }, + { + "internalType": "string", + "name": "moduleName", + "type": "string" + }, + { + "internalType": "uint256", + "name": "stakeShareLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "priorityExitShareThreshold", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "stakingModuleFee", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "treasuryFee", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxDepositsPerBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minDepositBlockDistance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "feeOracleConsensusVersion", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "hashConsensusInitialEpoch", + "type": "uint256" + } + ], + "internalType": "struct CuratedModuleParams", + "name": "curatedModule", + "type": "tuple" + } + ], + "internalType": "struct UpgradeParameters", + "name": "params", + "type": "tuple" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "StringTooLong", + "type": "error" + }, + { + "inputs": [], + "name": "AGENT", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "BURNER", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CIRCUIT_BREAKER", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CIRCUIT_BREAKER_COMMITTEE", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DUAL_GOVERNANCE", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LOCATOR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "RESEAL_MANAGER", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "VOTING", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCSMUpgradeConfig", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "csm", + "type": "address" + }, + { + "internalType": "address", + "name": "csmImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "parametersRegistry", + "type": "address" + }, + { + "internalType": "address", + "name": "parametersRegistryImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "feeOracle", + "type": "address" + }, + { + "internalType": "address", + "name": "feeOracleImpl", + "type": "address" + }, + { + "internalType": "uint256", + "name": "feeOracleConsensusVersion", + "type": "uint256" + }, + { + "internalType": "address", + "name": "vettedGate", + "type": "address" + }, + { + "internalType": "address", + "name": "vettedGateImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "identifiedDVTClusterGate", + "type": "address" + }, + { + "internalType": "address", + "name": "identifiedDVTClusterCurveSetup", + "type": "address" + }, + { + "internalType": "uint256", + "name": "identifiedDVTClusterBondCurveId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "accounting", + "type": "address" + }, + { + "internalType": "address", + "name": "accountingImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "feeDistributor", + "type": "address" + }, + { + "internalType": "address", + "name": "feeDistributorImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "exitPenalties", + "type": "address" + }, + { + "internalType": "address", + "name": "exitPenaltiesImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "strikes", + "type": "address" + }, + { + "internalType": "address", + "name": "strikesImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "oldPermissionlessGate", + "type": "address" + }, + { + "internalType": "address", + "name": "newPermissionlessGate", + "type": "address" + }, + { + "internalType": "address", + "name": "oldVerifier", + "type": "address" + }, + { + "internalType": "address", + "name": "newVerifier", + "type": "address" + }, + { + "internalType": "address", + "name": "oldEjector", + "type": "address" + }, + { + "internalType": "address", + "name": "newEjector", + "type": "address" + }, + { + "internalType": "address", + "name": "csmCommittee", + "type": "address" + } + ], + "internalType": "struct CSMUpgradeConfig", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCoreUpgradeConfig", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "kernel", + "type": "address" + }, + { + "internalType": "address", + "name": "acl", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "lidoAppId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "locator", + "type": "address" + }, + { + "internalType": "address", + "name": "oldDepositSecurityModule", + "type": "address" + }, + { + "internalType": "address", + "name": "newLocatorImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "newLidoImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "newAccountingImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "newAccountingOracleImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "newStakingRouterImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "newWithdrawalVaultImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "newValidatorsExitBusOracleImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "newOracleReportSanityChecker", + "type": "address" + }, + { + "internalType": "address", + "name": "newDepositSecurityModule", + "type": "address" + }, + { + "internalType": "address", + "name": "consolidationBusImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "consolidationMigratorImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "topUpGatewayImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "accounting", + "type": "address" + }, + { + "internalType": "address", + "name": "accountingOracle", + "type": "address" + }, + { + "internalType": "address", + "name": "validatorsExitBusOracle", + "type": "address" + }, + { + "internalType": "address", + "name": "withdrawalVault", + "type": "address" + }, + { + "internalType": "address", + "name": "consolidationGateway", + "type": "address" + }, + { + "internalType": "address", + "name": "consolidationBus", + "type": "address" + }, + { + "internalType": "address", + "name": "consolidationMigrator", + "type": "address" + }, + { + "internalType": "address", + "name": "topUpGateway", + "type": "address" + }, + { + "internalType": "uint256", + "name": "lidoDepositsReserveTarget", + "type": "uint256" + }, + { + "internalType": "address", + "name": "consolidationCommittee", + "type": "address" + }, + { + "internalType": "address", + "name": "topUpGatewayDepositor", + "type": "address" + }, + { + "internalType": "uint256", + "name": "twMaxExitRequestsLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "twExitsPerFrame", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "twFrameDurationInSec", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "aoConsensusVersion", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "veboMaxValidatorsPerReport", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "veboMaxExitBalanceEth", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "veboBalancePerFrameEth", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "veboFrameDurationInSec", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "veboConsensusVersion", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxTopUpPerBlockGwei", + "type": "uint256" + } + ], + "internalType": "struct CoreUpgradeConfig", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCuratedModuleConfig", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "module", + "type": "address" + }, + { + "internalType": "address[]", + "name": "curatedGates", + "type": "address[]" + }, + { + "internalType": "address", + "name": "parametersRegistry", + "type": "address" + }, + { + "internalType": "address", + "name": "accounting", + "type": "address" + }, + { + "internalType": "address", + "name": "ejector", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "address", + "name": "circuitBreakerPauser", + "type": "address" + }, + { + "internalType": "address", + "name": "feeDistributor", + "type": "address" + }, + { + "internalType": "address", + "name": "feeOracle", + "type": "address" + }, + { + "internalType": "address", + "name": "hashConsensus", + "type": "address" + }, + { + "internalType": "address", + "name": "strikes", + "type": "address" + }, + { + "internalType": "string", + "name": "moduleName", + "type": "string" + }, + { + "internalType": "uint256", + "name": "stakeShareLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "priorityExitShareThreshold", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "stakingModuleFee", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "treasuryFee", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxDepositsPerBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minDepositBlockDistance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "feeOracleConsensusVersion", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "hashConsensusInitialEpoch", + "type": "uint256" + }, + { + "internalType": "address", + "name": "metaRegistry", + "type": "address" + } + ], + "internalType": "struct CuratedModuleConfig", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getEasyTrackConfig", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "UpdateStakingModuleShareLimits", + "type": "address" + }, + { + "internalType": "address", + "name": "AllowConsolidationPair", + "type": "address" + }, + { + "internalType": "address", + "name": "SetMerkleGateTreeForCSM", + "type": "address" + }, + { + "internalType": "address", + "name": "ReportWithdrawalsForSlashedValidatorsForCSM", + "type": "address" + }, + { + "internalType": "address", + "name": "SettleGeneralDelayedPenaltyForCSM", + "type": "address" + }, + { + "internalType": "address", + "name": "SetMerkleGateTreeForCM", + "type": "address" + }, + { + "internalType": "address", + "name": "ReportWithdrawalsForSlashedValidatorsForCM", + "type": "address" + }, + { + "internalType": "address", + "name": "SettleGeneralDelayedPenaltyForCM", + "type": "address" + }, + { + "internalType": "address", + "name": "CreateOrUpdateOperatorGroupForCM", + "type": "address" + } + ], + "internalType": "struct EasyTrackNewFactories", + "name": "", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "address", + "name": "CSMSettleElStealingPenalty", + "type": "address" + }, + { + "internalType": "address", + "name": "CSMSetVettedGateTree", + "type": "address" + } + ], + "internalType": "struct EasyTrackOldFactories", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getGlobalConfig", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "agent", + "type": "address" + }, + { + "internalType": "address", + "name": "lido", + "type": "address" + }, + { + "internalType": "address", + "name": "burner", + "type": "address" + }, + { + "internalType": "address", + "name": "resealManager", + "type": "address" + }, + { + "internalType": "address", + "name": "circuitBreaker", + "type": "address" + }, + { + "internalType": "address", + "name": "circuitBreakerCommittee", + "type": "address" + }, + { + "internalType": "address", + "name": "easyTrack", + "type": "address" + }, + { + "internalType": "address", + "name": "easyTrackEVMScriptExecutor", + "type": "address" + }, + { + "internalType": "address", + "name": "stakingRouter", + "type": "address" + }, + { + "internalType": "address", + "name": "triggerableWithdrawalsGateway", + "type": "address" + } + ], + "internalType": "struct GlobalConfig", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/interfaces/UpgradeTemplate.json b/interfaces/UpgradeTemplate.json new file mode 100644 index 00000000..5a89db07 --- /dev/null +++ b/interfaces/UpgradeTemplate.json @@ -0,0 +1,1211 @@ +[ + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "locator", + "type": "address" + }, + { + "internalType": "address", + "name": "agent", + "type": "address" + }, + { + "internalType": "address", + "name": "voting", + "type": "address" + }, + { + "internalType": "address", + "name": "dualGovernance", + "type": "address" + }, + { + "internalType": "address", + "name": "circuitBreaker", + "type": "address" + }, + { + "internalType": "address", + "name": "circuitBreakerCommittee", + "type": "address" + }, + { + "internalType": "address", + "name": "easyTrack", + "type": "address" + }, + { + "components": [ + { + "internalType": "address", + "name": "UpdateStakingModuleShareLimits", + "type": "address" + }, + { + "internalType": "address", + "name": "AllowConsolidationPair", + "type": "address" + }, + { + "internalType": "address", + "name": "SetMerkleGateTreeForCSM", + "type": "address" + }, + { + "internalType": "address", + "name": "ReportWithdrawalsForSlashedValidatorsForCSM", + "type": "address" + }, + { + "internalType": "address", + "name": "SettleGeneralDelayedPenaltyForCSM", + "type": "address" + }, + { + "internalType": "address", + "name": "SetMerkleGateTreeForCM", + "type": "address" + }, + { + "internalType": "address", + "name": "ReportWithdrawalsForSlashedValidatorsForCM", + "type": "address" + }, + { + "internalType": "address", + "name": "SettleGeneralDelayedPenaltyForCM", + "type": "address" + }, + { + "internalType": "address", + "name": "CreateOrUpdateOperatorGroupForCM", + "type": "address" + } + ], + "internalType": "struct EasyTrackNewFactories", + "name": "newFactories", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "address", + "name": "CSMSettleElStealingPenalty", + "type": "address" + }, + { + "internalType": "address", + "name": "CSMSetVettedGateTree", + "type": "address" + } + ], + "internalType": "struct EasyTrackOldFactories", + "name": "oldFactories", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "address", + "name": "newLocatorImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "newLidoImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "newAccountingImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "newAccountingOracleImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "newStakingRouterImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "newWithdrawalVaultImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "newValidatorsExitBusOracleImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "consolidationBusImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "consolidationMigratorImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "topUpGatewayImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "consolidationBus", + "type": "address" + }, + { + "internalType": "address", + "name": "consolidationMigrator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "lidoDepositsReserveTarget", + "type": "uint256" + }, + { + "internalType": "address", + "name": "consolidationCommittee", + "type": "address" + }, + { + "internalType": "address", + "name": "topUpGatewayDepositor", + "type": "address" + }, + { + "internalType": "uint256", + "name": "twMaxExitRequestsLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "twExitsPerFrame", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "twFrameDurationInSec", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "aoConsensusVersion", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "veboMaxValidatorsPerReport", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "veboMaxExitBalanceEth", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "veboBalancePerFrameEth", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "veboFrameDurationInSec", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "veboConsensusVersion", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxTopUpPerBlockGwei", + "type": "uint256" + } + ], + "internalType": "struct CoreUpgradeParams", + "name": "coreUpgrade", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "address", + "name": "csmProxy", + "type": "address" + }, + { + "internalType": "address", + "name": "csmImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "vettedGateProxy", + "type": "address" + }, + { + "internalType": "address", + "name": "identifiedDVTClusterGate", + "type": "address" + }, + { + "internalType": "address", + "name": "identifiedDVTClusterCurveSetup", + "type": "address" + }, + { + "internalType": "uint256", + "name": "identifiedDVTClusterBondCurveId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "parametersRegistryImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "feeOracleImpl", + "type": "address" + }, + { + "internalType": "uint256", + "name": "feeOracleConsensusVersion", + "type": "uint256" + }, + { + "internalType": "address", + "name": "vettedGateImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "accountingImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "feeDistributorImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "exitPenaltiesImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "strikesImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "oldPermissionlessGate", + "type": "address" + }, + { + "internalType": "address", + "name": "newPermissionlessGate", + "type": "address" + }, + { + "internalType": "address", + "name": "oldVerifier", + "type": "address" + }, + { + "internalType": "address", + "name": "newVerifier", + "type": "address" + }, + { + "internalType": "address", + "name": "newEjector", + "type": "address" + }, + { + "internalType": "address", + "name": "csmCommittee", + "type": "address" + } + ], + "internalType": "struct CSMUpgradeParams", + "name": "csmUpgrade", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "address", + "name": "module", + "type": "address" + }, + { + "internalType": "address[]", + "name": "curatedGates", + "type": "address[]" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "address", + "name": "circuitBreakerPauser", + "type": "address" + }, + { + "internalType": "string", + "name": "moduleName", + "type": "string" + }, + { + "internalType": "uint256", + "name": "stakeShareLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "priorityExitShareThreshold", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "stakingModuleFee", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "treasuryFee", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxDepositsPerBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minDepositBlockDistance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "feeOracleConsensusVersion", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "hashConsensusInitialEpoch", + "type": "uint256" + } + ], + "internalType": "struct CuratedModuleParams", + "name": "curatedModule", + "type": "tuple" + } + ], + "internalType": "struct UpgradeParameters", + "name": "_params", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "_expireSinceInclusive", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "CMModuleIsPaused", + "type": "error" + }, + { + "inputs": [], + "name": "DSMMigrationIncorrectGuardianQuorum", + "type": "error" + }, + { + "inputs": [], + "name": "DSMMigrationIncorrectGuardians", + "type": "error" + }, + { + "inputs": [], + "name": "DSMMigrationIncorrectOwner", + "type": "error" + }, + { + "inputs": [], + "name": "DSMMigrationIncorrectVersion", + "type": "error" + }, + { + "inputs": [], + "name": "Expired", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "curveSetup", + "type": "address" + } + ], + "name": "IdentifiedDVTClusterCurveSetupNotExecuted", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "kernel", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "IncorrectAragonKernelImplementation", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "IncorrectOZAccessControlRoleHolders", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proxy", + "type": "address" + } + ], + "name": "IncorrectProxyAdmin", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proxy", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "IncorrectProxyImplementation", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "pausable", + "type": "address" + }, + { + "internalType": "address", + "name": "actualPauser", + "type": "address" + }, + { + "internalType": "address", + "name": "expectedPauser", + "type": "address" + } + ], + "name": "InvalidCircuitBreakerPauser", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidConsolidationBusAddressInConsolidationMigrator", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidConsolidationGatewayAddressInConsolidationBus", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidConsolidationGatewayAddressInWithdrawalVault", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "actualVersion", + "type": "uint256" + } + ], + "name": "InvalidContractVersion", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "consensus", + "type": "address" + }, + { + "internalType": "uint256", + "name": "actualEpoch", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expectedEpoch", + "type": "uint256" + } + ], + "name": "InvalidHashConsensusInitialEpoch", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "actualCurveId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expectedCurveId", + "type": "uint256" + } + ], + "name": "InvalidIdentifiedDVTClusterCurveId", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "internalType": "uint64", + "name": "actualVersion", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "expectedVersion", + "type": "uint64" + } + ], + "name": "InvalidInitializedContractVersion", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "locatorAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "appAddress", + "type": "address" + } + ], + "name": "InvalidLocatorAppAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "oracle", + "type": "address" + }, + { + "internalType": "uint256", + "name": "actualVersion", + "type": "uint256" + } + ], + "name": "InvalidOracleConsensusVersion", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTriggerableWithdrawalsGatewayInWithdrawalVault", + "type": "error" + }, + { + "inputs": [], + "name": "LidoMigrationIncorrectBeaconBalance", + "type": "error" + }, + { + "inputs": [], + "name": "LidoMigrationIncorrectBufferedEther", + "type": "error" + }, + { + "inputs": [], + "name": "LidoMigrationIncorrectDepositedSinceLastReport", + "type": "error" + }, + { + "inputs": [], + "name": "LidoMigrationIncorrectDepositedValidators", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "holder", + "type": "address" + } + ], + "name": "MissingAragonPermissionHolder", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "holder", + "type": "address" + } + ], + "name": "MissingOZAccessControlRoleHolder", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyAgentCanUpgrade", + "type": "error" + }, + { + "inputs": [], + "name": "SRMigrationIncorrectAddStakingModule", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newModuleId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "targetModuleId", + "type": "uint256" + } + ], + "name": "SRMigrationIncorrectConsolidationMigratorTargetModuleId", + "type": "error" + }, + { + "inputs": [], + "name": "SRMigrationIncorrectModulesCount", + "type": "error" + }, + { + "inputs": [], + "name": "SRMigrationIncorrectWithdrawalCredentials", + "type": "error" + }, + { + "inputs": [], + "name": "StartAlreadyCalledInThisTx", + "type": "error" + }, + { + "inputs": [], + "name": "StartAndFinishMustBeInSameTx", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "holder", + "type": "address" + } + ], + "name": "UnexpectedAragonPermissionHolder", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "actualManager", + "type": "address" + }, + { + "internalType": "address", + "name": "expectedManager", + "type": "address" + } + ], + "name": "UnexpectedAragonPermissionManager", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "holder", + "type": "address" + } + ], + "name": "UnexpectedOZAccessControlRoleHolder", + "type": "error" + }, + { + "inputs": [], + "name": "UpgradeAlreadyFinished", + "type": "error" + }, + { + "inputs": [], + "name": "UpgradeAlreadyStarted", + "type": "error" + }, + { + "anonymous": false, + "inputs": [], + "name": "UpgradeFinished", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "UpgradeStarted", + "type": "event" + }, + { + "inputs": [], + "name": "CONFIG", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "EXPECTED_FINAL_ACCOUNTING_ORACLE_CONSENSUS_VERSION", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "EXPECTED_FINAL_ACCOUNTING_ORACLE_VERSION", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "EXPECTED_FINAL_CM_ACCOUNTING_INITIALIZED_VERSION", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "EXPECTED_FINAL_CM_FEE_DISTRIBUTOR_INITIALIZED_VERSION", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "EXPECTED_FINAL_CM_MODULE_INITIALIZED_VERSION", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "EXPECTED_FINAL_CM_PARAMETERS_REGISTRY_INITIALIZED_VERSION", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "EXPECTED_FINAL_CM_VALIDATOR_STRIKES_INITIALIZED_VERSION", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "EXPECTED_FINAL_COMMUNITY_FEE_ORACLE_VERSION", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "EXPECTED_FINAL_CSM_ACCOUNTING_INITIALIZED_VERSION", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "EXPECTED_FINAL_CSM_FEE_DISTRIBUTOR_INITIALIZED_VERSION", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "EXPECTED_FINAL_CSM_MODULE_INITIALIZED_VERSION", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "EXPECTED_FINAL_CSM_PARAMETERS_REGISTRY_INITIALIZED_VERSION", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "EXPECTED_FINAL_CSM_VALIDATOR_STRIKES_INITIALIZED_VERSION", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "EXPECTED_FINAL_CSM_VETTED_GATE_INITIALIZED_VERSION", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "EXPECTED_FINAL_DSM_VERSION", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "EXPECTED_FINAL_LIDO_VERSION", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "EXPECTED_FINAL_STAKING_ROUTER_VERSION", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "EXPECTED_FINAL_VALIDATORS_EXIT_BUS_ORACLE_CONSENSUS_VERSION", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "EXPECTED_FINAL_VALIDATORS_EXIT_BUS_ORACLE_VERSION", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "EXPECTED_FINAL_WITHDRAWAL_VAULT_VERSION", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "EXPIRE_SINCE_INCLUSIVE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "finishUpgrade", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "isUpgradeFinished", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "startUpgrade", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "upgradeBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/interfaces/UpgradeVoteScript.json b/interfaces/UpgradeVoteScript.json index d712bb32..df172723 100644 --- a/interfaces/UpgradeVoteScript.json +++ b/interfaces/UpgradeVoteScript.json @@ -33,6 +33,11 @@ "name": "InvalidItemsCount", "type": "error" }, + { + "inputs": [], + "name": "InvalidMerkleGateAddress", + "type": "error" + }, { "inputs": [], "name": "CONFIG", From d2e691c0b53aa95a884debde6354b90282f3be88 Mon Sep 17 00:00:00 2001 From: KRogLA Date: Thu, 9 Jul 2026 15:17:50 +0200 Subject: [PATCH 04/30] chore: update srv3 vote items description --- scripts/upgrade_2026_07_15_srv3_cmv2.py | 154 +++++++++++++----------- 1 file changed, 81 insertions(+), 73 deletions(-) diff --git a/scripts/upgrade_2026_07_15_srv3_cmv2.py b/scripts/upgrade_2026_07_15_srv3_cmv2.py index 1e7e365c..686814cb 100644 --- a/scripts/upgrade_2026_07_15_srv3_cmv2.py +++ b/scripts/upgrade_2026_07_15_srv3_cmv2.py @@ -2,90 +2,99 @@ Vote 2026_07_15 1. Submit a Dual Governance proposal to activate Staking Router v3 + Curated Module v2 + Community Staking Module v3 -# ======================== Core ======================== + +# ======================== Start Upgrade ======================== 1.1. Call UpgradeTemplate.startUpgrade + +# ======================== Core ======================== 1.2. Upgrade LidoLocator implementation -1.3. Upgrade and finalize StakingRouter -1.4. Upgrade and finalize AccountingOracle -1.5. Upgrade and finalize ValidatorsExitBusOracle +1.3. Upgrade StakingRouter implementation and call finalizeUpgrade_v4 +1.4. Upgrade AccountingOracle implementation and call finalizeUpgrade_v5 +1.5. Upgrade ValidatorsExitBusOracle implementation and call finalizeUpgrade_v3 1.6. Upgrade Accounting implementation -1.7. Upgrade WithdrawalVault implementation +1.7. Upgrade WithdrawalVault implementation and call finalizeUpgrade_v3 1.8. Grant Aragon APP_MANAGER_ROLE to the AGENT 1.9. Set Lido implementation in Kernel 1.10. Revoke Aragon APP_MANAGER_ROLE from the AGENT -1.11. Create and grant Aragon BUFFER_RESERVE_MANAGER_ROLE to the AGENT +1.11. Create Aragon BUFFER_RESERVE_MANAGER_ROLE and grant role manager to the AGENT 1.12. Call finalizeUpgrade_v4 on Lido -1.13. Grant STAKING_MODULE_SHARE_MANAGE_ROLE to EasyTrack executor -1.14. Revoke STAKING_MODULE_UNVETTING_ROLE from old DSM -1.15. Grant STAKING_MODULE_UNVETTING_ROLE to new DSM -1.16. Grant TW_EXIT_LIMIT_MANAGER_ROLE to Agent on TWGateway -1.17. Set TWGateway exit request limits +1.13. Grant Staking Router STAKING_MODULE_SHARE_MANAGE_ROLE to EasyTrack executor +1.14. Revoke Staking Router STAKING_MODULE_UNVETTING_ROLE from old DSM +1.15. Grant Staking Router STAKING_MODULE_UNVETTING_ROLE to new DSM +1.16. Grant TWG TW_EXIT_LIMIT_MANAGER_ROLE to AGENT +1.17. Set TWG exit request limits 1.18. Register CircuitBreaker pauser for ConsolidationGateway +1.19. Register CircuitBreaker pauser for TopUpGateway + # ======================== CSM ======================== -1.19. Upgrade and finalize CSM v3 -1.20. Upgrade and finalize ParametersRegistry v3 -1.21. Upgrade and finalize FeeOracle v3 -1.22. Upgrade CSVettedGate implementation -1.23. Upgrade and finalize Accounting v3 -1.24. Upgrade and finalize FeeDistributor v3 -1.25. Upgrade ExitPenalties implementation -1.26. Upgrade ValidatorStrikes implementation -1.27. Point ValidatorStrikes to the new Ejector -1.28. Revoke REPORT_EL_REWARDS_STEALING_PENALTY_ROLE -1.29. Grant REPORT_GENERAL_DELAYED_PENALTY_ROLE -1.30. Revoke SETTLE_EL_REWARDS_STEALING_PENALTY_ROLE -1.31. Grant SETTLE_GENERAL_DELAYED_PENALTY_ROLE -1.32. Revoke VERIFIER_ROLE from old verifier -1.33. Grant VERIFIER_ROLE to new verifier -1.34. Grant REPORT_REGULAR_WITHDRAWN_VALIDATORS_ROLE to VerifierV3 -1.35. Grant REPORT_SLASHED_WITHDRAWN_VALIDATORS_ROLE to Easy Track -1.36. Revoke CREATE_NODE_OPERATOR_ROLE from old PermissionlessGate -1.37. Grant CREATE_NODE_OPERATOR_ROLE to new PermissionlessGate -1.38. Revoke START_REFERRAL_SEASON_ROLE -1.39. Revoke END_REFERRAL_SEASON_ROLE -1.40. Register CircuitBreaker pauser for CSM new verifier -1.41. Register CircuitBreaker pauser for CSM Ejector -1.42. Register CircuitBreaker pauser for CSM identified DVT cluster gate -1.43. Grant CREATE_NODE_OPERATOR_ROLE to identified DVT cluster gate -1.44. Grant SET_BOND_CURVE_ROLE to identified DVT cluster gate -1.45. Grant MANAGE_BOND_CURVES_ROLE to identified DVT cluster curve setup -1.46. Grant MANAGE_CURVE_PARAMETERS_ROLE to identified DVT cluster curve setup -1.47. Execute identified DVT cluster curve setup -1.48. Grant MANAGE_GENERAL_PENALTIES_AND_CHARGES_ROLE to CSM Committee -1.49. Revoke REQUEST_BURN_SHARES_ROLE from CSM Accounting -1.50. Grant REQUEST_BURN_MY_STETH_ROLE to CSM Accounting -1.51. Revoke TWG full-withdrawal role from old Ejector -1.52. Grant TWG full-withdrawal role to new Ejector +1.20. Upgrade CSM to v3 and call finalizeUpgradeV3 +1.21. Upgrade CSM ParametersRegistry to v3 and call finalizeUpgradeV3 +1.22. Upgrade CSM FeeOracle to v3 and call finalizeUpgradeV3 +1.23. Upgrade CSM VettedGate implementation +1.24. Upgrade CSM Accounting to v3 and call finalizeUpgradeV3 +1.25. Upgrade CSM FeeDistributor to v3 and call finalizeUpgradeV3 +1.26. Upgrade CSM ExitPenalties implementation +1.27. Upgrade CSM ValidatorStrikes implementation +1.28. Point CSM ValidatorStrikes to the New CSM Ejector +1.29. Revoke CSM REPORT_EL_REWARDS_STEALING_PENALTY_ROLE from CSM Committee +1.30. Grant CSM REPORT_GENERAL_DELAYED_PENALTY_ROLE to CSM Committee +1.31. Revoke CSM SETTLE_EL_REWARDS_STEALING_PENALTY_ROLE from Easy Track executor +1.32. Grant CSM SETTLE_GENERAL_DELAYED_PENALTY_ROLE to Easy Track executor +1.33. Revoke CSM VERIFIER_ROLE from the Old CSM Verifier +1.34. Grant CSM VERIFIER_ROLE to the New CSM Verifier +1.35. Grant CSM REPORT_REGULAR_WITHDRAWN_VALIDATORS_ROLE to the New CSM Verifier +1.36. Grant CSM REPORT_SLASHED_WITHDRAWN_VALIDATORS_ROLE to Easy Track executor +1.37. Revoke CSM CREATE_NODE_OPERATOR_ROLE from the Old CSM PermissionlessGate +1.38. Grant CSM CREATE_NODE_OPERATOR_ROLE to the New CSM PermissionlessGate +1.39. Revoke VettedGate START_REFERRAL_SEASON_ROLE from AGENT +1.40. Revoke VettedGate END_REFERRAL_SEASON_ROLE from CSM Committee +1.41. Set name Identified Community Stakers for CSM VettedGate gate +1.42. Unregister CircuitBreaker pauser for Old CSM Verifier +1.43. Unregister CircuitBreaker pauser for Old CSM Ejector +1.44. Register CircuitBreaker pauser for New CSM Verifier +1.45. Register CircuitBreaker pauser for New CSM Ejector +1.46. Register CircuitBreaker pauser for CSM Identified DVT Cluster gate +1.47. Grant CSM CREATE_NODE_OPERATOR_ROLE to Identified DVT Cluster gate +1.48. Grant CSM Accounting SET_BOND_CURVE_ROLE to Identified DVT Cluster gate +1.49. Grant CSM Accounting MANAGE_BOND_CURVES_ROLE to Identified DVT Cluster curve setup +1.50. Grant CSM ParametersRegistry MANAGE_CURVE_PARAMETERS_ROLE to Identified DVT Cluster curve setup +1.51. Execute Identified DVT Cluster curve setup +1.52. Grant CSM ParametersRegistry MANAGE_GENERAL_PENALTIES_AND_CHARGES_ROLE to CSM Committee +1.53. Revoke Burner REQUEST_BURN_SHARES_ROLE from CSM Accounting +1.54. Grant Burner REQUEST_BURN_MY_STETH_ROLE to CSM Accounting +1.55. Revoke TWG ADD_FULL_WITHDRAWAL_REQUEST_ROLE from the Old CSM Ejector +1.56. Grant TWG ADD_FULL_WITHDRAWAL_REQUEST_ROLE to the New CSM Ejector + # ======================== Curated Module ======================== -1.53. Add Curated module to StakingRouter -1.54. Grant REQUEST_BURN_MY_STETH_ROLE to Curated Accounting -1.55. Grant TWG full-withdrawal role to Curated Ejector -1.56. Grant RESUME_ROLE to agent on Curated module -1.57. Resume Curated module -1.58. Revoke RESUME_ROLE from agent on Curated module -1.59. Update Curated HashConsensus frame config -1.60. Register CircuitBreaker pauser for Curated module -1.61. Register CircuitBreaker pauser for Curated Accounting -1.62. Register CircuitBreaker pauser for Curated FeeOracle -1.63. Register CircuitBreaker pauser for Curated Verifier -1.64. Register CircuitBreaker pauser for Curated Ejector +1.57. Add Curated Module v2 to StakingRouter +1.58. Grant Burner REQUEST_BURN_MY_STETH_ROLE to Curated Accounting +1.59. Grant TWG ADD_FULL_WITHDRAWAL_REQUEST_ROLE to Curated Ejector +1.60. Grant CM RESUME_ROLE to AGENT +1.61. Resume Curated Module v2 +1.62. Revoke CM RESUME_ROLE from AGENT +1.63. Update Curated HashConsensus initial epoch +1.64. Register CircuitBreaker pauser for Curated Module v2 +1.65. Register CircuitBreaker pauser for Curated Accounting +1.66. Register CircuitBreaker pauser for Curated FeeOracle +1.67. Register CircuitBreaker pauser for Curated Verifier +1.68. Register CircuitBreaker pauser for Curated Ejector # ======================== Finish Upgrade ======================== -1.65. Call UpgradeTemplate.finishUpgrade +1.69. Call UpgradeTemplate.finishUpgrade # ======================== EasyTrack ======================== -2. Remove CSMSettleElStealingPenalty ET factory -3. Remove CSMSetVettedGateTree ET factory -4. Add UpdateStakingModuleShareLimits ET factory -5. Add AllowConsolidationPair ET factory -6. Add SetMerkleGateTree CSM ET factory -7. Add ReportWithdrawalsForSlashedValidators CSM ET factory -8. Add SettleGeneralDelayedPenalty CSM ET factory -9. Add SetMerkleGateTree CM ET factory -10. Add ReportWithdrawalsForSlashedValidators CM ET factory -11. Add SettleGeneralDelayedPenalty CM ET factory -12. Add CreateOrUpdateOperatorGroup CM ET factory - -Vote passed & executed on Apr-30-2026 02:04:12 PM +UTC, block 2721709. +2. Remove CSMSettleElStealingPenalty factory from Easy Track +3. Remove CSMSetVettedGateTree factory from Easy Track +4. Add UpdateStakingModuleShareLimits (for CSM) factory to Easy Track +5. Add AllowConsolidationPair factory to Easy Track +6. Add SetMerkleGateTree CSM factory to Easy Track +7. Add ReportWithdrawalsForSlashedValidators CSM factory to Easy Track +8. Add SettleGeneralDelayedPenalty CSM factory to Easy Track +9. Add SetMerkleGateTree CM factory to Easy Track +10. Add ReportWithdrawalsForSlashedValidators CM factory to Easy Track +11. Add SettleGeneralDelayedPenalty CM factory to Easy Track +12. Add CreateOrUpdateOperatorGroup CM factory to Easy Track + +Vote passed & executed on [TBA] +UTC, block [TBA] """ @@ -104,9 +113,8 @@ from utils.mainnet_fork import pass_and_exec_dao_vote from utils.voting import bake_vote_items, confirm_vote_script, create_vote - # UPGRADE_VOTE_SCRIPT address lives in configs/config_mainnet.py and is synced -# from core/deployed-local.json by sync_fork_addresses.py. +# from core/deployed-mainnet.json. # ============================= Description ================================== DG_PROPOSAL_METADATA = "Activate Staking Router v3 + Curated Module v2 + Community Staking Module v3" From 17bf58709f65cf43b209d11ecd05fa902e2e8cef Mon Sep 17 00:00:00 2001 From: KRogLA Date: Thu, 9 Jul 2026 15:18:52 +0200 Subject: [PATCH 05/30] feat: set actual UpgradeVoteScript mainnet address --- configs/config_mainnet.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configs/config_mainnet.py b/configs/config_mainnet.py index d69c68aa..953f8305 100644 --- a/configs/config_mainnet.py +++ b/configs/config_mainnet.py @@ -186,8 +186,8 @@ CURATED_V2_CIRCUIT_BREAKER_PAUSER = "0x2570e0b22AD904501dfB0d49575991ACB801dD91" # SRV3 # SRv3/CMv2 upgrade omnibus (UpgradeVoteScript) — the vote script reads its items -# from this contract. Fork-deployed, synced from core/deployed-local.json. -UPGRADE_VOTE_SCRIPT = "0xA2B2Fc588E2B69B781E9DdCE8d8671cd9CbbC224" # SRV3 +# from this contract. Synced from core/deployed-mainnet.json. +UPGRADE_VOTE_SCRIPT = "0xE6530830A2cf90773cB232748b2c674c27b6E0CA" # SRV3 # NodeOperatorsRegistry clone aka SimpleDVT SIMPLE_DVT_IMPL = "0x6828b023e737f96B168aCd0b5c6351971a4F81aE" From bfa78296943f0b9cd0332d32da9dc3bf47c4a0a9 Mon Sep 17 00:00:00 2001 From: KRogLA Date: Thu, 9 Jul 2026 15:21:00 +0200 Subject: [PATCH 06/30] test: srv3 voting before/after test --- tests/test_upgrade_2026_07_15_srv3_cmv2.py | 1634 ++++++++++++++++++++ 1 file changed, 1634 insertions(+) create mode 100644 tests/test_upgrade_2026_07_15_srv3_cmv2.py diff --git a/tests/test_upgrade_2026_07_15_srv3_cmv2.py b/tests/test_upgrade_2026_07_15_srv3_cmv2.py new file mode 100644 index 00000000..b593e547 --- /dev/null +++ b/tests/test_upgrade_2026_07_15_srv3_cmv2.py @@ -0,0 +1,1634 @@ +""" +Acceptance test for vote 2026_07_15 — Staking Router v3 + Curated Module v2 + Community Staking Module v3. + +Structure follows tests/_test_2026_MM_DD.py: + * Arrange variables + * Identify or create vote + * Execute vote (before / after voting checks) + * Execute Dual Governance proposal (before / after DG checks) + +All protocol addresses are resolved at runtime from the on-chain UpgradeConfig +(referenced by the deployed UpgradeVoteScript) so the test tracks the deployed +artefacts without a hand-maintained address list. + +Run: + ETHERSCAN_TOKEN= \ + poetry run brownie test tests/test_upgrade_2026_07_15_srv3_cmv2.py --network=mfh-1 -v +""" + +import os + +from typing import NamedTuple, Optional + +import pytest + +from brownie import chain, convert, history, interface, web3 +from brownie.network.contract import Contract +from brownie.network.event import EventDict +from brownie.network.transaction import TransactionReceipt + +from utils.config import network_name, TIMELOCK +from utils.test.tx_tracing_helpers import ( + add_event_emitter, + count_vote_items_by_events, + display_dg_events, + display_voting_events, + group_dg_events_from_receipt, + group_voting_events_from_receipt, +) +from utils.tx_tracing import tx_events_from_receipt +from utils.evm_script import encode_call_script +from utils.dual_governance import PROPOSAL_STATUS, process_proposals +from utils.test.event_validators.common import validate_events_chain +from utils.test.event_validators.dual_governance import validate_dual_governance_submit_event +from utils.test.event_validators.easy_track import ( + EVMScriptFactoryAdded, + validate_evmscript_factory_added_event, + validate_evmscript_factory_removed_event, +) +from utils.voting import find_metadata_by_vote_id +from utils.ipfs import calculate_vote_ipfs_description, get_lido_vote_cid_from_str + +# ============================================================================ +# ============================== Import vote ================================= +# ============================================================================ +from scripts.upgrade_2026_07_15_srv3_cmv2 import ( + IPFS_DESCRIPTION, + start_vote, + get_vote_items, + get_dg_items, + DG_PROPOSAL_METADATA, + UPGRADE_VOTE_SCRIPT, +) + + +# ============================================================================ +# ============================== Constants =================================== +# ============================================================================ +def _selector(signature: str) -> str: + return web3.keccak(text=signature).hex()[:10] + + +ZERO_ADDRESS = "0x0000000000000000000000000000000000000000" +DEFAULT_ADMIN_ROLE = "0x0000000000000000000000000000000000000000000000000000000000000000" + +# --- Aragon roles --- +APP_MANAGER_ROLE = web3.keccak(text="APP_MANAGER_ROLE").hex() +BUFFER_RESERVE_MANAGER_ROLE = web3.keccak(text="BUFFER_RESERVE_MANAGER_ROLE").hex() + +# --- StakingRouter roles (finalizeUpgrade_v4 migrates these, in this exact order) --- +MANAGE_WITHDRAWAL_CREDENTIALS_ROLE = web3.keccak(text="MANAGE_WITHDRAWAL_CREDENTIALS_ROLE").hex() +STAKING_MODULE_MANAGE_ROLE = web3.keccak(text="STAKING_MODULE_MANAGE_ROLE").hex() +STAKING_MODULE_UNVETTING_ROLE = web3.keccak(text="STAKING_MODULE_UNVETTING_ROLE").hex() +STAKING_MODULE_SHARE_MANAGE_ROLE = web3.keccak(text="STAKING_MODULE_SHARE_MANAGE_ROLE").hex() +REPORT_EXITED_VALIDATORS_ROLE = web3.keccak(text="REPORT_EXITED_VALIDATORS_ROLE").hex() +REPORT_VALIDATOR_EXITING_STATUS_ROLE = web3.keccak(text="REPORT_VALIDATOR_EXITING_STATUS_ROLE").hex() +REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE = web3.keccak(text="REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE").hex() +UNSAFE_SET_EXITED_VALIDATORS_ROLE = web3.keccak(text="UNSAFE_SET_EXITED_VALIDATORS_ROLE").hex() +REPORT_REWARDS_MINTED_ROLE = web3.keccak(text="REPORT_REWARDS_MINTED_ROLE").hex() + +# StakingRouter.finalizeUpgrade_v4 migration order (see StakingRouter.sol finalizeUpgrade_v4). +SR_MIGRATED_ROLES_ORDER = [ + DEFAULT_ADMIN_ROLE, + MANAGE_WITHDRAWAL_CREDENTIALS_ROLE, + STAKING_MODULE_MANAGE_ROLE, + STAKING_MODULE_UNVETTING_ROLE, + REPORT_EXITED_VALIDATORS_ROLE, + REPORT_VALIDATOR_EXITING_STATUS_ROLE, + REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE, + UNSAFE_SET_EXITED_VALIDATORS_ROLE, + REPORT_REWARDS_MINTED_ROLE, +] + +# --- Triggerable withdrawals gateway --- +TW_EXIT_LIMIT_MANAGER_ROLE = web3.keccak(text="TW_EXIT_LIMIT_MANAGER_ROLE").hex() +ADD_FULL_WITHDRAWAL_REQUEST_ROLE = web3.keccak(text="ADD_FULL_WITHDRAWAL_REQUEST_ROLE").hex() + +# --- CSM roles --- +REPORT_GENERAL_DELAYED_PENALTY_ROLE = web3.keccak(text="REPORT_GENERAL_DELAYED_PENALTY_ROLE").hex() +SETTLE_GENERAL_DELAYED_PENALTY_ROLE = web3.keccak(text="SETTLE_GENERAL_DELAYED_PENALTY_ROLE").hex() +REPORT_EL_REWARDS_STEALING_PENALTY_ROLE = web3.keccak(text="REPORT_EL_REWARDS_STEALING_PENALTY_ROLE").hex() +SETTLE_EL_REWARDS_STEALING_PENALTY_ROLE = web3.keccak(text="SETTLE_EL_REWARDS_STEALING_PENALTY_ROLE").hex() +VERIFIER_ROLE = web3.keccak(text="VERIFIER_ROLE").hex() +REPORT_REGULAR_WITHDRAWN_VALIDATORS_ROLE = web3.keccak(text="REPORT_REGULAR_WITHDRAWN_VALIDATORS_ROLE").hex() +REPORT_SLASHED_WITHDRAWN_VALIDATORS_ROLE = web3.keccak(text="REPORT_SLASHED_WITHDRAWN_VALIDATORS_ROLE").hex() +CREATE_NODE_OPERATOR_ROLE = web3.keccak(text="CREATE_NODE_OPERATOR_ROLE").hex() +SET_BOND_CURVE_ROLE = web3.keccak(text="SET_BOND_CURVE_ROLE").hex() +MANAGE_BOND_CURVES_ROLE = web3.keccak(text="MANAGE_BOND_CURVES_ROLE").hex() +MANAGE_CURVE_PARAMETERS_ROLE = web3.keccak(text="MANAGE_CURVE_PARAMETERS_ROLE").hex() +MANAGE_GENERAL_PENALTIES_AND_CHARGES_ROLE = web3.keccak(text="MANAGE_GENERAL_PENALTIES_AND_CHARGES_ROLE").hex() +START_REFERRAL_SEASON_ROLE = web3.keccak(text="START_REFERRAL_SEASON_ROLE").hex() +END_REFERRAL_SEASON_ROLE = web3.keccak(text="END_REFERRAL_SEASON_ROLE").hex() + +# --- Burner / Curated module roles --- +REQUEST_BURN_SHARES_ROLE = web3.keccak(text="REQUEST_BURN_SHARES_ROLE").hex() +REQUEST_BURN_MY_STETH_ROLE = web3.keccak(text="REQUEST_BURN_MY_STETH_ROLE").hex() +RESUME_ROLE = web3.keccak(text="RESUME_ROLE").hex() + +# --- EasyTrack factory permission selectors --- +VALIDATE_STAKING_MODULE_SHARE_PARAMS_SELECTOR = _selector("validateParams((uint16,uint16,uint16,uint16))") +UPDATE_MODULE_SHARES_SELECTOR = _selector("updateModuleShares(uint256,uint16,uint16)") +ALLOW_CONSOLIDATION_PAIR_SELECTOR = _selector("allowPair(uint256,uint256,address)") +SET_MERKLE_GATE_TREE_VALIDATE_INPUT_DATA_SELECTOR = _selector( + "validateInputData(address,bytes32,string,bytes32,string)" +) +SET_TREE_PARAMS_SELECTOR = _selector("setTreeParams(bytes32,string)") +REPORT_SLASHED_WITHDRAWN_VALIDATORS_SELECTOR = _selector( + "reportSlashedWithdrawnValidators((uint256,uint256,uint256,uint256,bool)[])" +) +SETTLE_GENERAL_DELAYED_PENALTY_SELECTOR = _selector("settleGeneralDelayedPenalty(uint256[],uint256[])") +CREATE_OR_UPDATE_OPERATOR_GROUP_VALIDATE_INPUT_DATA_SELECTOR = _selector( + "validateInputData(uint256,(string,(uint64,uint16)[],(bytes)[]),(string,(uint64,uint16)[],(bytes)[]))" +) +CREATE_OR_UPDATE_OPERATOR_GROUP_SELECTOR = _selector( + "createOrUpdateOperatorGroup(uint256,(string,(uint64,uint16)[],(bytes)[]))" +) + +# --- Contract / consensus versions --- +SR_INITIALIZED_VERSION = 4 +AO_CONTRACT_VERSION = 5 +AO_CONSENSUS_VERSION = 6 +VEBO_CONTRACT_VERSION = 3 +VEBO_CONSENSUS_VERSION = 5 +VEBO_MAX_VALIDATORS_PER_REPORT = 600 +VALIDATORS_EXIT_BUS_MAX_EXIT_BALANCE_ETH = 358400 +VALIDATORS_EXIT_BUS_BALANCE_PER_FRAME_ETH = 32 +VALIDATORS_EXIT_BUS_FRAME_DURATION_IN_SEC = 48 +WITHDRAWAL_VAULT_CONTRACT_VERSION = 3 +LIDO_CONTRACT_VERSION = 4 +CSM_INITIALIZED_VERSION = 3 +CS_FEE_ORACLE_CONTRACT_VERSION = 3 + +# --- Triggerable withdrawals exit-limit config --- +TW_MAX_EXIT_REQUESTS = 250 +TW_EXITS_PER_FRAME = 1 +TW_FRAME_DURATION_IN_SEC = 240 + +# --- Identified DVT cluster curve setup (baked into the OneShotCurveSetup contract) --- +IDVT_BOND_CURVE = [[1, 1500000000000000000], [2, 500000000000000000]] +IDVT_KEY_REMOVAL_CHARGE = 10000000000000000 +IDVT_GENERAL_DELAYED_PENALTY_FINE = 50000000000000000 +IDVT_QUEUE_PRIORITY = 1 +IDVT_QUEUE_MAX_DEPOSITS = 40 +IDVT_REWARD_SHARE_DATA = [[1, 5834], [65, 3334]] +IDVT_ALLOWED_EXIT_DELAY = 432000 +IDVT_EXIT_DELAY_FEE = 50000000000000000 + +IDENTIFIED_COMMUNITY_STAKERS_GATE_NAME = "Identified Community Stakers Gate" + +# ============================================================================ +# ============================= Test params ================================== +# ============================================================================ +EXPECTED_VOTE_ID = None +EXPECTED_DG_PROPOSAL_ID = None +EXPECTED_VOTE_EVENTS_COUNT = 12 # 1 DG submission + 11 Easy Track items +EXPECTED_DG_EVENTS_FROM_AGENT = 69 +EXPECTED_DG_EVENTS_COUNT = 69 +IPFS_DESCRIPTION_HASH = None +UPGRADE_VOTE_SCRIPT_ENV = "UPGRADE_VOTE_SCRIPT" + + +class StakingModuleItem(NamedTuple): + id: int + staking_module_address: str + name: str + staking_module_fee: int + stake_share_limit: int + treasury_fee: int + priority_exit_share_threshold: int + max_deposits_per_block: int + min_deposit_block_distance: int + + +# ============================================================================ +# ============================= Helpers ====================================== +# ============================================================================ +def _is_placeholder_address(value: str) -> bool: + normalized = str(value).lower() + return normalized in ("", ZERO_ADDRESS) or normalized.startswith("todo") + + +def _is_placeholder_text(value: str) -> bool: + return "TODO:" in value + + +def _event_list(events: EventDict, name: str): + return [event_item for event_item in events if event_item.name == name] + + +def _single_event(events: EventDict, name: str): + items = _event_list(events, name) + assert len(items) == 1, f"Expected exactly one {name} event, got {len(items)}" + return items[0] + + +def _normalize_role(role_value) -> str: + if isinstance(role_value, bytes): + return role_value.hex().replace("0x", "") + + if hasattr(role_value, "hex") and callable(role_value.hex): + return role_value.hex().replace("0x", "") + + return str(role_value).replace("0x", "") + + +def _assert_emitted_by(event_item, emitted_by: str) -> None: + assert convert.to_address(event_item["_emitted_by"]) == convert.to_address( + emitted_by + ), f"Wrong event emitter: expected {emitted_by}, got {event_item['_emitted_by']}" + + +def _permission(contract_address: str, selector: str) -> str: + return convert.to_address(contract_address).lower() + selector.lower().replace("0x", "") + + +def _concat_permissions(*permissions: str) -> str: + assert permissions, "Expected at least one permission" + return permissions[0] + "".join(permission.replace("0x", "") for permission in permissions[1:]) + + +def _raw_event_values(raw_event: dict) -> dict: + return {item["name"]: item["value"] for item in raw_event["data"]} + + +def _group_agent_dg_events_from_receipt(receipt: TransactionReceipt, timelock: str, agent: str) -> list[EventDict]: + """Split a Dual Governance execution receipt into per-item groups. + + The whole proposal is a single Agent.forward call, so the outer DG grouping + yields one item; we re-group by the `LogScriptCall` boundaries emitted by the + Agent (`src == agent`) to recover the individual upgrade items. + """ + events = tx_events_from_receipt(receipt) + + assert len(events) >= 1, "Unexpected events count" + assert ( + convert.to_address(events[-1]["address"]) == convert.to_address(timelock) + and events[-1]["name"] == "ProposalExecuted" + ), "Unexpected Dual Governance service event" + + groups = [] + current_group = None + + for event in events[:-1]: + event_values = _raw_event_values(event) if event["name"] == "LogScriptCall" else {} + is_start_of_new_group = event["name"] == "LogScriptCall" and convert.to_address( + event_values["src"] + ) == convert.to_address(agent) + + if is_start_of_new_group: + current_group = [] + groups.append(current_group) + + assert current_group is not None, "Unexpected DG events chain" + current_group.append(add_event_emitter(event)) + + return [EventDict(group) for group in groups] + + +# ---- event validators -------------------------------------------------------- +def validate_proxy_upgrade_event( + event: EventDict, + implementation: str, + emitted_by: Optional[str] = None, + events_chain: Optional[list[str]] = None, +) -> None: + _events_chain = events_chain or ["LogScriptCall", "Upgraded"] + validate_events_chain([e.name for e in event], _events_chain) + + assert event.count("LogScriptCall") == 1 + assert event.count("Upgraded") == 1 + + upgraded_event = _single_event(event, "Upgraded") + assert convert.to_address(upgraded_event["implementation"]) == convert.to_address( + implementation + ), "Wrong implementation address" + + if emitted_by is not None: + _assert_emitted_by(upgraded_event, emitted_by) + + +def validate_contract_version_set_event( + event: EventDict, + version: int, + emitted_by: Optional[str] = None, + events_chain: Optional[list[str]] = None, +) -> None: + _events_chain = events_chain or ["LogScriptCall", "ContractVersionSet"] + validate_events_chain([e.name for e in event], _events_chain) + + assert event.count("ContractVersionSet") == 1 + contract_version_event = _single_event(event, "ContractVersionSet") + assert contract_version_event["version"] == version, "Wrong contract version" + + if emitted_by is not None: + _assert_emitted_by(contract_version_event, emitted_by) + + +def validate_consensus_version_set_event( + event: EventDict, + new_version: int, + prev_version: int, + emitted_by: Optional[str] = None, + events_chain: Optional[list[str]] = None, +) -> None: + _events_chain = events_chain or ["LogScriptCall", "ConsensusVersionSet"] + validate_events_chain([e.name for e in event], _events_chain) + + assert event.count("ConsensusVersionSet") == 1 + consensus_version_event = _single_event(event, "ConsensusVersionSet") + assert consensus_version_event["version"] == new_version, "Wrong new consensus version" + assert consensus_version_event["prevVersion"] == prev_version, "Wrong previous consensus version" + + if emitted_by is not None: + _assert_emitted_by(consensus_version_event, emitted_by) + + +def validate_role_grant_event( + event: EventDict, + role_hash: str, + account: str, + sender: str, + emitted_by: Optional[str] = None, +) -> None: + validate_events_chain([e.name for e in event], ["LogScriptCall", "RoleGranted"]) + + assert event.count("RoleGranted") == 1 + role_granted_event = _single_event(event, "RoleGranted") + assert _normalize_role(role_granted_event["role"]) == role_hash.replace("0x", ""), "Wrong role hash" + assert convert.to_address(role_granted_event["account"]) == convert.to_address(account), "Wrong granted account" + assert convert.to_address(role_granted_event["sender"]) == convert.to_address(sender), "Wrong role grant sender" + + if emitted_by is not None: + _assert_emitted_by(role_granted_event, emitted_by) + + +def validate_role_revoke_event( + event: EventDict, + role_hash: str, + account: str, + sender: str, + emitted_by: Optional[str] = None, +) -> None: + validate_events_chain([e.name for e in event], ["LogScriptCall", "RoleRevoked"]) + + assert event.count("RoleRevoked") == 1 + role_revoked_event = _single_event(event, "RoleRevoked") + assert _normalize_role(role_revoked_event["role"]) == role_hash.replace("0x", ""), "Wrong role hash" + assert convert.to_address(role_revoked_event["account"]) == convert.to_address(account), "Wrong revoked account" + assert convert.to_address(role_revoked_event["sender"]) == convert.to_address(sender), "Wrong role revoke sender" + + if emitted_by is not None: + _assert_emitted_by(role_revoked_event, emitted_by) + + +def validate_module_add(event: EventDict, module: StakingModuleItem, emitted_by: str, sender: str) -> None: + validate_events_chain( + [e.name for e in event], + [ + "LogScriptCall", + "StakingModuleAdded", + "StakingModuleShareLimitSet", + "StakingModuleFeesSet", + "StakingModuleMaxDepositsPerBlockSet", + "StakingModuleMinDepositBlockDistanceSet", + "StakingRouterETHDeposited", + ], + ) + + module_added_event = _single_event(event, "StakingModuleAdded") + assert module_added_event["stakingModuleId"] == module.id + assert convert.to_address(module_added_event["stakingModule"]) == convert.to_address(module.staking_module_address) + assert module_added_event["name"] == module.name + assert convert.to_address(module_added_event["createdBy"]) == convert.to_address(sender) + _assert_emitted_by(module_added_event, emitted_by) + + module_share_limit_event = _single_event(event, "StakingModuleShareLimitSet") + assert module_share_limit_event["stakingModuleId"] == module.id + assert module_share_limit_event["stakeShareLimit"] == module.stake_share_limit + assert module_share_limit_event["priorityExitShareThreshold"] == module.priority_exit_share_threshold + assert convert.to_address(module_share_limit_event["setBy"]) == convert.to_address(sender) + _assert_emitted_by(module_share_limit_event, emitted_by) + + module_fees_event = _single_event(event, "StakingModuleFeesSet") + assert module_fees_event["stakingModuleId"] == module.id + assert module_fees_event["stakingModuleFee"] == module.staking_module_fee + assert module_fees_event["treasuryFee"] == module.treasury_fee + assert convert.to_address(module_fees_event["setBy"]) == convert.to_address(sender) + _assert_emitted_by(module_fees_event, emitted_by) + + max_deposits_event = _single_event(event, "StakingModuleMaxDepositsPerBlockSet") + assert max_deposits_event["stakingModuleId"] == module.id + assert max_deposits_event["maxDepositsPerBlock"] == module.max_deposits_per_block + assert convert.to_address(max_deposits_event["setBy"]) == convert.to_address(sender) + _assert_emitted_by(max_deposits_event, emitted_by) + + min_distance_event = _single_event(event, "StakingModuleMinDepositBlockDistanceSet") + assert min_distance_event["stakingModuleId"] == module.id + assert min_distance_event["minDepositBlockDistance"] == module.min_deposit_block_distance + assert convert.to_address(min_distance_event["setBy"]) == convert.to_address(sender) + _assert_emitted_by(min_distance_event, emitted_by) + + deposited_event = _single_event(event, "StakingRouterETHDeposited") + assert deposited_event["stakingModuleId"] == module.id + assert deposited_event["amount"] == 0 + _assert_emitted_by(deposited_event, emitted_by) + + +def validate_circuit_breaker_registration_event( + event: EventDict, + circuit_breaker: str, + pausable: str, + pauser: str, +) -> None: + validate_events_chain( + [e.name for e in event], + ["LogScriptCall", "PauserSet", "HeartbeatUpdated"], + ) + + pauser_set_event = _single_event(event, "PauserSet") + assert convert.to_address(pauser_set_event["pausable"]) == convert.to_address(pausable) + assert convert.to_address(pauser_set_event["previousPauser"]) == convert.to_address(ZERO_ADDRESS) + assert convert.to_address(pauser_set_event["newPauser"]) == convert.to_address(pauser) + _assert_emitted_by(pauser_set_event, circuit_breaker) + + heartbeat_updated_event = _single_event(event, "HeartbeatUpdated") + assert convert.to_address(heartbeat_updated_event["pauser"]) == convert.to_address(pauser) + assert heartbeat_updated_event["newHeartbeatExpiry"] > 0 + _assert_emitted_by(heartbeat_updated_event, circuit_breaker) + + +def validate_circuit_breaker_unregistration_event( + event: EventDict, + circuit_breaker: str, + pausable: str, + previous_pauser: str, +) -> None: + # Unregister always emits PauserSet(pausable, previousPauser, 0). It additionally emits + # HeartbeatUpdated(previousPauser, 0) iff previousPauser no longer guards any pausable + # afterwards — a fork-state-dependent tail that we validate only when present. + validate_events_chain( + [e.name for e in event], + ["LogScriptCall", "PauserSet", "HeartbeatUpdated"], + ) + + pauser_set_event = _single_event(event, "PauserSet") + assert convert.to_address(pauser_set_event["pausable"]) == convert.to_address(pausable) + assert convert.to_address(pauser_set_event["previousPauser"]) == convert.to_address(previous_pauser) + assert convert.to_address(pauser_set_event["newPauser"]) == convert.to_address(ZERO_ADDRESS) + _assert_emitted_by(pauser_set_event, circuit_breaker) + + if event.count("HeartbeatUpdated") > 0: + heartbeat_updated_event = _single_event(event, "HeartbeatUpdated") + assert convert.to_address(heartbeat_updated_event["pauser"]) == convert.to_address(previous_pauser) + assert heartbeat_updated_event["newHeartbeatExpiry"] == 0 + _assert_emitted_by(heartbeat_updated_event, circuit_breaker) + + +def validate_gate_name_set_event(event: EventDict, name: str, emitted_by: str) -> None: + # NOTE: events chain confirmed against the on-chain execution dump. + validate_events_chain([e.name for e in event], ["LogScriptCall", "NameSet"]) + name_set_event = _single_event(event, "NameSet") + assert name_set_event["name"] == name, "Wrong gate name" + _assert_emitted_by(name_set_event, emitted_by) + + +def _expected_sr_role_migration_grants(staking_router: str): + """Read the members of every role migrated by StakingRouter.finalizeUpgrade_v4. + + finalizeUpgrade_v4 re-grants each pre-upgrade member of the migrated roles in + role order, member index order — this is what the RoleGranted events reflect. + """ + sr = interface.StakingRouter(staking_router) + grants = [] + for role in SR_MIGRATED_ROLES_ORDER: + count = sr.getRoleMemberCount(role) + for i in range(count): + grants.append((role, sr.getRoleMember(role, i))) + return grants + + +# ============================================================================ +# ============================== Fixtures ==================================== +# ============================================================================ +@pytest.fixture(scope="module") +def runtime_upgrade_context(): + upgrade_vote_script = os.getenv(UPGRADE_VOTE_SCRIPT_ENV, UPGRADE_VOTE_SCRIPT) + print(f"Upgrade vote script: {upgrade_vote_script}") + print(f"DG_PROPOSAL_METADATA: {DG_PROPOSAL_METADATA}") + print(f"IPFS_DESCRIPTION: {IPFS_DESCRIPTION}") + + if ( + _is_placeholder_address(upgrade_vote_script) + or _is_placeholder_text(DG_PROPOSAL_METADATA) + or _is_placeholder_text(IPFS_DESCRIPTION) + ): + pytest.skip( + "Upgrade vote script address is missing. Set env UPGRADE_VOTE_SCRIPT " + "or UPGRADE_VOTE_SCRIPT in scripts/upgrade_2026_07_15_srv3_cmv2.py first." + ) + + vote_script = interface.UpgradeVoteScript(upgrade_vote_script) + upgrade_template = vote_script.TEMPLATE() + upgrade_config = interface.UpgradeConfig(vote_script.CONFIG()) + locator_impl = interface.LidoLocator(upgrade_config.getCoreUpgradeConfig()["newLocatorImpl"]) + + global_config = upgrade_config.getGlobalConfig() + core_config = upgrade_config.getCoreUpgradeConfig() + csm_config = upgrade_config.getCSMUpgradeConfig() + curated_config = upgrade_config.getCuratedModuleConfig() + easy_track_new_factories, easy_track_old_factories = upgrade_config.getEasyTrackConfig() + + # Load ABIs for Brownie receipt event decoding. + interface.CircuitBreaker(global_config["circuitBreaker"]) + interface.ValidatorsExitBusOracle(core_config["validatorsExitBusOracle"]) + interface.CSParametersRegistry(csm_config["parametersRegistry"]) + interface.OneShotCurveSetup(csm_config["identifiedDVTClusterCurveSetup"]) + interface.CSAccounting(csm_config["accounting"]) # BondCurveAdded (curve setup item) + # ExitBalanceLimitSet exists only in the new ValidatorsExitBusOracle impl ABI (not in the + # local interfaces/*.json), so fetch that impl from the explorer to make it decodable. + Contract.from_explorer(convert.to_address(core_config["newValidatorsExitBusOracleImpl"])) + + dual_governance = interface.DualGovernance(upgrade_config.DUAL_GOVERNANCE()) + dual_governance_admin_executor = None + for proposer in dual_governance.getProposers(): + try: + proposer_account = proposer["account"] + proposer_executor = proposer["executor"] + except (KeyError, TypeError): + proposer_account = proposer[0] + proposer_executor = proposer[1] + + if convert.to_address(proposer_account) == convert.to_address(upgrade_config.VOTING()): + dual_governance_admin_executor = proposer_executor + break + + assert dual_governance_admin_executor is not None, "Voting proposer is not registered in Dual Governance" + + validator_strikes = interface.IValidatorStrikesV3(csm_config["strikes"]) + old_csm_ejector = validator_strikes.ejector() + + staking_router = global_config["stakingRouter"] + + # Pre-upgrade state used to build dynamic expectations (read before the vote runs): + # - StakingRouter role migration performed by finalizeUpgrade_v4 + # - new staking module id assigned to Curated Module v2 + # - Curated HashConsensus epochsPerFrame preserved by updateInitialEpoch + sr_role_migration_grants = _expected_sr_role_migration_grants(staking_router) + expected_curated_module_id = interface.StakingRouter(staking_router).getStakingModulesCount() + 1 + curated_epochs_per_frame = interface.HashConsensus(curated_config["hashConsensus"]).getFrameConfig()[1] + + return { + "upgrade_vote_script": upgrade_vote_script, + "upgrade_template": upgrade_template, + "voting": upgrade_config.VOTING(), + "agent": upgrade_config.AGENT(), + "dual_governance": upgrade_config.DUAL_GOVERNANCE(), + "dual_governance_admin_executor": dual_governance_admin_executor, + "acl": core_config["acl"], + "aragon_kernel": core_config["kernel"], + "lido": global_config["lido"], + "lido_deposits_reserve_target": core_config["lidoDepositsReserveTarget"], + "easy_track": global_config["easyTrack"], + "lido_app_id": core_config["lidoAppId"], + "lido_impl": core_config["newLidoImpl"], + "lido_locator": core_config["locator"], + "lido_locator_impl": core_config["newLocatorImpl"], + "staking_router": staking_router, + "staking_router_impl": core_config["newStakingRouterImpl"], + "sr_role_migration_grants": sr_role_migration_grants, + "max_top_up_per_block_gwei": core_config["maxTopUpPerBlockGwei"], + "accounting_oracle": core_config["accountingOracle"], + "accounting_oracle_impl": core_config["newAccountingOracleImpl"], + "validators_exit_bus_oracle": core_config["validatorsExitBusOracle"], + "validators_exit_bus_oracle_impl": core_config["newValidatorsExitBusOracleImpl"], + "accounting": core_config["accounting"], + "accounting_impl": core_config["newAccountingImpl"], + "withdrawal_vault": core_config["withdrawalVault"], + "withdrawal_vault_impl": core_config["newWithdrawalVaultImpl"], + "oracle_report_sanity_checker": core_config["newOracleReportSanityChecker"], + "validator_exit_delay_verifier": locator_impl.validatorExitDelayVerifier(), + "easytrack_evm_script_executor": global_config["easyTrackEVMScriptExecutor"], + "circuit_breaker": global_config["circuitBreaker"], + "circuit_breaker_committee": global_config["circuitBreakerCommittee"], + "consolidation_gateway": core_config["consolidationGateway"], + "consolidation_committee": core_config["consolidationCommittee"], + "top_up_gateway": core_config["topUpGateway"], + "old_deposit_security_module": core_config["oldDepositSecurityModule"], + "new_deposit_security_module": core_config["newDepositSecurityModule"], + "triggerable_withdrawals_gateway": global_config["triggerableWithdrawalsGateway"], + "burner": global_config["burner"], + "csm": csm_config["csm"], + "csm_impl": csm_config["csmImpl"], + "cs_parameters_registry": csm_config["parametersRegistry"], + "cs_parameters_registry_impl": csm_config["parametersRegistryImpl"], + "cs_fee_oracle": csm_config["feeOracle"], + "cs_fee_oracle_impl": csm_config["feeOracleImpl"], + "cs_fee_oracle_consensus_version": csm_config["feeOracleConsensusVersion"], + "cs_vetted_gate": csm_config["vettedGate"], + "cs_vetted_gate_impl": csm_config["vettedGateImpl"], + "cs_accounting": csm_config["accounting"], + "cs_accounting_impl": csm_config["accountingImpl"], + "cs_fee_distributor": csm_config["feeDistributor"], + "cs_fee_distributor_impl": csm_config["feeDistributorImpl"], + "cs_exit_penalties": csm_config["exitPenalties"], + "cs_exit_penalties_impl": csm_config["exitPenaltiesImpl"], + "cs_validator_strikes": csm_config["strikes"], + "cs_validator_strikes_impl": csm_config["strikesImpl"], + "old_verifier": csm_config["oldVerifier"], + "verifier_v3": csm_config["newVerifier"], + "old_permissionless_gate": csm_config["oldPermissionlessGate"], + "new_permissionless_gate": csm_config["newPermissionlessGate"], + "identified_dvt_cluster_gate": csm_config["identifiedDVTClusterGate"], + "identified_dvt_cluster_curve_setup": csm_config["identifiedDVTClusterCurveSetup"], + "identified_dvt_cluster_bond_curve_id": csm_config["identifiedDVTClusterBondCurveId"], + "old_csm_ejector": old_csm_ejector, + "new_csm_ejector": csm_config["newEjector"], + "config_old_csm_ejector": csm_config["oldEjector"], + "csm_committee": csm_config["csmCommittee"], + "curated_module": curated_config["module"], + "curated_gates": curated_config["curatedGates"], + "curated_accounting": curated_config["accounting"], + "curated_ejector": curated_config["ejector"], + "curated_fee_oracle": curated_config["feeOracle"], + "curated_verifier": curated_config["verifier"], + "curated_circuit_breaker_pauser": curated_config["circuitBreakerPauser"], + "curated_strikes": curated_config["strikes"], + "curated_hash_consensus": curated_config["hashConsensus"], + "curated_hash_consensus_initial_epoch": curated_config["hashConsensusInitialEpoch"], + "curated_epochs_per_frame": curated_epochs_per_frame, + "meta_registry": curated_config["metaRegistry"], + "curated_module_item": StakingModuleItem( + id=expected_curated_module_id, + staking_module_address=curated_config["module"], + name=curated_config["moduleName"], + staking_module_fee=curated_config["stakingModuleFee"], + stake_share_limit=curated_config["stakeShareLimit"], + treasury_fee=curated_config["treasuryFee"], + priority_exit_share_threshold=curated_config["priorityExitShareThreshold"], + max_deposits_per_block=curated_config["maxDepositsPerBlock"], + min_deposit_block_distance=curated_config["minDepositBlockDistance"], + ), + "update_staking_module_share_limits_factory": easy_track_new_factories["UpdateStakingModuleShareLimits"], + "allow_consolidation_pair_factory": easy_track_new_factories["AllowConsolidationPair"], + "set_merkle_gate_tree_for_csm_factory": easy_track_new_factories["SetMerkleGateTreeForCSM"], + "report_withdrawals_for_slashed_validators_for_csm_factory": easy_track_new_factories[ + "ReportWithdrawalsForSlashedValidatorsForCSM" + ], + "settle_general_delayed_penalty_for_csm_factory": easy_track_new_factories["SettleGeneralDelayedPenaltyForCSM"], + "set_merkle_gate_tree_for_cm_factory": easy_track_new_factories["SetMerkleGateTreeForCM"], + "report_withdrawals_for_slashed_validators_for_cm_factory": easy_track_new_factories[ + "ReportWithdrawalsForSlashedValidatorsForCM" + ], + "settle_general_delayed_penalty_for_cm_factory": easy_track_new_factories["SettleGeneralDelayedPenaltyForCM"], + "create_or_update_operator_group_factory": easy_track_new_factories["CreateOrUpdateOperatorGroupForCM"], + "old_csm_settle_el_stealing_penalty_factory": easy_track_old_factories["CSMSettleElStealingPenalty"], + "old_csm_set_vetted_gate_tree_factory": easy_track_old_factories["CSMSetVettedGateTree"], + "consolidation_migrator": core_config["consolidationMigrator"], + } + + +@pytest.fixture(scope="module") +def dual_governance_proposal_calls(runtime_upgrade_context): + dg_items = get_dg_items(runtime_upgrade_context["upgrade_vote_script"]) + + proposal_calls = [] + for target, data in dg_items: + # get_dg_items() returns data as HexBytes.hex(); in current hexbytes this + # drops the "0x" prefix, which breaks Brownie's HexString comparison in the + # submit-event validator. Normalise to a 0x-prefixed hex string. + data_hex = data if str(data).startswith("0x") else "0x" + str(data) + proposal_calls.append( + { + "target": target, + "value": 0, + "data": data_hex, + } + ) + + return proposal_calls + + +# ============================================================================ +# =============================== The test =================================== +# ============================================================================ +def test_vote( + helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_governance_proposal_calls, runtime_upgrade_context +): + # ========================================================================= + # ========================= Arrange variables ============================= + # ========================================================================= + ctx = runtime_upgrade_context + + voting = interface.Voting(ctx["voting"]) + agent = interface.Agent(ctx["agent"]) + timelock = interface.EmergencyProtectedTimelock(TIMELOCK) + dual_governance = interface.DualGovernance(ctx["dual_governance"]) + easy_track = interface.EasyTrack(ctx["easy_track"]) + staking_router = interface.StakingRouter(ctx["staking_router"]) + + _, call_script_items = get_vote_items(upgrade_vote_script=ctx["upgrade_vote_script"]) + # NB: get_dg_items() returns the Dual Governance proposal calls — a single packed + # `Agent.forward(...)` call. The individual upgrade actions live inside it and only + # surface as events during DG execution, so their count comes from DG_ITEMS_COUNT(). + upgrade_template = ctx["upgrade_template"] + vote_script = interface.UpgradeVoteScript(ctx["upgrade_vote_script"]) + onchain_dg_items_count = vote_script.DG_ITEMS_COUNT() + + expected_vote_events_count = EXPECTED_VOTE_EVENTS_COUNT or len(call_script_items) + expected_dg_events_from_agent = EXPECTED_DG_EVENTS_FROM_AGENT or onchain_dg_items_count + expected_dg_events_count = EXPECTED_DG_EVENTS_COUNT or onchain_dg_items_count + expected_ipfs_description_hash = IPFS_DESCRIPTION_HASH or calculate_vote_ipfs_description(IPFS_DESCRIPTION)["cid"] + + # Guard against the deployed script drifting from the counts encoded in this test. + assert onchain_dg_items_count == expected_dg_events_count, ( + f"On-chain DG_ITEMS_COUNT ({onchain_dg_items_count}) != EXPECTED_DG_EVENTS_COUNT ({expected_dg_events_count})" + ) + assert len(call_script_items) == expected_vote_events_count, ( + f"On-chain voting item count ({len(call_script_items)}) != EXPECTED_VOTE_EVENTS_COUNT " + f"({expected_vote_events_count})" + ) + + old_easy_track_factories = [ + ctx["old_csm_settle_el_stealing_penalty_factory"], + ctx["old_csm_set_vetted_gate_tree_factory"], + ] + new_easy_track_factories = [ + ctx["update_staking_module_share_limits_factory"], + ctx["allow_consolidation_pair_factory"], + ctx["set_merkle_gate_tree_for_csm_factory"], + ctx["report_withdrawals_for_slashed_validators_for_csm_factory"], + ctx["settle_general_delayed_penalty_for_csm_factory"], + ctx["set_merkle_gate_tree_for_cm_factory"], + ctx["report_withdrawals_for_slashed_validators_for_cm_factory"], + ctx["settle_general_delayed_penalty_for_cm_factory"], + ctx["create_or_update_operator_group_factory"], + ] + # SetMerkleGateTree permissions = factory.validateInputData + each gate.setTreeParams + csm_tree_gate_permissions = _concat_permissions( + _permission(ctx["set_merkle_gate_tree_for_csm_factory"], SET_MERKLE_GATE_TREE_VALIDATE_INPUT_DATA_SELECTOR), + _permission(ctx["cs_vetted_gate"], SET_TREE_PARAMS_SELECTOR), + _permission(ctx["identified_dvt_cluster_gate"], SET_TREE_PARAMS_SELECTOR), + ) + curated_tree_gate_permissions = _concat_permissions( + _permission(ctx["set_merkle_gate_tree_for_cm_factory"], SET_MERKLE_GATE_TREE_VALIDATE_INPUT_DATA_SELECTOR), + *[_permission(gate, SET_TREE_PARAMS_SELECTOR) for gate in ctx["curated_gates"]], + ) + + # ========================================================================= + # ======================== Identify or Create 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, + upgrade_vote_script=ctx["upgrade_vote_script"], + ) + + onchain_script = voting.getVote(vote_id)["script"] + assert str(onchain_script).lower() == encode_call_script(call_script_items).lower() + + expected_dg_proposal_id = EXPECTED_DG_PROPOSAL_ID + dg_proposals_count_before_vote_execution = timelock.getProposalsCount() + + # ========================================================================= + # ============================= Execute Vote ============================== + # ========================================================================= + is_executed = voting.getVote(vote_id)["executed"] + if not is_executed: + # ===================================================================== + # ======================= Before voting checks ======================== + # ===================================================================== + initial_factories = easy_track.getEVMScriptFactories() + for factory in old_easy_track_factories: + assert factory in initial_factories, "Old Easy Track factory unexpectedly absent before the vote" + for factory in new_easy_track_factories: + assert factory not in initial_factories, "New Easy Track factory unexpectedly present before the vote" + + # Curated Module v2 is not registered in the Staking Router yet. + assert staking_router.getStakingModulesCount() == ctx["curated_module_item"].id - 1 + + assert get_lido_vote_cid_from_str(find_metadata_by_vote_id(vote_id)) == expected_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 ======================== + # ===================================================================== + new_factories = easy_track.getEVMScriptFactories() + for factory in old_easy_track_factories: + assert factory not in new_factories, "Old Easy Track factory not removed by the vote" + for factory in new_easy_track_factories: + assert factory in new_factories, "New Easy Track factory not added by the vote" + + assert len(vote_events) == expected_vote_events_count + assert count_vote_items_by_events(vote_tx, voting.address) == expected_vote_events_count + + if expected_dg_proposal_id is None: + expected_dg_proposal_id = dg_proposals_count_before_vote_execution + 1 + + assert expected_dg_proposal_id == timelock.getProposalsCount() + + # 1. Submit a Dual Governance proposal + validate_dual_governance_submit_event( + vote_events[0], + proposal_id=expected_dg_proposal_id, + proposer=ctx["voting"], + executor=ctx["dual_governance_admin_executor"], + metadata=DG_PROPOSAL_METADATA, + proposal_calls=dual_governance_proposal_calls, + ) + + # 2. Remove CSMSettleElStealingPenalty ET factory + validate_evmscript_factory_removed_event( + vote_events[1], + factory_addr=ctx["old_csm_settle_el_stealing_penalty_factory"], + emitted_by=easy_track, + ) + + # 3. Remove CSMSetVettedGateTree ET factory + validate_evmscript_factory_removed_event( + vote_events[2], + factory_addr=ctx["old_csm_set_vetted_gate_tree_factory"], + emitted_by=easy_track, + ) + + # 4. Add UpdateStakingModuleShareLimits ET factory + validate_evmscript_factory_added_event( + event=vote_events[3], + p=EVMScriptFactoryAdded( + factory_addr=ctx["update_staking_module_share_limits_factory"], + permissions=_concat_permissions( + _permission( + ctx["update_staking_module_share_limits_factory"], + VALIDATE_STAKING_MODULE_SHARE_PARAMS_SELECTOR, + ), + _permission(ctx["staking_router"], UPDATE_MODULE_SHARES_SELECTOR), + ), + ), + emitted_by=easy_track, + ) + + # 5. Add AllowConsolidationPair ET factory + validate_evmscript_factory_added_event( + event=vote_events[4], + p=EVMScriptFactoryAdded( + factory_addr=ctx["allow_consolidation_pair_factory"], + permissions=_permission(ctx["consolidation_migrator"], ALLOW_CONSOLIDATION_PAIR_SELECTOR), + ), + emitted_by=easy_track, + ) + + # 6. Add SetMerkleGateTree CSM ET factory + validate_evmscript_factory_added_event( + event=vote_events[5], + p=EVMScriptFactoryAdded( + factory_addr=ctx["set_merkle_gate_tree_for_csm_factory"], + permissions=csm_tree_gate_permissions, + ), + emitted_by=easy_track, + ) + + # 7. Add ReportWithdrawalsForSlashedValidators CSM ET factory + validate_evmscript_factory_added_event( + event=vote_events[6], + p=EVMScriptFactoryAdded( + factory_addr=ctx["report_withdrawals_for_slashed_validators_for_csm_factory"], + permissions=_permission(ctx["csm"], REPORT_SLASHED_WITHDRAWN_VALIDATORS_SELECTOR), + ), + emitted_by=easy_track, + ) + + # 8. Add SettleGeneralDelayedPenalty CSM ET factory + validate_evmscript_factory_added_event( + event=vote_events[7], + p=EVMScriptFactoryAdded( + factory_addr=ctx["settle_general_delayed_penalty_for_csm_factory"], + permissions=_permission(ctx["csm"], SETTLE_GENERAL_DELAYED_PENALTY_SELECTOR), + ), + emitted_by=easy_track, + ) + + # 9. Add SetMerkleGateTree CM ET factory + validate_evmscript_factory_added_event( + event=vote_events[8], + p=EVMScriptFactoryAdded( + factory_addr=ctx["set_merkle_gate_tree_for_cm_factory"], + permissions=curated_tree_gate_permissions, + ), + emitted_by=easy_track, + ) + + # 10. Add ReportWithdrawalsForSlashedValidators CM ET factory + validate_evmscript_factory_added_event( + event=vote_events[9], + p=EVMScriptFactoryAdded( + factory_addr=ctx["report_withdrawals_for_slashed_validators_for_cm_factory"], + permissions=_permission(ctx["curated_module"], REPORT_SLASHED_WITHDRAWN_VALIDATORS_SELECTOR), + ), + emitted_by=easy_track, + ) + + # 11. Add SettleGeneralDelayedPenalty CM ET factory + validate_evmscript_factory_added_event( + event=vote_events[10], + p=EVMScriptFactoryAdded( + factory_addr=ctx["settle_general_delayed_penalty_for_cm_factory"], + permissions=_permission(ctx["curated_module"], SETTLE_GENERAL_DELAYED_PENALTY_SELECTOR), + ), + emitted_by=easy_track, + ) + + # 12. Add CreateOrUpdateOperatorGroup CM ET factory + validate_evmscript_factory_added_event( + event=vote_events[11], + p=EVMScriptFactoryAdded( + factory_addr=ctx["create_or_update_operator_group_factory"], + permissions=_concat_permissions( + _permission( + ctx["create_or_update_operator_group_factory"], + CREATE_OR_UPDATE_OPERATOR_GROUP_VALIDATE_INPUT_DATA_SELECTOR, + ), + _permission(ctx["meta_registry"], CREATE_OR_UPDATE_OPERATOR_GROUP_SELECTOR), + ), + ), + emitted_by=easy_track, + ) + elif expected_dg_proposal_id is None: + pytest.skip("Fill EXPECTED_DG_PROPOSAL_ID to run the DG part against an already-executed vote.") + + # ========================================================================= + # ======================= Execute DG Proposal ============================= + # ========================================================================= + if expected_dg_proposal_id is not None: + # --- pre-DG state snapshots used by the after-DG acceptance checks --- + initial_cs_fee_oracle_consensus_version = interface.CSFeeOracle(ctx["cs_fee_oracle"]).getConsensusVersion() + + details = timelock.getProposalDetails(expected_dg_proposal_id) + if details["status"] != PROPOSAL_STATUS["executed"]: + # ================================================================= + # ================ Before DG proposal executed checks ============= + # ================================================================= + assert interface.AccountingOracle(ctx["accounting_oracle"]).getConsensusVersion() == AO_CONSENSUS_VERSION - 1 + assert ( + interface.ValidatorsExitBusOracle(ctx["validators_exit_bus_oracle"]).getConsensusVersion() + == VEBO_CONSENSUS_VERSION - 1 + ) + + 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"]: + # Delegate execution to process_proposals: it waits the schedule delay and, crucially, + # pushes a fresh AccountingOracle report so Lido.finalizeUpgrade_v4 (DG item 1.12) does + # not revert with "NO_REPORT" once the DG delays have rolled the oracle frame over. + process_proposals([expected_dg_proposal_id]) + dg_tx: TransactionReceipt = history[-1] + display_dg_events(dg_tx) + outer_dg_events = group_dg_events_from_receipt( + dg_tx, + timelock=TIMELOCK, + admin_executor=ctx["dual_governance_admin_executor"], + ) + dg_events = _group_agent_dg_events_from_receipt( + dg_tx, + timelock=TIMELOCK, + agent=agent.address, + ) + assert count_vote_items_by_events(dg_tx, agent.address) == expected_dg_events_from_agent + assert len(outer_dg_events) == 1 + assert len(dg_events) == expected_dg_events_count + + # ============================================================= + # ================ DG EXECUTION EVENTS VALIDATION ============= + # ============================================================= + + # ------------------------ Core ------------------------------ + # 1.1. Call UpgradeTemplate.startUpgrade + validate_events_chain([e.name for e in dg_events[0]], ["LogScriptCall", "UpgradeStarted"]) + _assert_emitted_by(_single_event(dg_events[0], "UpgradeStarted"), upgrade_template) + + # 1.2. Upgrade LidoLocator implementation + validate_proxy_upgrade_event(dg_events[1], ctx["lido_locator_impl"], emitted_by=ctx["lido_locator"]) + + # 1.3. Upgrade StakingRouter implementation and call finalizeUpgrade_v4. + # finalizeUpgrade_v4 sets maxTopUpPerBlockGwei and re-grants each pre-upgrade + # member of the migrated roles. + sr_grants = ctx["sr_role_migration_grants"] + validate_proxy_upgrade_event( + dg_events[2], + ctx["staking_router_impl"], + emitted_by=ctx["staking_router"], + events_chain=["LogScriptCall", "Upgraded", "MaxTopUpPerBlockGweiSet"] + + ["RoleGranted"] * len(sr_grants) + + ["Initialized"], + ) + max_top_up_event = _single_event(dg_events[2], "MaxTopUpPerBlockGweiSet") + assert max_top_up_event["maxTopUpPerBlockGwei"] == ctx["max_top_up_per_block_gwei"] + assert convert.to_address(max_top_up_event["setBy"]) == convert.to_address(ctx["agent"]) + _assert_emitted_by(max_top_up_event, ctx["staking_router"]) + role_grants = _event_list(dg_events[2], "RoleGranted") + assert len(role_grants) == len(sr_grants) + for role_granted_event, (role_hash, account) in zip(role_grants, sr_grants): + assert _normalize_role(role_granted_event["role"]) == _normalize_role(role_hash) + assert convert.to_address(role_granted_event["account"]) == convert.to_address(account) + assert convert.to_address(role_granted_event["sender"]) == convert.to_address(ctx["agent"]) + _assert_emitted_by(role_granted_event, ctx["staking_router"]) + initialized_event = _single_event(dg_events[2], "Initialized") + assert initialized_event["version"] == SR_INITIALIZED_VERSION + _assert_emitted_by(initialized_event, ctx["staking_router"]) + + # 1.4. Upgrade AccountingOracle implementation and call finalizeUpgrade_v5 + ao_chain = ["LogScriptCall", "Upgraded", "ContractVersionSet", "ConsensusVersionSet"] + validate_proxy_upgrade_event( + dg_events[3], ctx["accounting_oracle_impl"], emitted_by=ctx["accounting_oracle"], events_chain=ao_chain + ) + validate_contract_version_set_event( + dg_events[3], AO_CONTRACT_VERSION, emitted_by=ctx["accounting_oracle"], events_chain=ao_chain + ) + validate_consensus_version_set_event( + dg_events[3], + AO_CONSENSUS_VERSION, + AO_CONSENSUS_VERSION - 1, + emitted_by=ctx["accounting_oracle"], + events_chain=ao_chain, + ) + + # 1.5. Upgrade ValidatorsExitBusOracle implementation and call finalizeUpgrade_v3 + vebo_chain = [ + "LogScriptCall", + "Upgraded", + "ContractVersionSet", + "ConsensusVersionSet", + "SetMaxValidatorsPerReport", + "ExitBalanceLimitSet", + ] + validate_proxy_upgrade_event( + dg_events[4], + ctx["validators_exit_bus_oracle_impl"], + emitted_by=ctx["validators_exit_bus_oracle"], + events_chain=vebo_chain, + ) + validate_contract_version_set_event( + dg_events[4], + VEBO_CONTRACT_VERSION, + emitted_by=ctx["validators_exit_bus_oracle"], + events_chain=vebo_chain, + ) + validate_consensus_version_set_event( + dg_events[4], + VEBO_CONSENSUS_VERSION, + VEBO_CONSENSUS_VERSION - 1, + emitted_by=ctx["validators_exit_bus_oracle"], + events_chain=vebo_chain, + ) + set_max_validators_event = _single_event(dg_events[4], "SetMaxValidatorsPerReport") + assert set_max_validators_event["maxValidatorsPerReport"] == VEBO_MAX_VALIDATORS_PER_REPORT + _assert_emitted_by(set_max_validators_event, ctx["validators_exit_bus_oracle"]) + exit_balance_limit_event = _single_event(dg_events[4], "ExitBalanceLimitSet") + assert exit_balance_limit_event["maxExitBalanceEth"] == VALIDATORS_EXIT_BUS_MAX_EXIT_BALANCE_ETH + assert exit_balance_limit_event["balancePerFrameEth"] == VALIDATORS_EXIT_BUS_BALANCE_PER_FRAME_ETH + assert exit_balance_limit_event["frameDurationInSec"] == VALIDATORS_EXIT_BUS_FRAME_DURATION_IN_SEC + _assert_emitted_by(exit_balance_limit_event, ctx["validators_exit_bus_oracle"]) + + # 1.6. Upgrade Accounting implementation + validate_proxy_upgrade_event(dg_events[5], ctx["accounting_impl"], emitted_by=ctx["accounting"]) + + # 1.7. Upgrade WithdrawalVault implementation and call finalizeUpgrade_v3 + wv_chain = ["LogScriptCall", "Upgraded", "ContractVersionSet"] + validate_proxy_upgrade_event( + dg_events[6], ctx["withdrawal_vault_impl"], emitted_by=ctx["withdrawal_vault"], events_chain=wv_chain + ) + validate_contract_version_set_event( + dg_events[6], + WITHDRAWAL_VAULT_CONTRACT_VERSION, + emitted_by=ctx["withdrawal_vault"], + events_chain=wv_chain, + ) + + # 1.8. Grant Aragon APP_MANAGER_ROLE to the AGENT + validate_events_chain([e.name for e in dg_events[7]], ["LogScriptCall", "SetPermission"]) + set_permission_event = _single_event(dg_events[7], "SetPermission") + assert convert.to_address(set_permission_event["entity"]) == convert.to_address(ctx["agent"]) + assert convert.to_address(set_permission_event["app"]) == convert.to_address(ctx["aragon_kernel"]) + assert set_permission_event["role"] == APP_MANAGER_ROLE + assert set_permission_event["allowed"] is True + _assert_emitted_by(set_permission_event, ctx["acl"]) + + # 1.9. Set Lido implementation in Kernel + validate_events_chain([e.name for e in dg_events[8]], ["LogScriptCall", "SetApp"]) + set_app_event = _single_event(dg_events[8], "SetApp") + assert set_app_event["appId"] == ctx["lido_app_id"] + assert convert.to_address(set_app_event["app"]) == convert.to_address(ctx["lido_impl"]) + _assert_emitted_by(set_app_event, ctx["aragon_kernel"]) + + # 1.10. Revoke Aragon APP_MANAGER_ROLE from the AGENT + validate_events_chain([e.name for e in dg_events[9]], ["LogScriptCall", "SetPermission"]) + set_permission_event = _single_event(dg_events[9], "SetPermission") + assert convert.to_address(set_permission_event["entity"]) == convert.to_address(ctx["agent"]) + assert convert.to_address(set_permission_event["app"]) == convert.to_address(ctx["aragon_kernel"]) + assert set_permission_event["role"] == APP_MANAGER_ROLE + assert set_permission_event["allowed"] is False + _assert_emitted_by(set_permission_event, ctx["acl"]) + + # 1.11. Create Aragon BUFFER_RESERVE_MANAGER_ROLE and grant role manager to the AGENT + validate_events_chain( + [e.name for e in dg_events[10]], + ["LogScriptCall", "SetPermission", "ChangePermissionManager"], + ) + set_permission_event = _single_event(dg_events[10], "SetPermission") + assert convert.to_address(set_permission_event["entity"]) == convert.to_address(ctx["agent"]) + assert convert.to_address(set_permission_event["app"]) == convert.to_address(ctx["lido"]) + assert set_permission_event["role"] == BUFFER_RESERVE_MANAGER_ROLE + assert set_permission_event["allowed"] is True + _assert_emitted_by(set_permission_event, ctx["acl"]) + change_permission_manager_event = _single_event(dg_events[10], "ChangePermissionManager") + assert convert.to_address(change_permission_manager_event["app"]) == convert.to_address(ctx["lido"]) + assert change_permission_manager_event["role"] == BUFFER_RESERVE_MANAGER_ROLE + assert convert.to_address(change_permission_manager_event["manager"]) == convert.to_address(ctx["agent"]) + _assert_emitted_by(change_permission_manager_event, ctx["acl"]) + + # 1.12. Call finalizeUpgrade_v4 on Lido + lido_finalize_chain = ["LogScriptCall", "ContractVersionSet", "DepositsReserveTargetSet"] + validate_contract_version_set_event( + dg_events[11], LIDO_CONTRACT_VERSION, emitted_by=ctx["lido"], events_chain=lido_finalize_chain + ) + deposits_reserve_target_event = _single_event(dg_events[11], "DepositsReserveTargetSet") + assert deposits_reserve_target_event["depositsReserveTarget"] == ctx["lido_deposits_reserve_target"] + _assert_emitted_by(deposits_reserve_target_event, ctx["lido"]) + + # 1.13. Grant Staking Router STAKING_MODULE_SHARE_MANAGE_ROLE to EasyTrack executor + validate_role_grant_event( + dg_events[12], + STAKING_MODULE_SHARE_MANAGE_ROLE, + ctx["easytrack_evm_script_executor"], + sender=ctx["agent"], + emitted_by=ctx["staking_router"], + ) + + # 1.14. Revoke Staking Router STAKING_MODULE_UNVETTING_ROLE from old DSM + validate_role_revoke_event( + dg_events[13], + STAKING_MODULE_UNVETTING_ROLE, + ctx["old_deposit_security_module"], + sender=ctx["agent"], + emitted_by=ctx["staking_router"], + ) + + # 1.15. Grant Staking Router STAKING_MODULE_UNVETTING_ROLE to new DSM + validate_role_grant_event( + dg_events[14], + STAKING_MODULE_UNVETTING_ROLE, + ctx["new_deposit_security_module"], + sender=ctx["agent"], + emitted_by=ctx["staking_router"], + ) + + # 1.16. Grant TWG TW_EXIT_LIMIT_MANAGER_ROLE to AGENT + validate_role_grant_event( + dg_events[15], + TW_EXIT_LIMIT_MANAGER_ROLE, + ctx["agent"], + sender=ctx["agent"], + emitted_by=ctx["triggerable_withdrawals_gateway"], + ) + + # 1.17. Set TWG exit request limits + validate_events_chain([e.name for e in dg_events[16]], ["LogScriptCall", "ExitRequestsLimitSet"]) + exit_requests_limit_set_event = _single_event(dg_events[16], "ExitRequestsLimitSet") + assert exit_requests_limit_set_event["maxExitRequestsLimit"] == TW_MAX_EXIT_REQUESTS + assert exit_requests_limit_set_event["exitsPerFrame"] == TW_EXITS_PER_FRAME + assert exit_requests_limit_set_event["frameDurationInSec"] == TW_FRAME_DURATION_IN_SEC + _assert_emitted_by(exit_requests_limit_set_event, ctx["triggerable_withdrawals_gateway"]) + + # 1.18. Register CircuitBreaker pauser for ConsolidationGateway + validate_circuit_breaker_registration_event( + dg_events[17], + circuit_breaker=ctx["circuit_breaker"], + pausable=ctx["consolidation_gateway"], + pauser=ctx["circuit_breaker_committee"], + ) + + # 1.19. Register CircuitBreaker pauser for TopUpGateway + validate_circuit_breaker_registration_event( + dg_events[18], + circuit_breaker=ctx["circuit_breaker"], + pausable=ctx["top_up_gateway"], + pauser=ctx["circuit_breaker_committee"], + ) + + # ------------------------- CSM ------------------------------ + # 1.20. Upgrade CSM to v3 and call finalizeUpgradeV3 + validate_proxy_upgrade_event( + dg_events[19], ctx["csm_impl"], emitted_by=ctx["csm"], + events_chain=["LogScriptCall", "Upgraded", "Initialized"], + ) + assert _single_event(dg_events[19], "Initialized")["version"] == CSM_INITIALIZED_VERSION + _assert_emitted_by(_single_event(dg_events[19], "Initialized"), ctx["csm"]) + + # 1.21. Upgrade CSM ParametersRegistry to v3 and call finalizeUpgradeV3 + validate_proxy_upgrade_event( + dg_events[20], ctx["cs_parameters_registry_impl"], emitted_by=ctx["cs_parameters_registry"], + events_chain=["LogScriptCall", "Upgraded", "Initialized"], + ) + assert _single_event(dg_events[20], "Initialized")["version"] == CSM_INITIALIZED_VERSION + _assert_emitted_by(_single_event(dg_events[20], "Initialized"), ctx["cs_parameters_registry"]) + + # 1.22. Upgrade CSM FeeOracle to v3 and call finalizeUpgradeV3 + fo_chain = ["LogScriptCall", "Upgraded", "ConsensusVersionSet", "ContractVersionSet"] + validate_proxy_upgrade_event( + dg_events[21], ctx["cs_fee_oracle_impl"], emitted_by=ctx["cs_fee_oracle"], events_chain=fo_chain + ) + validate_consensus_version_set_event( + dg_events[21], + ctx["cs_fee_oracle_consensus_version"], + initial_cs_fee_oracle_consensus_version, + emitted_by=ctx["cs_fee_oracle"], + events_chain=fo_chain, + ) + validate_contract_version_set_event( + dg_events[21], CS_FEE_ORACLE_CONTRACT_VERSION, emitted_by=ctx["cs_fee_oracle"], events_chain=fo_chain + ) + + # 1.23. Upgrade CSM VettedGate implementation + validate_proxy_upgrade_event(dg_events[22], ctx["cs_vetted_gate_impl"], emitted_by=ctx["cs_vetted_gate"]) + + # 1.24. Upgrade CSM Accounting to v3 and call finalizeUpgradeV3 + validate_proxy_upgrade_event( + dg_events[23], ctx["cs_accounting_impl"], emitted_by=ctx["cs_accounting"], + events_chain=["LogScriptCall", "Upgraded", "Initialized"], + ) + assert _single_event(dg_events[23], "Initialized")["version"] == CSM_INITIALIZED_VERSION + _assert_emitted_by(_single_event(dg_events[23], "Initialized"), ctx["cs_accounting"]) + + # 1.25. Upgrade CSM FeeDistributor to v3 and call finalizeUpgradeV3 + validate_proxy_upgrade_event( + dg_events[24], ctx["cs_fee_distributor_impl"], emitted_by=ctx["cs_fee_distributor"], + events_chain=["LogScriptCall", "Upgraded", "Initialized"], + ) + assert _single_event(dg_events[24], "Initialized")["version"] == CSM_INITIALIZED_VERSION + _assert_emitted_by(_single_event(dg_events[24], "Initialized"), ctx["cs_fee_distributor"]) + + # 1.26. Upgrade CSM ExitPenalties implementation + validate_proxy_upgrade_event(dg_events[25], ctx["cs_exit_penalties_impl"], emitted_by=ctx["cs_exit_penalties"]) + + # 1.27. Upgrade CSM ValidatorStrikes implementation + validate_proxy_upgrade_event(dg_events[26], ctx["cs_validator_strikes_impl"], emitted_by=ctx["cs_validator_strikes"]) + + # 1.28. Point CSM ValidatorStrikes to the New CSM Ejector + validate_events_chain([e.name for e in dg_events[27]], ["LogScriptCall", "EjectorSet"]) + ejector_set_event = _single_event(dg_events[27], "EjectorSet") + assert convert.to_address(ejector_set_event["ejector"]) == convert.to_address(ctx["new_csm_ejector"]) + _assert_emitted_by(ejector_set_event, ctx["cs_validator_strikes"]) + + # 1.29. Revoke CSM REPORT_EL_REWARDS_STEALING_PENALTY_ROLE from CSM Committee + validate_role_revoke_event( + dg_events[28], REPORT_EL_REWARDS_STEALING_PENALTY_ROLE, ctx["csm_committee"], + sender=ctx["agent"], emitted_by=ctx["csm"], + ) + + # 1.30. Grant CSM REPORT_GENERAL_DELAYED_PENALTY_ROLE to CSM Committee + validate_role_grant_event( + dg_events[29], REPORT_GENERAL_DELAYED_PENALTY_ROLE, ctx["csm_committee"], + sender=ctx["agent"], emitted_by=ctx["csm"], + ) + + # 1.31. Revoke CSM SETTLE_EL_REWARDS_STEALING_PENALTY_ROLE from Easy Track executor + validate_role_revoke_event( + dg_events[30], SETTLE_EL_REWARDS_STEALING_PENALTY_ROLE, ctx["easytrack_evm_script_executor"], + sender=ctx["agent"], emitted_by=ctx["csm"], + ) + + # 1.32. Grant CSM SETTLE_GENERAL_DELAYED_PENALTY_ROLE to Easy Track executor + validate_role_grant_event( + dg_events[31], SETTLE_GENERAL_DELAYED_PENALTY_ROLE, ctx["easytrack_evm_script_executor"], + sender=ctx["agent"], emitted_by=ctx["csm"], + ) + + # 1.33. Revoke CSM VERIFIER_ROLE from the Old CSM Verifier + validate_role_revoke_event( + dg_events[32], VERIFIER_ROLE, ctx["old_verifier"], sender=ctx["agent"], emitted_by=ctx["csm"], + ) + + # 1.34. Grant CSM VERIFIER_ROLE to the New CSM Verifier + validate_role_grant_event( + dg_events[33], VERIFIER_ROLE, ctx["verifier_v3"], sender=ctx["agent"], emitted_by=ctx["csm"], + ) + + # 1.35. Grant CSM REPORT_REGULAR_WITHDRAWN_VALIDATORS_ROLE to the New CSM Verifier + validate_role_grant_event( + dg_events[34], REPORT_REGULAR_WITHDRAWN_VALIDATORS_ROLE, ctx["verifier_v3"], + sender=ctx["agent"], emitted_by=ctx["csm"], + ) + + # 1.36. Grant CSM REPORT_SLASHED_WITHDRAWN_VALIDATORS_ROLE to Easy Track executor + validate_role_grant_event( + dg_events[35], REPORT_SLASHED_WITHDRAWN_VALIDATORS_ROLE, ctx["easytrack_evm_script_executor"], + sender=ctx["agent"], emitted_by=ctx["csm"], + ) + + # 1.37. Revoke CSM CREATE_NODE_OPERATOR_ROLE from the Old CSM PermissionlessGate + validate_role_revoke_event( + dg_events[36], CREATE_NODE_OPERATOR_ROLE, ctx["old_permissionless_gate"], + sender=ctx["agent"], emitted_by=ctx["csm"], + ) + + # 1.38. Grant CSM CREATE_NODE_OPERATOR_ROLE to the New CSM PermissionlessGate + validate_role_grant_event( + dg_events[37], CREATE_NODE_OPERATOR_ROLE, ctx["new_permissionless_gate"], + sender=ctx["agent"], emitted_by=ctx["csm"], + ) + + # 1.39. Revoke VettedGate START_REFERRAL_SEASON_ROLE from AGENT + validate_role_revoke_event( + dg_events[38], START_REFERRAL_SEASON_ROLE, ctx["agent"], + sender=ctx["agent"], emitted_by=ctx["cs_vetted_gate"], + ) + + # 1.40. Revoke VettedGate END_REFERRAL_SEASON_ROLE from CSM Committee + validate_role_revoke_event( + dg_events[39], END_REFERRAL_SEASON_ROLE, ctx["csm_committee"], + sender=ctx["agent"], emitted_by=ctx["cs_vetted_gate"], + ) + + # 1.41. Set name Identified Community Stakers for CSM VettedGate gate + validate_gate_name_set_event( + dg_events[40], IDENTIFIED_COMMUNITY_STAKERS_GATE_NAME, emitted_by=ctx["cs_vetted_gate"] + ) + + # 1.42. Unregister CircuitBreaker pauser for Old CSM Verifier + validate_circuit_breaker_unregistration_event( + dg_events[41], + circuit_breaker=ctx["circuit_breaker"], + pausable=ctx["old_verifier"], + previous_pauser=ctx["csm_committee"], + ) + + # 1.43. Unregister CircuitBreaker pauser for Old CSM Ejector + validate_circuit_breaker_unregistration_event( + dg_events[42], + circuit_breaker=ctx["circuit_breaker"], + pausable=ctx["config_old_csm_ejector"], + previous_pauser=ctx["csm_committee"], + ) + + # 1.44. Register CircuitBreaker pauser for New CSM Verifier + validate_circuit_breaker_registration_event( + dg_events[43], circuit_breaker=ctx["circuit_breaker"], pausable=ctx["verifier_v3"], + pauser=ctx["csm_committee"], + ) + + # 1.45. Register CircuitBreaker pauser for New CSM Ejector + validate_circuit_breaker_registration_event( + dg_events[44], circuit_breaker=ctx["circuit_breaker"], pausable=ctx["new_csm_ejector"], + pauser=ctx["csm_committee"], + ) + + # 1.46. Register CircuitBreaker pauser for CSM Identified DVT Cluster gate + validate_circuit_breaker_registration_event( + dg_events[45], circuit_breaker=ctx["circuit_breaker"], pausable=ctx["identified_dvt_cluster_gate"], + pauser=ctx["csm_committee"], + ) + + # 1.47. Grant CSM CREATE_NODE_OPERATOR_ROLE to Identified DVT Cluster gate + validate_role_grant_event( + dg_events[46], CREATE_NODE_OPERATOR_ROLE, ctx["identified_dvt_cluster_gate"], + sender=ctx["agent"], emitted_by=ctx["csm"], + ) + + # 1.48. Grant CSM Accounting SET_BOND_CURVE_ROLE to Identified DVT Cluster gate + validate_role_grant_event( + dg_events[47], SET_BOND_CURVE_ROLE, ctx["identified_dvt_cluster_gate"], + sender=ctx["agent"], emitted_by=ctx["cs_accounting"], + ) + + # 1.49. Grant CSM Accounting MANAGE_BOND_CURVES_ROLE to Identified DVT Cluster curve setup + validate_role_grant_event( + dg_events[48], MANAGE_BOND_CURVES_ROLE, ctx["identified_dvt_cluster_curve_setup"], + sender=ctx["agent"], emitted_by=ctx["cs_accounting"], + ) + + # 1.50. Grant CSM ParametersRegistry MANAGE_CURVE_PARAMETERS_ROLE to Identified DVT Cluster curve setup + validate_role_grant_event( + dg_events[49], MANAGE_CURVE_PARAMETERS_ROLE, ctx["identified_dvt_cluster_curve_setup"], + sender=ctx["agent"], emitted_by=ctx["cs_parameters_registry"], + ) + + # 1.51. Execute Identified DVT Cluster curve setup + validate_events_chain( + [e.name for e in dg_events[50]], + [ + "LogScriptCall", + "BondCurveAdded", + "KeyRemovalChargeSet", + "GeneralDelayedPenaltyAdditionalFineSet", + "QueueConfigSet", + "RewardShareDataSet", + "AllowedExitDelaySet", + "ExitDelayFeeSet", + "RoleRevoked", + "RoleRevoked", + "BondCurveDeployed", + ], + ) + bond_curve_id = ctx["identified_dvt_cluster_bond_curve_id"] + bond_curve_added_event = _single_event(dg_events[50], "BondCurveAdded") + assert bond_curve_added_event["curveId"] == bond_curve_id + assert bond_curve_added_event["bondCurveIntervals"] == IDVT_BOND_CURVE + _assert_emitted_by(bond_curve_added_event, ctx["cs_accounting"]) + key_removal_charge_set_event = _single_event(dg_events[50], "KeyRemovalChargeSet") + assert key_removal_charge_set_event["curveId"] == bond_curve_id + assert key_removal_charge_set_event["keyRemovalCharge"] == IDVT_KEY_REMOVAL_CHARGE + _assert_emitted_by(key_removal_charge_set_event, ctx["cs_parameters_registry"]) + general_delayed_penalty_fine_event = _single_event(dg_events[50], "GeneralDelayedPenaltyAdditionalFineSet") + assert general_delayed_penalty_fine_event["curveId"] == bond_curve_id + assert general_delayed_penalty_fine_event["fine"] == IDVT_GENERAL_DELAYED_PENALTY_FINE + _assert_emitted_by(general_delayed_penalty_fine_event, ctx["cs_parameters_registry"]) + queue_config_set_event = _single_event(dg_events[50], "QueueConfigSet") + assert queue_config_set_event["curveId"] == bond_curve_id + assert queue_config_set_event["priority"] == IDVT_QUEUE_PRIORITY + assert queue_config_set_event["maxDeposits"] == IDVT_QUEUE_MAX_DEPOSITS + _assert_emitted_by(queue_config_set_event, ctx["cs_parameters_registry"]) + reward_share_data_set_event = _single_event(dg_events[50], "RewardShareDataSet") + assert reward_share_data_set_event["curveId"] == bond_curve_id + assert reward_share_data_set_event["data"] == IDVT_REWARD_SHARE_DATA + _assert_emitted_by(reward_share_data_set_event, ctx["cs_parameters_registry"]) + allowed_exit_delay_set_event = _single_event(dg_events[50], "AllowedExitDelaySet") + assert allowed_exit_delay_set_event["curveId"] == bond_curve_id + assert allowed_exit_delay_set_event["delay"] == IDVT_ALLOWED_EXIT_DELAY + _assert_emitted_by(allowed_exit_delay_set_event, ctx["cs_parameters_registry"]) + exit_delay_fee_event = _single_event(dg_events[50], "ExitDelayFeeSet") + assert exit_delay_fee_event["curveId"] == bond_curve_id + assert exit_delay_fee_event["penalty"] == IDVT_EXIT_DELAY_FEE + _assert_emitted_by(exit_delay_fee_event, ctx["cs_parameters_registry"]) + role_revokes = _event_list(dg_events[50], "RoleRevoked") + assert len(role_revokes) == 2 + assert _normalize_role(role_revokes[0]["role"]) == MANAGE_BOND_CURVES_ROLE.replace("0x", "") + assert convert.to_address(role_revokes[0]["account"]) == convert.to_address( + ctx["identified_dvt_cluster_curve_setup"] + ) + assert convert.to_address(role_revokes[0]["sender"]) == convert.to_address( + ctx["identified_dvt_cluster_curve_setup"] + ) + _assert_emitted_by(role_revokes[0], ctx["cs_accounting"]) + assert _normalize_role(role_revokes[1]["role"]) == MANAGE_CURVE_PARAMETERS_ROLE.replace("0x", "") + assert convert.to_address(role_revokes[1]["account"]) == convert.to_address( + ctx["identified_dvt_cluster_curve_setup"] + ) + assert convert.to_address(role_revokes[1]["sender"]) == convert.to_address( + ctx["identified_dvt_cluster_curve_setup"] + ) + _assert_emitted_by(role_revokes[1], ctx["cs_parameters_registry"]) + bond_curve_deployed_event = _single_event(dg_events[50], "BondCurveDeployed") + assert bond_curve_deployed_event["curveId"] == bond_curve_id + _assert_emitted_by(bond_curve_deployed_event, ctx["identified_dvt_cluster_curve_setup"]) + + # 1.52. Grant CSM ParametersRegistry MANAGE_GENERAL_PENALTIES_AND_CHARGES_ROLE to CSM Committee + validate_role_grant_event( + dg_events[51], MANAGE_GENERAL_PENALTIES_AND_CHARGES_ROLE, ctx["csm_committee"], + sender=ctx["agent"], emitted_by=ctx["cs_parameters_registry"], + ) + + # 1.53. Revoke Burner REQUEST_BURN_SHARES_ROLE from CSM Accounting + validate_role_revoke_event( + dg_events[52], REQUEST_BURN_SHARES_ROLE, ctx["cs_accounting"], + sender=ctx["agent"], emitted_by=ctx["burner"], + ) + + # 1.54. Grant Burner REQUEST_BURN_MY_STETH_ROLE to CSM Accounting + validate_role_grant_event( + dg_events[53], REQUEST_BURN_MY_STETH_ROLE, ctx["cs_accounting"], + sender=ctx["agent"], emitted_by=ctx["burner"], + ) + + # 1.55. Revoke TWG ADD_FULL_WITHDRAWAL_REQUEST_ROLE from the Old CSM Ejector + validate_role_revoke_event( + dg_events[54], ADD_FULL_WITHDRAWAL_REQUEST_ROLE, ctx["config_old_csm_ejector"], + sender=ctx["agent"], emitted_by=ctx["triggerable_withdrawals_gateway"], + ) + + # 1.56. Grant TWG ADD_FULL_WITHDRAWAL_REQUEST_ROLE to the New CSM Ejector + validate_role_grant_event( + dg_events[55], ADD_FULL_WITHDRAWAL_REQUEST_ROLE, ctx["new_csm_ejector"], + sender=ctx["agent"], emitted_by=ctx["triggerable_withdrawals_gateway"], + ) + + # -------------------- Curated Module ------------------------ + # 1.57. Add Curated Module v2 to StakingRouter + validate_module_add( + dg_events[56], ctx["curated_module_item"], emitted_by=ctx["staking_router"], sender=ctx["agent"] + ) + + # 1.58. Grant Burner REQUEST_BURN_MY_STETH_ROLE to Curated Accounting + validate_role_grant_event( + dg_events[57], REQUEST_BURN_MY_STETH_ROLE, ctx["curated_accounting"], + sender=ctx["agent"], emitted_by=ctx["burner"], + ) + + # 1.59. Grant TWG ADD_FULL_WITHDRAWAL_REQUEST_ROLE to Curated Ejector + validate_role_grant_event( + dg_events[58], ADD_FULL_WITHDRAWAL_REQUEST_ROLE, ctx["curated_ejector"], + sender=ctx["agent"], emitted_by=ctx["triggerable_withdrawals_gateway"], + ) + + # 1.60. Grant CM RESUME_ROLE to AGENT + validate_role_grant_event( + dg_events[59], RESUME_ROLE, ctx["agent"], sender=ctx["agent"], emitted_by=ctx["curated_module"], + ) + + # 1.61. Resume Curated Module v2 + validate_events_chain([e.name for e in dg_events[60]], ["LogScriptCall", "Resumed"]) + _assert_emitted_by(_single_event(dg_events[60], "Resumed"), ctx["curated_module"]) + + # 1.62. Revoke CM RESUME_ROLE from AGENT + validate_role_revoke_event( + dg_events[61], RESUME_ROLE, ctx["agent"], sender=ctx["agent"], emitted_by=ctx["curated_module"], + ) + + # 1.63. Update Curated HashConsensus initial epoch + validate_events_chain([e.name for e in dg_events[62]], ["LogScriptCall", "FrameConfigSet"]) + frame_config_set_event = _single_event(dg_events[62], "FrameConfigSet") + assert frame_config_set_event["newInitialEpoch"] == ctx["curated_hash_consensus_initial_epoch"] + assert frame_config_set_event["newEpochsPerFrame"] == ctx["curated_epochs_per_frame"] + _assert_emitted_by(frame_config_set_event, ctx["curated_hash_consensus"]) + + # 1.64. Register CircuitBreaker pauser for Curated Module v2 + validate_circuit_breaker_registration_event( + dg_events[63], circuit_breaker=ctx["circuit_breaker"], pausable=ctx["curated_module"], + pauser=ctx["curated_circuit_breaker_pauser"], + ) + + # 1.65. Register CircuitBreaker pauser for Curated Accounting + validate_circuit_breaker_registration_event( + dg_events[64], circuit_breaker=ctx["circuit_breaker"], pausable=ctx["curated_accounting"], + pauser=ctx["curated_circuit_breaker_pauser"], + ) + + # 1.66. Register CircuitBreaker pauser for Curated FeeOracle + validate_circuit_breaker_registration_event( + dg_events[65], circuit_breaker=ctx["circuit_breaker"], pausable=ctx["curated_fee_oracle"], + pauser=ctx["curated_circuit_breaker_pauser"], + ) + + # 1.67. Register CircuitBreaker pauser for Curated Verifier + validate_circuit_breaker_registration_event( + dg_events[66], circuit_breaker=ctx["circuit_breaker"], pausable=ctx["curated_verifier"], + pauser=ctx["curated_circuit_breaker_pauser"], + ) + + # 1.68. Register CircuitBreaker pauser for Curated Ejector + validate_circuit_breaker_registration_event( + dg_events[67], circuit_breaker=ctx["circuit_breaker"], pausable=ctx["curated_ejector"], + pauser=ctx["curated_circuit_breaker_pauser"], + ) + + # ---------------------- Finish upgrade ---------------------- + # 1.69. Call UpgradeTemplate.finishUpgrade (also migrates the sanity checker baseline snapshot) + validate_events_chain( + [e.name for e in dg_events[68]], + ["LogScriptCall", "BaselineSnapshotMigrated", "UpgradeFinished", "ScriptResult", "Executed"], + ) + _assert_emitted_by( + _single_event(dg_events[68], "BaselineSnapshotMigrated"), ctx["oracle_report_sanity_checker"] + ) + _assert_emitted_by(_single_event(dg_events[68], "UpgradeFinished"), upgrade_template) + + # ===================================================================== + # ================= After DG proposal executed checks ================= + # ===================================================================== + assert timelock.getProposalDetails(expected_dg_proposal_id)["status"] == PROPOSAL_STATUS["executed"] + + # Core upgrade landed. + assert interface.AccountingOracle(ctx["accounting_oracle"]).getConsensusVersion() == AO_CONSENSUS_VERSION + assert ( + interface.ValidatorsExitBusOracle(ctx["validators_exit_bus_oracle"]).getConsensusVersion() + == VEBO_CONSENSUS_VERSION + ) + assert interface.WithdrawalVault(ctx["withdrawal_vault"]).getContractVersion() == WITHDRAWAL_VAULT_CONTRACT_VERSION + assert interface.Lido(ctx["lido"]).getContractVersion() == LIDO_CONTRACT_VERSION + assert interface.CSFeeOracle(ctx["cs_fee_oracle"]).getConsensusVersion() == ctx["cs_fee_oracle_consensus_version"] + + # Staking Router role migration & new roles. + assert staking_router.hasRole(STAKING_MODULE_SHARE_MANAGE_ROLE, ctx["easytrack_evm_script_executor"]) + assert staking_router.hasRole(STAKING_MODULE_UNVETTING_ROLE, ctx["new_deposit_security_module"]) + assert not staking_router.hasRole(STAKING_MODULE_UNVETTING_ROLE, ctx["old_deposit_security_module"]) + + # Curated Module v2 registered and resumed. + assert staking_router.getStakingModulesCount() == ctx["curated_module_item"].id + curated_module = interface.CSModule(ctx["curated_module"]) + assert curated_module.isPaused() is False + + # Easy Track factory set updated (also checked right after the vote). + current_factories = easy_track.getEVMScriptFactories() + for factory in old_easy_track_factories: + assert factory not in current_factories + for factory in new_easy_track_factories: + assert factory in current_factories From cf232bc5869498328c29c011248a7b77567c8270 Mon Sep 17 00:00:00 2001 From: KRogLA Date: Thu, 9 Jul 2026 15:28:53 +0200 Subject: [PATCH 07/30] fix: bump srv3 vote ipfs description --- scripts/upgrade_2026_07_15_srv3_cmv2.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/upgrade_2026_07_15_srv3_cmv2.py b/scripts/upgrade_2026_07_15_srv3_cmv2.py index 686814cb..08b845be 100644 --- a/scripts/upgrade_2026_07_15_srv3_cmv2.py +++ b/scripts/upgrade_2026_07_15_srv3_cmv2.py @@ -120,10 +120,10 @@ DG_PROPOSAL_METADATA = "Activate Staking Router v3 + Curated Module v2 + Community Staking Module v3" DG_SUBMISSION_DESCRIPTION = "1. Submit a Dual Governance proposal to activate Staking Router v3 + Curated Module v2 + Community Staking Module v3" IPFS_DESCRIPTION = """ -1. **Activate Staking Router v3**, including protocol contract upgrades and Dual Governance execution setup. Items 1.1-1.18. -2. **Upgrade Community Staking Module to v3**, including CSM contract upgrades, role updates and identified DVT cluster setup. Items 1.19-1.52. -3. **Add and configure Curated Module v2**. Items 1.53-1.64. -4. **Finalize the protocol upgrade**. Item 1.65. +1. **Activate Staking Router v3**, including protocol contract upgrades and Dual Governance execution setup. Items 1.1-1.19. +2. **Upgrade Community Staking Module to v3**, including CSM contract upgrades, role updates and identified DVT cluster setup. Items 1.20-1.56. +3. **Add and configure Curated Module v2**. Items 1.57-1.68. +4. **Finalize the protocol upgrade**. Item 1.69. 5. **Update Easy Track factories for CSM v3 and Curated Module v2 operations**. Items 2-12. """ From 54f6700d4dd09a45761a287b31b2b62bb86fa50b Mon Sep 17 00:00:00 2001 From: KRogLA Date: Thu, 9 Jul 2026 17:31:55 +0200 Subject: [PATCH 08/30] fix: update mainnet addresses --- configs/config_mainnet.py | 52 +++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/configs/config_mainnet.py b/configs/config_mainnet.py index 953f8305..3dde12d7 100644 --- a/configs/config_mainnet.py +++ b/configs/config_mainnet.py @@ -116,7 +116,7 @@ # LidoLocator LIDO_LOCATOR = "0xC1d0b3DE6792Bf6b4b37EccdcC24e45978Cfd2Eb" -LIDO_LOCATOR_IMPL = "0x9E6b222a71644484b6E9eb67bD8400128e0c3fb8" # SRV3 +LIDO_LOCATOR_IMPL = "0x0360002bf51DCae1c0267aE0AFDaBacAF7De686b" # SRV3 # Other upgrade addresses LIDO_V2_UPGRADE_TEMPLATE = "0xa818fF9EC93122Bf9401ab4340C42De638CD600a" @@ -129,7 +129,7 @@ WITHDRAWAL_CREDENTIALS = "0x010000000000000000000000b9d7934878b5fb9610b3fe8a5e441e8fad7e293f" # Lido -LIDO_IMPL = "0x59deCAF1289BbF615Ac8b1024127eC7FF842aB01" # SRV3 +LIDO_IMPL = "0x028271E30a695c0527A0C50cA30603feD004cDb0" # SRV3 # see Lido's proxy appId() LIDO_ARAGON_APP_ID = "0x3ca7c3e38968823ccb4c78ea688df41356f182ae1d159e4ee608d30d68cef320" LIDO_MAX_STAKE_LIMIT_ETH = 150_000 @@ -169,7 +169,7 @@ # Values mirror UpgradeConfig.getCuratedModuleConfig() (see core deployed-*.json `curatedModule`). # It is appended after the existing 3 modules (Curated=1, SimpleDVT=2, CSM=3), so its id is 4. CURATED_V2_STAKING_MODULE_ID = 4 -CURATED_V2_STAKING_MODULE_ADDRESS = "0x1A54c1b37CB228e506838486592D54Bec5Bb3747" # SRV3 +CURATED_V2_STAKING_MODULE_ADDRESS = "0xDa5F930cE326EB5205085D66c72A4E79d60cB8C1" # SRV3 CURATED_V2_STAKING_MODULE_NAME = "curated-onchain-v2" CURATED_V2_STAKING_MODULE_TARGET_SHARE_BP = 10000 CURATED_V2_STAKING_MODULE_PRIORITY_EXIT_SHARE_THRESHOLD = 10000 @@ -177,10 +177,10 @@ CURATED_V2_STAKING_MODULE_TREASURY_FEE_BP = 600 CURATED_V2_STAKING_MODULE_MAX_DEPOSITS_PER_BLOCK = 100 CURATED_V2_STAKING_MODULE_MIN_DEPOSITS_BLOCK_DISTANCE = 75 -CURATED_V2_ACCOUNTING = "0xFfFEF82624cf7ad1300D084aA547DDa828a95eAd" # SRV3 -CURATED_V2_FEE_ORACLE = "0xB4214247C3A64d780Ae4e42e1441863B7Af0f73A" # SRV3 -CURATED_V2_VERIFIER = "0x4A19e9496B21c438c7f264F0fEF8A168DF297633" # SRV3 -CURATED_V2_EJECTOR = "0xdC9058e6D8b71Adc71306De8d8E7335e414aB7A1" # SRV3 +CURATED_V2_ACCOUNTING = "0x2F91e3A8C5d6593bf4F8403fCfeCcd62dF59f6F6" # SRV3 +CURATED_V2_FEE_ORACLE = "0x8EeFCdbD984c30E472BcbF545783D051CB5114e5" # SRV3 +CURATED_V2_VERIFIER = "0xC392F457960f1B13Ebaf1aa6C065479dD507E1E3" # SRV3 +CURATED_V2_EJECTOR = "0xe181A377A2d2BDE9A83f1474BC3DB7A412de091E" # SRV3 # CuratedModuleConfig.circuitBreakerPauser — the vote registers it as pauser # for all five CM v2 pausables on the CircuitBreaker CURATED_V2_CIRCUIT_BREAKER_PAUSER = "0x2570e0b22AD904501dfB0d49575991ACB801dD91" # SRV3 @@ -238,7 +238,7 @@ EXIT_EVENTS_LOOKBACK_WINDOW_IN_SLOTS = 14 * 7200 # 14 days # OracleReportSanityChecker -ORACLE_REPORT_SANITY_CHECKER = "0xD63E39dD4EC7BFB901C7a77aa0470E1D9aD67FF8" # SRV3 +ORACLE_REPORT_SANITY_CHECKER = "0x147f8d3cf3004FAf9Bf94E88B54b6C06De507be9" # SRV3 APPEARED_VALIDATORS_PER_DAY_LIMIT = 1800 EXITED_VALIDATORS_PER_DAY_LIMIT = 3600 ANNUAL_BALANCE_INCREASE_BP_LIMIT = 1000 # 10% @@ -268,7 +268,7 @@ TOTAL_COVER_SHARES_BURNT = 0 # DepositSecurityModule -DEPOSIT_SECURITY_MODULE = "0x53fa102681e10C680cb1EdEe1A15ea5630e61Ac5" # SRV3 +DEPOSIT_SECURITY_MODULE = "0xF573E9E3de1f86B085417ab294f56E7920B4e9Be" # SRV3 DEPOSIT_SECURITY_MODULE_V2 = "0xC77F8768774E1c9244BEed705C4354f2113CFc09" # dsm address before SR V2 enact DSM_MAX_OPERATORS_PER_UNVETTING = 200 DSM_PAUSE_INTENT_VALIDITY_PERIOD_BLOCKS = 6646 @@ -286,7 +286,7 @@ # AccountingOracle # and its corresponding HashConsensus ACCOUNTING_ORACLE = "0x852deD011285fe67063a08005c71a85690503Cee" -ACCOUNTING_ORACLE_IMPL = "0x839cBf32175fC81712dc2c59617C0cd2B5d421cf" # SRV3 +ACCOUNTING_ORACLE_IMPL = "0xe4f03D1107d1905B6F2A28FCb6Af221E0CE19136" # SRV3 HASH_CONSENSUS_FOR_AO = "0xD624B08C83bAECF0807Dd2c6880C3154a5F0B288" AO_EPOCHS_PER_FRAME = 225 AO_FAST_LANE_LENGTH_SLOTS = 100 @@ -295,7 +295,7 @@ # ValidatorsExitBusOracle VALIDATORS_EXIT_BUS_ORACLE = "0x0De4Ea0184c2ad0BacA7183356Aea5B8d5Bf5c6e" -VALIDATORS_EXIT_BUS_ORACLE_IMPL = "0x9812525C76ca09F30410c0402aBC612aBc3bCaDc" # SRV3 +VALIDATORS_EXIT_BUS_ORACLE_IMPL = "0x2C3386b39db89eef0F362A3BE0C05a6811E809E3" # SRV3 HASH_CONSENSUS_FOR_VEBO = "0x7FaDB6358950c5fAA66Cb5EB8eE5147De3df355a" VEBO_EPOCHS_PER_FRAME = 45 VEBO_FAST_LANE_LENGTH_SLOTS = 100 @@ -343,7 +343,7 @@ # WithdrawalsVault WITHDRAWAL_VAULT_IMPL_V1 = "0xe681faB8851484B57F32143FD78548f25fD59980" -WITHDRAWAL_VAULT_IMPL = "0xB1cF93F953586f7B9C26B61Ac9342a18C96c27a1" # SRV3 +WITHDRAWAL_VAULT_IMPL = "0xfB4521BD151BFB45DB6045D2d07e58e0f597e340" # SRV3 # EIP712StETH EIP712_STETH = "0x8F73e4C2A6D852bb4ab2A45E6a9CF5715b3228B7" @@ -351,14 +351,14 @@ # StakingRouter STAKING_ROUTER = "0xFdDf38947aFB03C621C71b06C9C70bce73f12999" -STAKING_ROUTER_IMPL = "0x6f058a2abc238D775531e1d391d7E0337d024Df7" # SRV3 +STAKING_ROUTER_IMPL = "0xDD76927045435C7605cf6f5F978cfb8CABDb5F80" # SRV3 STAKING_ROUTER_VERSION = 4 # SRV3 # Global per-block top-up cap (in Gwei), set by StakingRouter.finalizeUpgrade_v4 STAKING_ROUTER_MAX_TOP_UP_PER_BLOCK_GWEI = 3200000000000 # SRV3 # TopUpGateway -TOP_UP_GATEWAY = "0xaC10e29fFc0e2Ba64c0D91db7EA31fE45FE43E68" # SRV3 -TOP_UP_GATEWAY_IMPL = "0xF9C0092ae1f3B2E08D07ceAD0C2927318e7B3E21" # SRV3 +TOP_UP_GATEWAY = "0x3FC2C71579D80790Aaa3fc7Be8B66ac39dC57374" # SRV3 +TOP_UP_GATEWAY_IMPL = "0xb08dBc68C521cD7A4318dc4C807a42bEB20f1106" # SRV3 # initialize() params — upgrade-params-mainnet.toml [topUpGateway] TOP_UP_GATEWAY_MAX_VALIDATORS_PER_TOP_UP = 32 TOP_UP_GATEWAY_MIN_BLOCK_DISTANCE = 75 @@ -372,23 +372,23 @@ CIRCUIT_BREAKER = "0x6019CB557978296BA3C08a7B73225C0975DFB2F7" # ConsolidationGateway — deployed directly (no proxy), admin/limits set in the constructor -CONSOLIDATION_GATEWAY = "0xe446b867936f6E8cbcbf6B680D5db1b1344ee08F" # SRV3 +CONSOLIDATION_GATEWAY = "0x17be979344f2c2cC806229a532D92f8742C10462" # SRV3 # constructor params — upgrade-params-mainnet.toml [consolidationGateway] CONSOLIDATION_GATEWAY_MAX_REQUESTS_LIMIT = 2900 # SRV3 CONSOLIDATION_GATEWAY_CONSOLIDATIONS_PER_FRAME = 1 # SRV3 CONSOLIDATION_GATEWAY_FRAME_DURATION_IN_SEC = 30 # SRV3 # ConsolidationBus -CONSOLIDATION_BUS = "0x69f49a6681D72D373f2dC4977b05882196e9c660" # SRV3 -CONSOLIDATION_BUS_IMPL = "0x012811b876787FbeE4558064103647E2D36055ED" # SRV3 +CONSOLIDATION_BUS = "0xd907CE33B4Be423823d1CFFe80BD147E8b8554C8" # SRV3 +CONSOLIDATION_BUS_IMPL = "0xFfDe8Acab9D7037f29198Ad03ad6d05bac8B0a2E" # SRV3 # initialize() params — upgrade-params-mainnet.toml [consolidationBus] CONSOLIDATION_BUS_BATCH_SIZE = 200 # SRV3 CONSOLIDATION_BUS_MAX_GROUPS_IN_BATCH = 10 # SRV3 CONSOLIDATION_BUS_EXECUTION_DELAY = 86400 # SRV3 (seconds) # ConsolidationMigrator — Curated (id 1) -> Curated Module v2 (id 4) migration -CONSOLIDATION_MIGRATOR = "0x5f401c9cF95cB75bC8B28981D3d77b6513Ad652A" # SRV3 -CONSOLIDATION_MIGRATOR_IMPL = "0xB45052DD52e14591C5cb4307e8fbd4bC11608f20" # SRV3 +CONSOLIDATION_MIGRATOR = "0x9Dc70b5A4f4F5E4AF9058C983D560564F031f1D7" # SRV3 +CONSOLIDATION_MIGRATOR_IMPL = "0x6Fb4c152F092373dD71f0C07C83c1E77406599aB" # SRV3 CONSOLIDATION_SOURCE_MODULE_ID = 1 # SRV3 CONSOLIDATION_TARGET_MODULE_ID = 4 # SRV3 == CURATED_V2_STAKING_MODULE_ID # Curated Module Committee (CMC) multisig — stable deploy input from the toml @@ -501,16 +501,16 @@ CS_FEE_DISTRIBUTOR_ADDRESS = "0xD99CC66fEC647E68294C6477B40fC7E0F6F618D0" CS_FEE_ORACLE_ADDRESS = "0x4D4074628678Bd302921c20573EEa1ed38DdF7FB" CS_GATE_SEAL_ADDRESS = "0x16Dbd4B85a448bE564f1742d5c8cCdD2bB3185D0" -CS_VERIFIER_ADDRESS = "0x5B92BBACaF636fb38d52cb9d36a4986514ae4439" # SRV3 newVerifier -CS_VERIFIER_ADDRESS_OLD = "0x3Dfc50f22aCA652a0a6F28a0F892ab62074b5583" +CS_VERIFIER_ADDRESS = "0xfce7aB839e55de77730716D05b3553e45ab3A5Ba" # SRV3 newVerifier +CS_VERIFIER_ADDRESS_OLD = "0xdC5FE1782B6943f318E05230d688713a560063DC" CS_PARAMS_REGISTRY_ADDRESS = "0x9D28ad303C90DF524BA960d7a2DAC56DcC31e428" CS_EXIT_PENALTIES_ADDRESS = "0x06cd61045f958A209a0f8D746e103eCc625f4193" CS_STRIKES_ADDRESS = "0xaa328816027F2D32B9F56d190BC9Fa4A5C07637f" -CS_EJECTOR_ADDRESS = "0x2cB8510b0A30A38427E7e9555e8584b1a90c1BF7" # SRV3 +CS_EJECTOR_ADDRESS = "0x610B517D380f287c239C93F8eF6FfBd567AA4bA5" # SRV3 CS_VETTED_GATE_ADDRESS = "0xB314D4A76C457c93150d308787939063F4Cc67E0" -CS_PERMISSIONLESS_GATE_ADDRESS = "0xe29eaE1f3A3D0eDD45Bd6D4248A38F603f1F4d1A" # SRV3 newPermissionlessGate +CS_PERMISSIONLESS_GATE_ADDRESS = "0xb8cd8F059Ad7a5dB8CAfDe34aAb007317F7156C8" # SRV3 newPermissionlessGate CS_VERIFIER_V2_ADDRESS = "0xdC5FE1782B6943f318E05230d688713a560063DC" -CS_IDENTIFIED_DVT_CLUSTER_GATE_ADDRESS = "0x8d2b4aCDa9717847F739fa1c5e78BF47ca99a024" # SRV3 +CS_IDENTIFIED_DVT_CLUSTER_GATE_ADDRESS = "0xa12760721A72A7199aB38059DA6690b9Cd4ed7B8" # SRV3 CS_GATE_SEAL_V2_ADDRESS = "0xE1686C2E90eb41a48356c1cC7FaA17629af3ADB3" TWO_PHASE_FRAME_CONFIG_UPDATE = "0xb2B4DB1491cbe949ae85EfF01E0d3ee239f110C1" @@ -640,7 +640,7 @@ # Lido V3 - stVaults VAULT_HUB = "0x1d201BE093d847f6446530Efb0E8Fb426d176709" ACCOUNTING = "0x23ED611be0e1a820978875C0122F92260804cdDf" -ACCOUNTING_IMPL = "0xE85FD09eBc17A3aAB5f7BA691142506ab38EC1B7" # SRV3 +ACCOUNTING_IMPL = "0x3aa937Ac2ab89CDd363EdC6b5A4d4A42dF5bc043" # SRV3 OPERATOR_GRID = "0xC69685E89Cefc327b43B7234AC646451B27c544d" LAZY_ORACLE = "0x5DB427080200c235F2Ae8Cd17A7be87921f7AD6c" PREDEPOSIT_GUARANTEE = "0xF4bF42c6D6A0E38825785048124DBAD6c9eaaac3" From d328d081a454fc8b7715a382ed409822be273256 Mon Sep 17 00:00:00 2001 From: Anna Mukharram Date: Thu, 9 Jul 2026 20:07:42 +0400 Subject: [PATCH 09/30] fix: stake_distribution update --- brownie-config.yml | 1 - configs/config_mainnet.py | 1 + interfaces/IStakingModuleV2.json | 54 +++ .../test_staking_router_stake_distribution.py | 384 +++++++++++------- 4 files changed, 289 insertions(+), 151 deletions(-) create mode 100644 interfaces/IStakingModuleV2.json diff --git a/brownie-config.yml b/brownie-config.yml index c7acdf8e..98db6cfb 100644 --- a/brownie-config.yml +++ b/brownie-config.yml @@ -5,7 +5,6 @@ dependencies: networks: default: mainnet-fork development: - gas_limit: auto priority_fee: auto live: priority_fee: auto diff --git a/configs/config_mainnet.py b/configs/config_mainnet.py index d69c68aa..ed5ba07e 100644 --- a/configs/config_mainnet.py +++ b/configs/config_mainnet.py @@ -81,6 +81,7 @@ EASYTRACK_CURATED_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY = "0x4F716AD3Cc7A3A5cdA2359e5B2c84335c171dCde" EASYTRACK_SIMPLE_DVT_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY = "0x58A59dDC6Aea9b1D5743D024E15DfA4badB56E37" EASYTRACK_CS_SET_VETTED_GATE_TREE_FACTORY = "0xBc5642bDD6F2a54b01A75605aAe9143525D97308" +EASYTRACK_UPDATE_STAKING_MODULE_SHARE_LIMITS_FACTORY = "0xCF44d533A7766Ba299579eA0262fa61c0da81bA3" # SRV3 # Liquidity Observation Lab (LOL) stETH AllowedRecipientsRegistry LOL_ALLOWED_RECIPIENTS_REGISTRY = "0x48c4929630099b217136b64089E8543dB0E5163a" diff --git a/interfaces/IStakingModuleV2.json b/interfaces/IStakingModuleV2.json new file mode 100644 index 00000000..e07d06f9 --- /dev/null +++ b/interfaces/IStakingModuleV2.json @@ -0,0 +1,54 @@ +[ + { + "inputs": [ + { + "internalType": "uint256", + "name": "depositAmount", + "type": "uint256" + }, + { + "internalType": "bytes[]", + "name": "pubkeys", + "type": "bytes[]" + }, + { + "internalType": "uint256[]", + "name": "keyIndices", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "operatorIds", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "topUpLimits", + "type": "uint256[]" + } + ], + "name": "allocateDeposits", + "outputs": [ + { + "internalType": "uint256[]", + "name": "allocations", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getTotalModuleStake", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] \ No newline at end of file diff --git a/tests/regression/test_staking_router_stake_distribution.py b/tests/regression/test_staking_router_stake_distribution.py index 116e950d..3d557e61 100644 --- a/tests/regression/test_staking_router_stake_distribution.py +++ b/tests/regression/test_staking_router_stake_distribution.py @@ -1,24 +1,44 @@ from typing import Dict -from utils.config import contracts +from brownie import chain, interface + +from utils.config import EASYTRACK_UPDATE_STAKING_MODULE_SHARE_LIMITS_FACTORY, contracts +from utils.evm_script import encode_call_script from utils.test.csm_helpers import csm_add_node_operator, fill_csm_operators_with_keys from utils.test.deposits_helpers import fill_deposit_buffer +from utils.test.easy_track_helpers import create_and_enact_motion from utils.test.simple_dvt_helpers import fill_simple_dvt_ops_vetted_keys from utils.test.staking_router_helpers import StakingModuleStatus TOTAL_BASIS_POINTS = 10000 +WC_TYPE_02 = 2 class Module: def __init__( - self, id, stake_share_limit, module_fee, treasury_fee, deposited_keys, exited_keys, depositable_keys, status, - priorityExitShareThreshold, maxDepositsPerBlock, minDepositBlockDistance + self, + id, + address, + stake_share_limit, + module_fee, + treasury_fee, + deposited_keys, + exited_keys, + depositable_keys, + status, + priorityExitShareThreshold, + maxDepositsPerBlock, + minDepositBlockDistance, + withdrawal_credentials_type, + total_module_stake, ): self.id = id + self.address = address self.target_share = stake_share_limit self.status = status self.active_keys = 0 self.depositable_keys = depositable_keys + self.current_allocation = 0 self.allocated_keys = 0 self.allocation_limit = 0 self.module_fee = module_fee @@ -28,6 +48,12 @@ def __init__( self.priorityExitShareThreshold = priorityExitShareThreshold self.maxDepositsPerBlock = maxDepositsPerBlock self.minDepositBlockDistance = minDepositBlockDistance + self.withdrawal_credentials_type = withdrawal_credentials_type + self.total_module_stake = total_module_stake + + +def ceil_div(a: int, b: int) -> int: + return -(-a // b) def get_modules_info(staking_router): @@ -37,71 +63,107 @@ def get_modules_info(staking_router): for digest in module_digests: (_, _, state, summary) = digest - (id, _, module_fee, treasury_fee, stake_share_limit, status, _, _, _, _, priorityExitShareThreshold, - maxDepositsPerBlock, minDepositBlockDistance) = state + ( + id, + address, + module_fee, + treasury_fee, + stake_share_limit, + status, + _, + _, + _, + exited_keys_stored, + priorityExitShareThreshold, + maxDepositsPerBlock, + minDepositBlockDistance, + withdrawalCredentialsType, + _, + ) = state (exited_keys, deposited_keys, depositable_keys) = summary - if status != StakingModuleStatus.Active.value: - # reset depositable keys in case of module is inactivated - # https://github.com/lidofinance/lido-dao/blob/331ecec7fe3c8d57841fd73ccca7fb1cc9bc174e/contracts/0.8.9/StakingRouter.sol#L1230-L1232 - depositable_keys = 0 + + total_module_stake = 0 + if withdrawalCredentialsType == WC_TYPE_02: + total_module_stake = interface.IStakingModuleV2(address).getTotalModuleStake() modules[id] = Module( - id, stake_share_limit, module_fee, treasury_fee, deposited_keys, exited_keys, depositable_keys, status, - priorityExitShareThreshold, maxDepositsPerBlock, minDepositBlockDistance + id, + address, + stake_share_limit, + module_fee, + treasury_fee, + deposited_keys, + max(exited_keys, exited_keys_stored), + depositable_keys, + status, + priorityExitShareThreshold, + maxDepositsPerBlock, + minDepositBlockDistance, + withdrawalCredentialsType, + total_module_stake, ) - # total_active_keys = sum([module.active_keys for module in modules.values()]) return modules -def prep_modules_info(modules: Dict[int, Module]): - # reset keys counters - total_active_keys = 0 +def prep_modules_info(modules: Dict[int, Module], deposit_size: int): + # reset the allocation counters; a module's current allocation is measured in + # 32-ETH validator equivalents: active validators for WC 0x01 modules, + # ceil(total module stake / 32 ETH) for WC 0x02 modules + total_allocation = 0 for module in modules.values(): module.active_keys = module.deposited_keys - module.exited_keys assert module.active_keys >= 0 - total_active_keys += module.active_keys + if module.withdrawal_credentials_type == WC_TYPE_02: + module.current_allocation = ceil_div(module.total_module_stake, deposit_size) + else: + module.current_allocation = module.active_keys + module.allocated_keys = 0 + total_allocation += module.current_allocation - return total_active_keys + return total_allocation -def calc_allocation(modules: Dict[int, Module], keys_to_allocate: int, ignore_depositable: bool = False): - total_active_keys = prep_modules_info(modules) - # simulate target share distribution - # https://github.com/lidofinance/lido-dao/blob/331ecec7fe3c8d57841fd73ccca7fb1cc9bc174e/contracts/0.8.9/StakingRouter.sol#L1266-L1268 +def calc_allocation(modules: Dict[int, Module], deposit_amount: int, is_top_up: bool = False): + # simulate SRLib._getDepositAllocations: everything is computed in 32-ETH + # validator-equivalent units, the results are returned in wei + deposit_size = contracts.staking_router.INITIAL_DEPOSIT_SIZE() + max_effective_balance = contracts.staking_router.MAX_EFFECTIVE_BALANCE_WC_TYPE_02() + units_to_allocate = deposit_amount // deposit_size - target_total_active_keys = total_active_keys + keys_to_allocate + total_validators = units_to_allocate + prep_modules_info(modules, deposit_size) for module in modules.values(): - target_active_keys = module.target_share * target_total_active_keys // TOTAL_BASIS_POINTS - module.allocation_limit = ( - target_active_keys - if ignore_depositable - else min(target_active_keys, module.active_keys + module.depositable_keys) - ) - module.allocated_keys = 0 - - # simulate min first strategy - # https://github.com/lidofinance/lido-dao/blob/331ecec7fe3c8d57841fd73ccca7fb1cc9bc174e/contracts/0.8.9/StakingRouter.sol#L1274 - - for _ in range(keys_to_allocate): - # find the module with the lowest active_keys - min_active_keys = modules[1].active_keys - min_active_keys_module = modules[1] - + if module.status != StakingModuleStatus.Active.value: + module.allocation_limit = module.current_allocation + continue + if is_top_up and module.withdrawal_credentials_type == WC_TYPE_02: + capacity = module.active_keys * max_effective_balance // deposit_size + else: + capacity = module.current_allocation + module.depositable_keys + target_validators = module.target_share * total_validators // TOTAL_BASIS_POINTS + module.allocation_limit = min(target_validators, capacity) + + # simulate min first strategy: every unit goes to the least filled module + # that still has free capacity, first index wins the tie + for _ in range(units_to_allocate): + best_module = None for module in modules.values(): - if module.active_keys < min_active_keys and module.active_keys < module.allocation_limit: - min_active_keys = module.active_keys - min_active_keys_module = module - - # allocate one key to the module if possible - if min_active_keys_module.active_keys < min_active_keys_module.allocation_limit: - min_active_keys_module.active_keys += 1 - min_active_keys_module.allocated_keys += 1 - - total_allocated_keys = sum([module.allocated_keys for module in modules.values()]) - return total_allocated_keys, target_total_active_keys + filled = module.current_allocation + module.allocated_keys + if filled >= module.allocation_limit: + continue + if best_module is None or filled < best_module.current_allocation + best_module.allocated_keys: + best_module = module + if best_module is None: + break + best_module.allocated_keys += 1 + + allocated = [module.allocated_keys * deposit_size for module in modules.values()] + new_allocations = [ + (module.current_allocation + module.allocated_keys) * deposit_size for module in modules.values() + ] + return sum(allocated), allocated, new_allocations def assure_depositable_keys(stranger): @@ -117,28 +179,37 @@ def assure_depositable_keys(stranger): def test_stake_distribution(stranger): """ Test stake distribution among the staking modules - 1. checks that result of `getDepositsAllocation` matches the local allocation calculations + 1. checks that result of `getDepositAllocations` matches the local allocation calculations 2. checks that deposits to modules can be made according to the calculated allocation """ assure_depositable_keys(stranger) - keys_to_allocate = 100 # keys to allocate to the modules - allocation_from_contract = contracts.staking_router.getDepositsAllocation(keys_to_allocate) + deposits_count = 100 # seed deposits to add to the buffer + fill_deposit_buffer(deposits_count) + + deposit_amount = contracts.lido.getDepositableEther() + allocation_from_contract = contracts.staking_router.getDepositAllocations(deposit_amount, False) # collect the modules information modules = get_modules_info(contracts.staking_router) - total_allocated_keys, _ = calc_allocation(modules, keys_to_allocate) + total_allocated, allocated, new_allocations = calc_allocation(modules, deposit_amount) # check that local allocation matches the contract allocation - assert allocation_from_contract == (total_allocated_keys, [module.active_keys for module in modules.values()]) - - # fill the deposit buffer - fill_deposit_buffer(total_allocated_keys) + assert allocation_from_contract == (total_allocated, allocated, new_allocations) - # perform deposits to the modules + # perform deposits to the modules; the router computes the deposits count itself: + # min(maxDepositsPerBlock, module allocation / 32 ETH) for module in modules.values(): - if module.allocated_keys > 0: - contracts.lido.deposit(module.allocated_keys, module.id, "0x", {"from": contracts.deposit_security_module}) + expected_deposits = min(module.maxDepositsPerBlock, module.allocated_keys) + if expected_deposits == 0: + continue + + (_, deposited_before, _) = contracts.staking_router.getStakingModuleSummary(module.id) + chain.mine(module.minDepositBlockDistance) + contracts.staking_router.deposit(module.id, "0x", {"from": contracts.deposit_security_module}) + (_, deposited_after, _) = contracts.staking_router.getStakingModuleSummary(module.id) + + assert deposited_after - deposited_before == expected_deposits # check that the new active keys in the modules match the expected values module_digests_after_deposit = contracts.staking_router.getAllStakingModuleDigests() @@ -146,107 +217,120 @@ def test_stake_distribution(stranger): for digest in module_digests_after_deposit: (_, _, state, summary) = digest - (id, _, _, _, _, _, _, _, _, _, _, _, _) = state + (id, _, _, _, _, _, _, _, _, _, _, _, _, _, _) = state (exited_keys, deposited_keys, _) = summary active_keys_after_deposit = deposited_keys - exited_keys - assert expected_modules_state[id].active_keys == active_keys_after_deposit + expected = expected_modules_state[id] + assert active_keys_after_deposit == expected.active_keys + min( + expected.maxDepositsPerBlock, expected.allocated_keys + ) def test_target_share_distribution(stranger): - keys_to_allocate = 100 # keys to allocate to the modules - keys_to_allocate_double = keys_to_allocate * 2 + """ + Test that `stakeShareLimit` caps the deposit allocation of a module + 1. sets a module a share limit that admits exactly `keys_to_allocate` more seed deposits + 2. checks that the share limit is the binding constraint (the module has spare keys above it) + 3. checks that on an oversized allocation the module fills up to the share limit and stops, + the rest spills over to the other modules + 4. checks the contract allocation matches the local model and a real deposit follows it + """ + deposit_size = contracts.staking_router.INITIAL_DEPOSIT_SIZE() modules = get_modules_info(contracts.staking_router) - min_target_share = 1 # 0.01% = 1 / 10000 - nor_m_id = 1 - nor_m = modules[nor_m_id] - - cur_total_active_keys = prep_modules_info(modules) - - module = sorted(modules.values(), key=lambda m: m.active_keys / cur_total_active_keys * TOTAL_BASIS_POINTS)[0] - - # calc some hypothetical module allocation share for testing - expected_active_keys_1 = module.active_keys + keys_to_allocate - expected_active_keys_2 = module.active_keys + keys_to_allocate_double - - expected_total_active_keys = cur_total_active_keys + keys_to_allocate - expected_total_active_keys_2 = cur_total_active_keys + keys_to_allocate_double - - # calc module share that is guaranteed to fit `keys_to_allocate` deposited keys amount (upper cap) - expected_target_share_1 = (expected_active_keys_1 * TOTAL_BASIS_POINTS // expected_total_active_keys) + 1 - # calc module share for doubled `keys_to_allocate` keys amount, expected to overcome the 1st target share - expected_target_share_2 = expected_active_keys_2 * TOTAL_BASIS_POINTS // expected_total_active_keys_2 - - # ensure 2nd keys amount is enough to overcome the 1st target share (after 1st keys amount) at least by 1 basis point - assert expected_target_share_1 >= min_target_share - assert expected_target_share_2 > expected_target_share_1 - - # force update module `targetShare` value to simulate new allocation - module.target_share = expected_target_share_1 - - expected_total_allocated_keys, expected_total_active_keys = calc_allocation(modules, keys_to_allocate, True) - assert expected_total_allocated_keys == keys_to_allocate - assert module.active_keys >= expected_active_keys_1 - assert module.allocated_keys == keys_to_allocate - assert nor_m.allocated_keys == 0 - - expected_total_allocated_keys, expected_total_active_keys = calc_allocation(modules, keys_to_allocate_double, True) - assert expected_total_allocated_keys == keys_to_allocate_double - assert module.active_keys < expected_active_keys_2 - assert module.allocated_keys < keys_to_allocate_double - assert nor_m.allocated_keys <= keys_to_allocate_double - - # set the new target share value, which will be reached after 1s deposit of `keys_to_allocate`` batch - contracts.staking_router.updateStakingModule( - module.id, - expected_target_share_1, - module.priorityExitShareThreshold, - module.module_fee, - module.treasury_fee, - module.maxDepositsPerBlock, - module.minDepositBlockDistance, - {"from": contracts.agent}, + total_allocation = prep_modules_info(modules, deposit_size) + + # target module: the least filled active module which can be topped up with keys + # (no key onboarding helper for Curated Module v2 yet, so ids 2-3 only) + candidates = [m for m in modules.values() if m.status == StakingModuleStatus.Active.value and m.id in (2, 3)] + module = min(candidates, key=lambda m: m.current_allocation) + module_idx = list(modules.keys()).index(module.id) + + # scenario size: must exceed the 1 bp share granularity (1 bp of the total) + keys_to_allocate = max(100, 2 * (total_allocation // TOTAL_BASIS_POINTS)) + required_depositable_keys = 2 * keys_to_allocate + + # a share limit that admits exactly +keys_to_allocate to the target module + target_share = (module.current_allocation + keys_to_allocate) * TOTAL_BASIS_POINTS // ( + total_allocation + keys_to_allocate + ) + 1 + assert target_share <= module.priorityExitShareThreshold + + # the doubled amount must not fit into the target share (share granularity check) + doubled_share = ( + (module.current_allocation + required_depositable_keys) + * TOTAL_BASIS_POINTS + // (total_allocation + required_depositable_keys) ) - # add enough depositable keys to the target module to overcome the target share - # at least first 3 NOs, each with 1/3 of the `keys_to_allocate_double` available keys - if module.id == 2: - fill_simple_dvt_ops_vetted_keys(stranger, 3, (module.deposited_keys + keys_to_allocate_double + 3) // 3) - elif module.id == 3: - fill_csm_operators_with_keys(3, (module.deposited_keys + keys_to_allocate_double + 3) // 3) - - # update the modules info and recalc the allocation according to the module limits - modules = get_modules_info(contracts.staking_router) - expected_total_allocated_keys, expected_total_active_keys = calc_allocation(modules, keys_to_allocate_double, False) - - assert expected_total_allocated_keys == keys_to_allocate_double - assert module.active_keys < expected_active_keys_2 - assert module.allocated_keys < keys_to_allocate_double - assert nor_m.allocated_keys <= keys_to_allocate_double - - allocation_from_contract = contracts.staking_router.getDepositsAllocation(keys_to_allocate_double) - # check that local allocation matches the contract allocation - assert allocation_from_contract == ( - expected_total_allocated_keys, - [module.active_keys for module in modules.values()], + assert doubled_share > target_share + + # the module must have more depositable keys than the share admits, + # so the share limit is the binding constraint, not the keys + if module.depositable_keys < required_depositable_keys: + min_keys_cnt = (required_depositable_keys + 2) // 3 + if module.id == 2: + fill_simple_dvt_ops_vetted_keys(stranger, 3, min_keys_cnt) + elif module.id == 3: + fill_csm_operators_with_keys(3, min_keys_cnt) + + motion_calldata = encode_call_script( + [ + ( + contracts.staking_router.address, + contracts.staking_router.updateModuleShares.encode_input( + module.id, target_share, module.priorityExitShareThreshold + ), + ) + ] + ) + create_and_enact_motion( + contracts.easy_track, + stranger, + EASYTRACK_UPDATE_STAKING_MODULE_SHARE_LIMITS_FACTORY, + motion_calldata, + stranger, ) - # fill the deposit buffer - fill_deposit_buffer(keys_to_allocate_double) - - # perform deposits to the modules - for module in modules.values(): - if module.allocated_keys > 0: - contracts.lido.deposit(module.allocated_keys, module.id, "0x", {"from": contracts.deposit_security_module}) + modules = get_modules_info(contracts.staking_router) + module = modules[module.id] + assert module.target_share == target_share + assert module.depositable_keys >= required_depositable_keys + + # the share limit admits the base amount and the contract agrees with the model + deposit_amount = keys_to_allocate * deposit_size + allocations = calc_allocation(modules, deposit_amount) + assert contracts.staking_router.getDepositAllocations(deposit_amount, False) == allocations + assert module.allocation_limit >= module.current_allocation + keys_to_allocate + assert module.current_allocation + module.depositable_keys > module.allocation_limit + + # find an allocation amount that overflows the target module: the module fills up + # to its share limit and stops, no matter how close the other modules levels are + overflow_amount = required_depositable_keys * deposit_size + for _ in range(10): + total_allocated, allocated, new_allocations = calc_allocation(modules, overflow_amount) + if new_allocations[module_idx] == module.allocation_limit * deposit_size: + break + overflow_amount *= 2 + + assert new_allocations[module_idx] == module.allocation_limit * deposit_size + assert module.current_allocation + module.depositable_keys > module.allocation_limit + assert allocated[module_idx] < overflow_amount + assert contracts.staking_router.getDepositAllocations(overflow_amount, False) == ( + total_allocated, + allocated, + new_allocations, + ) - # check that the new active keys in the modules match the expected values - module_digests_after_deposit = contracts.staking_router.getAllStakingModuleDigests() - expected_modules_state = modules + # the new share limit applies to a real deposit as well + fill_deposit_buffer(keys_to_allocate) + (_, allocated, _) = calc_allocation(modules, contracts.lido.getDepositableEther()) - for digest in module_digests_after_deposit: - (_, _, state, summary) = digest - (id, _, _, _, _, _, _, _, _, _, _, _, _) = state - (exited_keys, deposited_keys, _) = summary + expected_deposits = min(module.maxDepositsPerBlock, allocated[module_idx] // deposit_size) + if expected_deposits > 0: + (_, deposited_before, _) = contracts.staking_router.getStakingModuleSummary(module.id) + chain.mine(module.minDepositBlockDistance) + contracts.staking_router.deposit(module.id, "0x", {"from": contracts.deposit_security_module}) + (_, deposited_after, _) = contracts.staking_router.getStakingModuleSummary(module.id) - active_keys_after_deposit = deposited_keys - exited_keys - assert expected_modules_state[id].active_keys == active_keys_after_deposit + assert deposited_after - deposited_before == expected_deposits From 49f746a8e9597b38b759193f7cdabe9e58cb063e Mon Sep 17 00:00:00 2001 From: skhomuti Date: Thu, 9 Jul 2026 13:03:18 +0500 Subject: [PATCH 10/30] test: add staking modules vote regressions --- .../workflows/{csm_tests.yml => sm-tests.yml} | 25 +- configs/config_mainnet.py | 16 + interfaces/BaseModule.json | 1 + interfaces/CSAccounting.json | 1 - interfaces/CSExitPenalties.json | 1 - interfaces/CSFeeDistributor.json | 1 - interfaces/CSModule.json | 2 +- interfaces/CSPermissionlessGate.json | 1 - interfaces/CSStrikes.json | 1 - interfaces/CSVettedGate.json | 1 - interfaces/CreateOrUpdateOperatorGroup.json | 1 + interfaces/CuratedGate.json | 1 + interfaces/CuratedModule.json | 1 + interfaces/{CSEjector.json => Ejector.json} | 0 interfaces/ExitPenalties.json | 1 + interfaces/FeeDistributor.json | 1 + .../{CSFeeOracle.json => FeeOracle.json} | 0 interfaces/MerkleGate.json | 1 + interfaces/MetaRegistry.json | 1 + interfaces/ModuleAccounting.json | 1 + ...sRegistry.json => ParametersRegistry.json} | 0 interfaces/PermissionlessGate.json | 1 + ...ReportWithdrawalsForSlashedValidators.json | 1 + interfaces/SetMerkleGateTree.json | 1 + interfaces/SettleGeneralDelayedPenalty.json | 1 + .../UpdateStakingModuleShareLimits.json | 1 + interfaces/ValidatorStrikes.json | 1 + interfaces/Verifier.json | 1 + interfaces/VettedGate.json | 1 + tests/acceptance/test_csm.py | 280 ------------------ tests/conftest.py | 5 +- tests/regression/test_easy_track_factories.py | 265 ++++++++++++++++- tests/regression/test_permissions.py | 168 +++++++---- utils/config.py | 40 +-- 34 files changed, 459 insertions(+), 365 deletions(-) rename .github/workflows/{csm_tests.yml => sm-tests.yml} (73%) create mode 100644 interfaces/BaseModule.json delete mode 100644 interfaces/CSAccounting.json delete mode 100644 interfaces/CSExitPenalties.json delete mode 100644 interfaces/CSFeeDistributor.json delete mode 100644 interfaces/CSPermissionlessGate.json delete mode 100644 interfaces/CSStrikes.json delete mode 100644 interfaces/CSVettedGate.json create mode 100644 interfaces/CreateOrUpdateOperatorGroup.json create mode 100644 interfaces/CuratedGate.json create mode 100644 interfaces/CuratedModule.json rename interfaces/{CSEjector.json => Ejector.json} (100%) create mode 100644 interfaces/ExitPenalties.json create mode 100644 interfaces/FeeDistributor.json rename interfaces/{CSFeeOracle.json => FeeOracle.json} (100%) create mode 100644 interfaces/MerkleGate.json create mode 100644 interfaces/MetaRegistry.json create mode 100644 interfaces/ModuleAccounting.json rename interfaces/{CSParametersRegistry.json => ParametersRegistry.json} (100%) create mode 100644 interfaces/PermissionlessGate.json create mode 100644 interfaces/ReportWithdrawalsForSlashedValidators.json create mode 100644 interfaces/SetMerkleGateTree.json create mode 100644 interfaces/SettleGeneralDelayedPenalty.json create mode 100644 interfaces/UpdateStakingModuleShareLimits.json create mode 100644 interfaces/ValidatorStrikes.json create mode 100644 interfaces/Verifier.json create mode 100644 interfaces/VettedGate.json delete mode 100644 tests/acceptance/test_csm.py diff --git a/.github/workflows/csm_tests.yml b/.github/workflows/sm-tests.yml similarity index 73% rename from .github/workflows/csm_tests.yml rename to .github/workflows/sm-tests.yml index e288cea6..0a14c7bb 100644 --- a/.github/workflows/csm_tests.yml +++ b/.github/workflows/sm-tests.yml @@ -89,6 +89,22 @@ jobs: run: poetry run brownie networks import network-config.yaml True working-directory: scripts + - name: Capture pre-vote block for staking modules regression + id: modules-regression-vote-block + shell: bash + run: | + response=$(curl -sS --fail \ + -X POST \ + -H "Content-Type: application/json" \ + --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' \ + ${{ env.HARDHAT_NODE_URL }}) + block_hex=$(printf "%s" "$response" | sed -E 's/.*"result":"([^"]+)".*/\1/') + if [ -z "$block_hex" ] || [ "$block_hex" = "$response" ]; then + echo "Unable to parse block number from response: $response" >&2 + exit 1 + fi + echo "vote_prev_block=$((16#${block_hex#0x}))" >> "$GITHUB_OUTPUT" + - name: Prepare test environment with Brownie run: PYTHONPATH=$PWD poetry run brownie run scripts/ci/prepare_environment --network mfh-1 working-directory: scripts @@ -97,9 +113,10 @@ jobs: ETHERSCAN_TOKEN: ${{ secrets.ETHERSCAN_TOKEN }} - name: Run staking modules regression tests - uses: lidofinance/staking-modules/.github/actions/regression-tests@develop + uses: lidofinance/community-staking-module/.github/actions/regression-tests@agent/staking-modules-regression-action with: - repository: lidofinance/staking-modules - ref: main - path: staking-modules + repository: lidofinance/community-staking-module + ref: develop + path: community-staking-module rpc_url: ${{ env.HARDHAT_NODE_URL }} + vote_prev_block: ${{ steps.modules-regression-vote-block.outputs.vote_prev_block }} diff --git a/configs/config_mainnet.py b/configs/config_mainnet.py index 3dde12d7..0d2ade2d 100644 --- a/configs/config_mainnet.py +++ b/configs/config_mainnet.py @@ -81,6 +81,14 @@ EASYTRACK_CURATED_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY = "0x4F716AD3Cc7A3A5cdA2359e5B2c84335c171dCde" EASYTRACK_SIMPLE_DVT_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY = "0x58A59dDC6Aea9b1D5743D024E15DfA4badB56E37" EASYTRACK_CS_SET_VETTED_GATE_TREE_FACTORY = "0xBc5642bDD6F2a54b01A75605aAe9143525D97308" +EASYTRACK_CSM_SET_MERKLE_GATE_TREE_FACTORY = "0xf3ec30B86c3dC1b8a1C754D885F9bE3160e15B4c" +EASYTRACK_CSM_REPORT_WITHDRAWALS_FOR_SLASHED_VALIDATORS_FACTORY = "0xE330516a03bDdEBA4209b5591112f1aa3dd90F0A" +EASYTRACK_CSM_SETTLE_GENERAL_DELAYED_PENALTY_FACTORY = "0xB71755bE764abB4Ce26cb4dADf056Be57fB8880F" +EASYTRACK_CM_SET_MERKLE_GATE_TREE_FACTORY = "0xa121667D1780a1D54EAEd67AE17ee13d0f872D60" +EASYTRACK_CM_REPORT_WITHDRAWALS_FOR_SLASHED_VALIDATORS_FACTORY = "0x71862Abd99819597670007bb992A7a7562fE50f2" +EASYTRACK_CM_SETTLE_GENERAL_DELAYED_PENALTY_FACTORY = "0xfffEFC16231eDC6Dc9C93e364ff4D4E3f787f416" +EASYTRACK_CM_CREATE_OR_UPDATE_OPERATOR_GROUP_FACTORY = "0x2fC78638b77381e9D040163Bd6EB1cac967bDBdF" +EASYTRACK_UPDATE_STAKING_MODULE_SHARE_LIMITS_FACTORY = "0x0C6703F1d8D9DdfB6c6e5F57b4f7432a6500D6D8" # Liquidity Observation Lab (LOL) stETH AllowedRecipientsRegistry LOL_ALLOWED_RECIPIENTS_REGISTRY = "0x48c4929630099b217136b64089E8543dB0E5163a" @@ -181,6 +189,11 @@ CURATED_V2_FEE_ORACLE = "0x8EeFCdbD984c30E472BcbF545783D051CB5114e5" # SRV3 CURATED_V2_VERIFIER = "0xC392F457960f1B13Ebaf1aa6C065479dD507E1E3" # SRV3 CURATED_V2_EJECTOR = "0xe181A377A2d2BDE9A83f1474BC3DB7A412de091E" # SRV3 +CM_MODULE_ADDRESS = CURATED_V2_STAKING_MODULE_ADDRESS +CM_META_REGISTRY_ADDRESS = "0xA64b339eebD3dC3De848298B6a140955932901d8" +CM_PROFESSIONAL_OPERATOR_GATE_ADDRESS = "0x6093EFA6B5E2FF3be54d1c895c9deA932805c49F" +CM_ACCOUNTING_ADDRESS = CURATED_V2_ACCOUNTING +CM_EJECTOR_ADDRESS = CURATED_V2_EJECTOR # CuratedModuleConfig.circuitBreakerPauser — the vote registers it as pauser # for all five CM v2 pausables on the CircuitBreaker CURATED_V2_CIRCUIT_BREAKER_PAUSER = "0x2570e0b22AD904501dfB0d49575991ACB801dD91" # SRV3 @@ -509,9 +522,12 @@ CS_EJECTOR_ADDRESS = "0x610B517D380f287c239C93F8eF6FfBd567AA4bA5" # SRV3 CS_VETTED_GATE_ADDRESS = "0xB314D4A76C457c93150d308787939063F4Cc67E0" CS_PERMISSIONLESS_GATE_ADDRESS = "0xb8cd8F059Ad7a5dB8CAfDe34aAb007317F7156C8" # SRV3 newPermissionlessGate +CS_PERMISSIONLESS_GATE_V3_ADDRESS = CS_PERMISSIONLESS_GATE_ADDRESS CS_VERIFIER_V2_ADDRESS = "0xdC5FE1782B6943f318E05230d688713a560063DC" +CS_VERIFIER_V3_ADDRESS = CS_VERIFIER_ADDRESS CS_IDENTIFIED_DVT_CLUSTER_GATE_ADDRESS = "0xa12760721A72A7199aB38059DA6690b9Cd4ed7B8" # SRV3 CS_GATE_SEAL_V2_ADDRESS = "0xE1686C2E90eb41a48356c1cC7FaA17629af3ADB3" +CS_EJECTOR_V3_ADDRESS = CS_EJECTOR_ADDRESS TWO_PHASE_FRAME_CONFIG_UPDATE = "0xb2B4DB1491cbe949ae85EfF01E0d3ee239f110C1" # DualGovernance diff --git a/interfaces/BaseModule.json b/interfaces/BaseModule.json new file mode 100644 index 00000000..bb299705 --- /dev/null +++ b/interfaces/BaseModule.json @@ -0,0 +1 @@ +[{"type":"function","name":"ACCOUNTING","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IAccounting"}],"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":"EXIT_PENALTIES","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IExitPenalties"}],"stateMutability":"view"},{"type":"function","name":"FEE_DISTRIBUTOR","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"LIDO_LOCATOR","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ILidoLocator"}],"stateMutability":"view"},{"type":"function","name":"OPERATOR_ADDRESSES_ADMIN_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"PARAMETERS_REGISTRY","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IParametersRegistry"}],"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_GENERAL_DELAYED_PENALTY_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"REPORT_REGULAR_WITHDRAWN_VALIDATORS_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"REPORT_SLASHED_WITHDRAWN_VALIDATORS_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_GENERAL_DELAYED_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":"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 IAccounting.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 IAccounting.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":"allocateDeposits","inputs":[{"name":"maxDepositAmount","type":"uint256","internalType":"uint256"},{"name":"pubkeys","type":"bytes[]","internalType":"bytes[]"},{"name":"keyIndices","type":"uint256[]","internalType":"uint256[]"},{"name":"operatorIds","type":"uint256[]","internalType":"uint256[]"},{"name":"topUpLimits","type":"uint256[]","internalType":"uint256[]"}],"outputs":[{"name":"allocations","type":"uint256[]","internalType":"uint256[]"}],"stateMutability":"nonpayable"},{"type":"function","name":"batchDepositInfoUpdate","inputs":[{"name":"maxCount","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"operatorsLeft","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"cancelGeneralDelayedPenalty","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"amount","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"changeNodeOperatorAddresses","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"newManagerAddress","type":"address","internalType":"address"},{"name":"newRewardAddress","type":"address","internalType":"address"}],"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":"compensateGeneralDelayedPenalty","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"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":"","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":"exitDeadlineThreshold","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"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":"getKeyAllocatedBalances","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"startIndex","type":"uint256","internalType":"uint256"},{"name":"keysCount","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"balances","type":"uint256[]","internalType":"uint256[]"}],"stateMutability":"view"},{"type":"function","name":"getKeyConfirmedBalances","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"startIndex","type":"uint256","internalType":"uint256"},{"name":"keysCount","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"balances","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"},{"name":"usedPriorityQueue","type":"bool","internalType":"bool"}]}],"stateMutability":"view"},{"type":"function","name":"getNodeOperatorBalance","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getNodeOperatorDepositInfoToUpdateCount","inputs":[],"outputs":[{"name":"count","type":"uint256","internalType":"uint256"}],"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":"getNodeOperatorOwner","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"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":"getRoleMembers","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"address[]","internalType":"address[]"}],"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":"keys","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":"getTotalModuleStake","inputs":[],"outputs":[{"name":"","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":"isPaused","inputs":[],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"isValidatorExitDelayPenaltyApplicable","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"proofSlotTimestamp","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":"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":"obtainDepositData","inputs":[{"name":"depositsCount","type":"uint256","internalType":"uint256"},{"name":"depositCalldata","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":"view"},{"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":"elWithdrawalRequestFeePaid","type":"uint256","internalType":"uint256"},{"name":"exitType","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"onWithdrawalCredentialsChanged","inputs":[],"outputs":[],"stateMutability":"view"},{"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":"reportGeneralDelayedPenalty","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"penaltyType","type":"bytes32","internalType":"bytes32"},{"name":"amount","type":"uint256","internalType":"uint256"},{"name":"details","type":"string","internalType":"string"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"reportRegularWithdrawnValidators","inputs":[{"name":"validatorInfos","type":"tuple[]","internalType":"struct WithdrawnValidatorInfo[]","components":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"keyIndex","type":"uint256","internalType":"uint256"},{"name":"exitBalance","type":"uint256","internalType":"uint256"},{"name":"slashingPenalty","type":"uint256","internalType":"uint256"},{"name":"isSlashed","type":"bool","internalType":"bool"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"reportSlashedWithdrawnValidators","inputs":[{"name":"validatorInfos","type":"tuple[]","internalType":"struct WithdrawnValidatorInfo[]","components":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"keyIndex","type":"uint256","internalType":"uint256"},{"name":"exitBalance","type":"uint256","internalType":"uint256"},{"name":"slashingPenalty","type":"uint256","internalType":"uint256"},{"name":"isSlashed","type":"bool","internalType":"bool"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"reportValidatorBalance","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"keyIndex","type":"uint256","internalType":"uint256"},{"name":"currentBalanceWei","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"reportValidatorExitDelay","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"proofSlotTimestamp","type":"uint256","internalType":"uint256"},{"name":"publicKey","type":"bytes","internalType":"bytes"},{"name":"eligibleToExitInSec","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"reportValidatorSlashing","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"keyIndex","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"requestFullDepositInfoUpdate","inputs":[],"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":"settleGeneralDelayedPenalty","inputs":[{"name":"nodeOperatorIds","type":"uint256[]","internalType":"uint256[]"},{"name":"bondLockNonces","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":"unsafeUpdateValidatorsCount","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"exitedValidatorsCount","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateDepositInfo","inputs":[{"name":"nodeOperatorId","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":"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":"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":"FullDepositInfoUpdateRequested","inputs":[],"anonymous":false},{"type":"event","name":"GeneralDelayedPenaltyCancelled","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"GeneralDelayedPenaltyCompensated","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"GeneralDelayedPenaltyReported","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"penaltyType","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"additionalFine","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"details","type":"string","indexed":false,"internalType":"string"}],"anonymous":false},{"type":"event","name":"GeneralDelayedPenaltySettled","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"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":"KeyAllocatedBalanceChanged","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"keyIndex","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"newTotal","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"KeyConfirmedBalanceChanged","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"keyIndex","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"newBalance","type":"uint256","indexed":false,"internalType":"uint256"}],"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":"NodeOperatorBalanceUpdated","inputs":[{"name":"operatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"balanceWei","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"NodeOperatorDepositInfoFullyUpdated","inputs":[],"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":"TotalWithdrawnValidatorsRebuilt","inputs":[{"name":"totalWithdrawnValidators","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ValidatorSlashingReported","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"keyIndex","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"pubkey","type":"bytes","indexed":false,"internalType":"bytes"}],"anonymous":false},{"type":"event","name":"ValidatorWithdrawn","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"keyIndex","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"exitBalance","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"slashingPenalty","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"pubkey","type":"bytes","indexed":false,"internalType":"bytes"}],"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":"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":"CannotAddKeys","inputs":[]},{"type":"error","name":"DepositInfoIsNotUpToDate","inputs":[]},{"type":"error","name":"DepositableKeysWithUnsupportedWithdrawalCredentials","inputs":[]},{"type":"error","name":"FailedToSendEther","inputs":[]},{"type":"error","name":"InvalidAmount","inputs":[]},{"type":"error","name":"InvalidInitialization","inputs":[]},{"type":"error","name":"InvalidInput","inputs":[]},{"type":"error","name":"InvalidManagerAddress","inputs":[]},{"type":"error","name":"InvalidRewardAddress","inputs":[]},{"type":"error","name":"InvalidVetKeysPointer","inputs":[]},{"type":"error","name":"InvalidWithdrawnValidatorInfo","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":"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":"SlashingPenaltyIsNotApplicable","inputs":[]},{"type":"error","name":"UnreportableBalance","inputs":[]},{"type":"error","name":"ValidatorSlashingAlreadyReported","inputs":[]},{"type":"error","name":"ZeroAccountingAddress","inputs":[]},{"type":"error","name":"ZeroAdminAddress","inputs":[]},{"type":"error","name":"ZeroExitBalance","inputs":[]},{"type":"error","name":"ZeroExitPenaltiesAddress","inputs":[]},{"type":"error","name":"ZeroLocatorAddress","inputs":[]},{"type":"error","name":"ZeroManagerAddress","inputs":[]},{"type":"error","name":"ZeroModuleType","inputs":[]},{"type":"error","name":"ZeroParametersRegistryAddress","inputs":[]},{"type":"error","name":"ZeroPauseDuration","inputs":[]},{"type":"error","name":"ZeroPenaltyType","inputs":[]},{"type":"error","name":"ZeroRewardAddress","inputs":[]},{"type":"error","name":"ZeroSenderAddress","inputs":[]}] diff --git a/interfaces/CSAccounting.json b/interfaces/CSAccounting.json deleted file mode 100644 index 8eaef61d..00000000 --- a/interfaces/CSAccounting.json +++ /dev/null @@ -1 +0,0 @@ -[{"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/CSExitPenalties.json b/interfaces/CSExitPenalties.json deleted file mode 100644 index 12a6b410..00000000 --- a/interfaces/CSExitPenalties.json +++ /dev/null @@ -1 +0,0 @@ -[{"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/CSFeeDistributor.json b/interfaces/CSFeeDistributor.json deleted file mode 100644 index e5f46981..00000000 --- a/interfaces/CSFeeDistributor.json +++ /dev/null @@ -1 +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":"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/CSModule.json b/interfaces/CSModule.json index 0652581d..c8eaaddc 100644 --- a/interfaces/CSModule.json +++ b/interfaces/CSModule.json @@ -1 +1 @@ -[{"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"}] +[{"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 IAccounting"}],"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":"EXIT_PENALTIES","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IExitPenalties"}],"stateMutability":"view"},{"type":"function","name":"FEE_DISTRIBUTOR","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"LIDO_LOCATOR","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ILidoLocator"}],"stateMutability":"view"},{"type":"function","name":"MANAGE_TOP_UP_QUEUE_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"OPERATOR_ADDRESSES_ADMIN_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"PARAMETERS_REGISTRY","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IParametersRegistry"}],"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_GENERAL_DELAYED_PENALTY_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"REPORT_REGULAR_WITHDRAWN_VALIDATORS_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"REPORT_SLASHED_WITHDRAWN_VALIDATORS_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":"REWIND_TOP_UP_QUEUE_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"SETTLE_GENERAL_DELAYED_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":"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 IAccounting.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 IAccounting.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":"allocateDeposits","inputs":[{"name":"maxDepositAmount","type":"uint256","internalType":"uint256"},{"name":"pubkeys","type":"bytes[]","internalType":"bytes[]"},{"name":"keyIndices","type":"uint256[]","internalType":"uint256[]"},{"name":"operatorIds","type":"uint256[]","internalType":"uint256[]"},{"name":"topUpLimits","type":"uint256[]","internalType":"uint256[]"}],"outputs":[{"name":"allocations","type":"uint256[]","internalType":"uint256[]"}],"stateMutability":"nonpayable"},{"type":"function","name":"batchDepositInfoUpdate","inputs":[{"name":"maxCount","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"operatorsLeft","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"cancelGeneralDelayedPenalty","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"amount","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"changeNodeOperatorAddresses","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"newManagerAddress","type":"address","internalType":"address"},{"name":"newRewardAddress","type":"address","internalType":"address"}],"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":"compensateGeneralDelayedPenalty","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"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":"finalizeUpgradeV3","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":"getKeyAllocatedBalances","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"startIndex","type":"uint256","internalType":"uint256"},{"name":"keysCount","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"balances","type":"uint256[]","internalType":"uint256[]"}],"stateMutability":"view"},{"type":"function","name":"getKeyConfirmedBalances","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"startIndex","type":"uint256","internalType":"uint256"},{"name":"keysCount","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"balances","type":"uint256[]","internalType":"uint256[]"}],"stateMutability":"view"},{"type":"function","name":"getKeysForTopUp","inputs":[{"name":"maxKeyCount","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"pubkeys","type":"bytes[]","internalType":"bytes[]"}],"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":"getNodeOperatorBalance","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getNodeOperatorDepositInfoToUpdateCount","inputs":[],"outputs":[{"name":"count","type":"uint256","internalType":"uint256"}],"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":"getNodeOperatorOwner","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"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":"getRoleMembers","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"address[]","internalType":"address[]"}],"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":"keys","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":"getTopUpQueue","inputs":[],"outputs":[{"name":"enabled","type":"bool","internalType":"bool"},{"name":"limit","type":"uint256","internalType":"uint256"},{"name":"length","type":"uint256","internalType":"uint256"},{"name":"head","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getTopUpQueueItem","inputs":[{"name":"index","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"keyIndex","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getTotalModuleStake","inputs":[],"outputs":[{"name":"","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"},{"name":"topUpQueueLimit","type":"uint8","internalType":"uint8"}],"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":"proofSlotTimestamp","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":"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":"obtainDepositData","inputs":[{"name":"depositsCount","type":"uint256","internalType":"uint256"},{"name":"depositCalldata","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":"view"},{"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":"elWithdrawalRequestFeePaid","type":"uint256","internalType":"uint256"},{"name":"exitType","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"onWithdrawalCredentialsChanged","inputs":[],"outputs":[],"stateMutability":"view"},{"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":"rebuildTotalWithdrawnValidators","inputs":[],"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":"reportGeneralDelayedPenalty","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"penaltyType","type":"bytes32","internalType":"bytes32"},{"name":"amount","type":"uint256","internalType":"uint256"},{"name":"details","type":"string","internalType":"string"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"reportRegularWithdrawnValidators","inputs":[{"name":"validatorInfos","type":"tuple[]","internalType":"struct WithdrawnValidatorInfo[]","components":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"keyIndex","type":"uint256","internalType":"uint256"},{"name":"exitBalance","type":"uint256","internalType":"uint256"},{"name":"slashingPenalty","type":"uint256","internalType":"uint256"},{"name":"isSlashed","type":"bool","internalType":"bool"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"reportSlashedWithdrawnValidators","inputs":[{"name":"validatorInfos","type":"tuple[]","internalType":"struct WithdrawnValidatorInfo[]","components":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"keyIndex","type":"uint256","internalType":"uint256"},{"name":"exitBalance","type":"uint256","internalType":"uint256"},{"name":"slashingPenalty","type":"uint256","internalType":"uint256"},{"name":"isSlashed","type":"bool","internalType":"bool"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"reportValidatorBalance","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"keyIndex","type":"uint256","internalType":"uint256"},{"name":"currentBalanceWei","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"reportValidatorExitDelay","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"proofSlotTimestamp","type":"uint256","internalType":"uint256"},{"name":"publicKey","type":"bytes","internalType":"bytes"},{"name":"eligibleToExitInSec","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"reportValidatorSlashing","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"keyIndex","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"requestFullDepositInfoUpdate","inputs":[],"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":"rewindTopUpQueue","inputs":[{"name":"to","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setTopUpQueueLimit","inputs":[{"name":"limit","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"settleGeneralDelayedPenalty","inputs":[{"name":"nodeOperatorIds","type":"uint256[]","internalType":"uint256[]"},{"name":"bondLockNonces","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":"unsafeUpdateValidatorsCount","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"exitedValidatorsCount","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateDepositInfo","inputs":[{"name":"nodeOperatorId","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":"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":"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":"FullDepositInfoUpdateRequested","inputs":[],"anonymous":false},{"type":"event","name":"GeneralDelayedPenaltyCancelled","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"GeneralDelayedPenaltyCompensated","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"GeneralDelayedPenaltyReported","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"penaltyType","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"additionalFine","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"details","type":"string","indexed":false,"internalType":"string"}],"anonymous":false},{"type":"event","name":"GeneralDelayedPenaltySettled","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"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":"KeyAllocatedBalanceChanged","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"keyIndex","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"newTotal","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"KeyConfirmedBalanceChanged","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"keyIndex","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"newBalance","type":"uint256","indexed":false,"internalType":"uint256"}],"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":"NodeOperatorBalanceUpdated","inputs":[{"name":"operatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"balanceWei","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"NodeOperatorDepositInfoFullyUpdated","inputs":[],"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":"TopUpQueueItemProcessed","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"keyIndex","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"TopUpQueueLimitSet","inputs":[{"name":"limit","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"TopUpQueueRewound","inputs":[{"name":"to","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":"TotalWithdrawnValidatorsRebuilt","inputs":[{"name":"totalWithdrawnValidators","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ValidatorSlashingReported","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"keyIndex","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"pubkey","type":"bytes","indexed":false,"internalType":"bytes"}],"anonymous":false},{"type":"event","name":"ValidatorWithdrawn","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"keyIndex","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"exitBalance","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"slashingPenalty","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"pubkey","type":"bytes","indexed":false,"internalType":"bytes"}],"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":"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":"CannotAddKeys","inputs":[]},{"type":"error","name":"DepositInfoIsNotUpToDate","inputs":[]},{"type":"error","name":"DepositQueueIsEmpty","inputs":[]},{"type":"error","name":"DepositableKeysWithUnsupportedWithdrawalCredentials","inputs":[]},{"type":"error","name":"FailedToSendEther","inputs":[]},{"type":"error","name":"InvalidAmount","inputs":[]},{"type":"error","name":"InvalidInitialization","inputs":[]},{"type":"error","name":"InvalidInput","inputs":[]},{"type":"error","name":"InvalidManagerAddress","inputs":[]},{"type":"error","name":"InvalidRewardAddress","inputs":[]},{"type":"error","name":"InvalidTopUpOrder","inputs":[]},{"type":"error","name":"InvalidVetKeysPointer","inputs":[]},{"type":"error","name":"InvalidWithdrawnValidatorInfo","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":"ResumedExpected","inputs":[]},{"type":"error","name":"RewindForward","inputs":[]},{"type":"error","name":"SafeCastOverflowedUintDowncast","inputs":[{"name":"bits","type":"uint8","internalType":"uint8"},{"name":"value","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"SameAddress","inputs":[]},{"type":"error","name":"SameTopUpQueueLimit","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":"SlashingPenaltyIsNotApplicable","inputs":[]},{"type":"error","name":"TopUpQueueDisabled","inputs":[]},{"type":"error","name":"TopUpQueueIsEmpty","inputs":[]},{"type":"error","name":"TopUpQueueIsFull","inputs":[]},{"type":"error","name":"UnexpectedExtraKey","inputs":[]},{"type":"error","name":"UnreportableBalance","inputs":[]},{"type":"error","name":"UpgradeIsNotFinalized","inputs":[]},{"type":"error","name":"ValidatorSlashingAlreadyReported","inputs":[]},{"type":"error","name":"ZeroAccountingAddress","inputs":[]},{"type":"error","name":"ZeroAdminAddress","inputs":[]},{"type":"error","name":"ZeroExitBalance","inputs":[]},{"type":"error","name":"ZeroExitPenaltiesAddress","inputs":[]},{"type":"error","name":"ZeroLocatorAddress","inputs":[]},{"type":"error","name":"ZeroManagerAddress","inputs":[]},{"type":"error","name":"ZeroModuleType","inputs":[]},{"type":"error","name":"ZeroParametersRegistryAddress","inputs":[]},{"type":"error","name":"ZeroPauseDuration","inputs":[]},{"type":"error","name":"ZeroPenaltyType","inputs":[]},{"type":"error","name":"ZeroRewardAddress","inputs":[]},{"type":"error","name":"ZeroSenderAddress","inputs":[]},{"type":"error","name":"ZeroTopUpQueueLimit","inputs":[]}] diff --git a/interfaces/CSPermissionlessGate.json b/interfaces/CSPermissionlessGate.json deleted file mode 100644 index d7e5a505..00000000 --- a/interfaces/CSPermissionlessGate.json +++ /dev/null @@ -1 +0,0 @@ -[{"inputs":[{"internalType":"address","name":"module","type":"address"},{"internalType":"address","name":"admin","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":"ZeroAdminAddress","type":"error"},{"inputs":[],"name":"ZeroModuleAddress","type":"error"},{"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"},{"inputs":[],"name":"CURVE_ID","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":"MODULE","outputs":[{"internalType":"contract ICSModule","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RECOVERER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"keysCount","type":"uint256"},{"internalType":"bytes","name":"publicKeys","type":"bytes"},{"internalType":"bytes","name":"signatures","type":"bytes"},{"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":"addNodeOperatorETH","outputs":[{"internalType":"uint256","name":"nodeOperatorId","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"keysCount","type":"uint256"},{"internalType":"bytes","name":"publicKeys","type":"bytes"},{"internalType":"bytes","name":"signatures","type":"bytes"},{"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"},{"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"},{"internalType":"address","name":"referrer","type":"address"}],"name":"addNodeOperatorStETH","outputs":[{"internalType":"uint256","name":"nodeOperatorId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"keysCount","type":"uint256"},{"internalType":"bytes","name":"publicKeys","type":"bytes"},{"internalType":"bytes","name":"signatures","type":"bytes"},{"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"},{"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"},{"internalType":"address","name":"referrer","type":"address"}],"name":"addNodeOperatorWstETH","outputs":[{"internalType":"uint256","name":"nodeOperatorId","type":"uint256"}],"stateMutability":"nonpayable","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":"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":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","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/CSStrikes.json b/interfaces/CSStrikes.json deleted file mode 100644 index 6ccc28dd..00000000 --- a/interfaces/CSStrikes.json +++ /dev/null @@ -1 +0,0 @@ -[{"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/CSVettedGate.json b/interfaces/CSVettedGate.json deleted file mode 100644 index c65aac7e..00000000 --- a/interfaces/CSVettedGate.json +++ /dev/null @@ -1 +0,0 @@ -[{"inputs":[{"internalType":"address","name":"module","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":"AlreadyConsumed","type":"error"},{"inputs":[],"name":"InvalidCurveId","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"InvalidProof","type":"error"},{"inputs":[],"name":"InvalidReferralsThreshold","type":"error"},{"inputs":[],"name":"InvalidTreeCid","type":"error"},{"inputs":[],"name":"InvalidTreeRoot","type":"error"},{"inputs":[],"name":"NodeOperatorDoesNotExist","type":"error"},{"inputs":[],"name":"NotAllowedToClaim","type":"error"},{"inputs":[],"name":"NotEnoughReferrals","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[],"name":"PauseUntilMustBeInFuture","type":"error"},{"inputs":[],"name":"PausedExpected","type":"error"},{"inputs":[],"name":"ReferralProgramIsActive","type":"error"},{"inputs":[],"name":"ReferralProgramIsNotActive","type":"error"},{"inputs":[],"name":"ResumedExpected","type":"error"},{"inputs":[],"name":"ZeroAdminAddress","type":"error"},{"inputs":[],"name":"ZeroModuleAddress","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"member","type":"address"}],"name":"Consumed","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":true,"internalType":"uint256","name":"season","type":"uint256"}],"name":"ReferralProgramSeasonEnded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"season","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"referralCurveId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"referralsThreshold","type":"uint256"}],"name":"ReferralProgramSeasonStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"referrer","type":"address"},{"indexed":true,"internalType":"uint256","name":"season","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"referralNodeOperatorId","type":"uint256"}],"name":"ReferralRecorded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"referrer","type":"address"},{"indexed":true,"internalType":"uint256","name":"season","type":"uint256"}],"name":"ReferrerConsumed","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":"bytes32","name":"treeRoot","type":"bytes32"},{"indexed":false,"internalType":"string","name":"treeCid","type":"string"}],"name":"TreeSet","type":"event"},{"inputs":[],"name":"ACCOUNTING","outputs":[{"internalType":"contract ICSAccounting","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"END_REFERRAL_SEASON_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MODULE","outputs":[{"internalType":"contract ICSModule","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":"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":"SET_TREE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"START_REFERRAL_SEASON_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"keysCount","type":"uint256"},{"internalType":"bytes","name":"publicKeys","type":"bytes"},{"internalType":"bytes","name":"signatures","type":"bytes"},{"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":"bytes32[]","name":"proof","type":"bytes32[]"},{"internalType":"address","name":"referrer","type":"address"}],"name":"addNodeOperatorETH","outputs":[{"internalType":"uint256","name":"nodeOperatorId","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"keysCount","type":"uint256"},{"internalType":"bytes","name":"publicKeys","type":"bytes"},{"internalType":"bytes","name":"signatures","type":"bytes"},{"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"},{"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"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"},{"internalType":"address","name":"referrer","type":"address"}],"name":"addNodeOperatorStETH","outputs":[{"internalType":"uint256","name":"nodeOperatorId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"keysCount","type":"uint256"},{"internalType":"bytes","name":"publicKeys","type":"bytes"},{"internalType":"bytes","name":"signatures","type":"bytes"},{"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"},{"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"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"},{"internalType":"address","name":"referrer","type":"address"}],"name":"addNodeOperatorWstETH","outputs":[{"internalType":"uint256","name":"nodeOperatorId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nodeOperatorId","type":"uint256"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"claimBondCurve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nodeOperatorId","type":"uint256"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"claimReferrerBondCurve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"curveId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"endCurrentReferralProgramSeason","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getInitializedVersion","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"referrer","type":"address"}],"name":"getReferralsCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"referrer","type":"address"},{"internalType":"uint256","name":"season","type":"uint256"}],"name":"getReferralsCount","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":"member","type":"address"}],"name":"hashLeaf","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"_curveId","type":"uint256"},{"internalType":"bytes32","name":"_treeRoot","type":"bytes32"},{"internalType":"string","name":"_treeCid","type":"string"},{"internalType":"address","name":"admin","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"member","type":"address"}],"name":"isConsumed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isReferralProgramSeasonActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"referrer","type":"address"}],"name":"isReferrerConsumed","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":"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":[],"name":"referralCurveId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"referralProgramSeasonNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"referralsThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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":"bytes32","name":"_treeRoot","type":"bytes32"},{"internalType":"string","name":"_treeCid","type":"string"}],"name":"setTreeParams","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_referralCurveId","type":"uint256"},{"internalType":"uint256","name":"_referralsThreshold","type":"uint256"}],"name":"startNewReferralProgramSeason","outputs":[{"internalType":"uint256","name":"season","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"treeCid","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"treeRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"member","type":"address"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"verifyProof","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}] diff --git a/interfaces/CreateOrUpdateOperatorGroup.json b/interfaces/CreateOrUpdateOperatorGroup.json new file mode 100644 index 00000000..4edd3d22 --- /dev/null +++ b/interfaces/CreateOrUpdateOperatorGroup.json @@ -0,0 +1 @@ +[{"inputs":[{"internalType":"address","name":"_trustedCaller","type":"address"},{"internalType":"string","name":"_name","type":"string"},{"internalType":"address","name":"_module","type":"address"},{"internalType":"uint256","name":"_allowedExtModuleId","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"allowedExternalModuleId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_creator","type":"address"},{"internalType":"bytes","name":"_evmScriptCallData","type":"bytes"}],"name":"createEVMScript","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_evmScriptCallData","type":"bytes"}],"name":"decodeEVMScriptCallData","outputs":[{"internalType":"uint256","name":"groupId","type":"uint256"},{"components":[{"internalType":"string","name":"name","type":"string"},{"components":[{"internalType":"uint64","name":"nodeOperatorId","type":"uint64"},{"internalType":"uint16","name":"share","type":"uint16"}],"internalType":"struct IMetaRegistry.SubNodeOperator[]","name":"subNodeOperators","type":"tuple[]"},{"components":[{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct IMetaRegistry.ExternalOperator[]","name":"externalOperators","type":"tuple[]"}],"internalType":"struct IMetaRegistry.OperatorGroup","name":"currentGroupInfo","type":"tuple"},{"components":[{"internalType":"string","name":"name","type":"string"},{"components":[{"internalType":"uint64","name":"nodeOperatorId","type":"uint64"},{"internalType":"uint16","name":"share","type":"uint16"}],"internalType":"struct IMetaRegistry.SubNodeOperator[]","name":"subNodeOperators","type":"tuple[]"},{"components":[{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct IMetaRegistry.ExternalOperator[]","name":"externalOperators","type":"tuple[]"}],"internalType":"struct IMetaRegistry.OperatorGroup","name":"groupInfo","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"_externalOperatorData","type":"bytes"}],"name":"decodeNORExtOperatorData","outputs":[{"internalType":"uint8","name":"moduleId","type":"uint8"},{"internalType":"uint64","name":"nodeOperatorId","type":"uint64"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint8","name":"moduleId","type":"uint8"},{"internalType":"uint64","name":"nodeOperatorId","type":"uint64"}],"name":"encodeNORExtOperatorData","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"metaRegistry","outputs":[{"internalType":"contract IMetaRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"module","outputs":[{"internalType":"contract ICuratedModule","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakingRouter","outputs":[{"internalType":"contract IStakingRouter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"trustedCaller","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"groupId","type":"uint256"},{"components":[{"internalType":"string","name":"name","type":"string"},{"components":[{"internalType":"uint64","name":"nodeOperatorId","type":"uint64"},{"internalType":"uint16","name":"share","type":"uint16"}],"internalType":"struct IMetaRegistry.SubNodeOperator[]","name":"subNodeOperators","type":"tuple[]"},{"components":[{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct IMetaRegistry.ExternalOperator[]","name":"externalOperators","type":"tuple[]"}],"internalType":"struct IMetaRegistry.OperatorGroup","name":"currentGroupInfo","type":"tuple"},{"components":[{"internalType":"string","name":"name","type":"string"},{"components":[{"internalType":"uint64","name":"nodeOperatorId","type":"uint64"},{"internalType":"uint16","name":"share","type":"uint16"}],"internalType":"struct IMetaRegistry.SubNodeOperator[]","name":"subNodeOperators","type":"tuple[]"},{"components":[{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct IMetaRegistry.ExternalOperator[]","name":"externalOperators","type":"tuple[]"}],"internalType":"struct IMetaRegistry.OperatorGroup","name":"newGroupInfo","type":"tuple"}],"name":"validateInputData","outputs":[],"stateMutability":"view","type":"function"}] diff --git a/interfaces/CuratedGate.json b/interfaces/CuratedGate.json new file mode 100644 index 00000000..ce8e7290 --- /dev/null +++ b/interfaces/CuratedGate.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 IAccounting"}],"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":"META_REGISTRY","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IMetaRegistry"}],"stateMutability":"view"},{"type":"function","name":"MODULE","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ICuratedModule"}],"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_TREE_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"createNodeOperator","inputs":[{"name":"name","type":"string","internalType":"string"},{"name":"description","type":"string","internalType":"string"},{"name":"managerAddress","type":"address","internalType":"address"},{"name":"rewardAddress","type":"address","internalType":"address"},{"name":"proof","type":"bytes32[]","internalType":"bytes32[]"}],"outputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"curveId","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":"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":"getRoleMembers","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"address[]","internalType":"address[]"}],"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":"name","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":"name","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"type":"function","name":"pauseFor","inputs":[{"name":"duration","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":"setName","inputs":[{"name":"name","type":"string","internalType":"string"}],"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":"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":"NameSet","inputs":[{"name":"name","type":"string","indexed":false,"internalType":"string"}],"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":"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":"InvalidInitialization","inputs":[]},{"type":"error","name":"InvalidName","inputs":[]},{"type":"error","name":"InvalidProof","inputs":[]},{"type":"error","name":"InvalidTreeCid","inputs":[]},{"type":"error","name":"InvalidTreeRoot","inputs":[]},{"type":"error","name":"NotInitializing","inputs":[]},{"type":"error","name":"PauseUntilMustBeInFuture","inputs":[]},{"type":"error","name":"PausedExpected","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/CuratedModule.json b/interfaces/CuratedModule.json new file mode 100644 index 00000000..61d16cb1 --- /dev/null +++ b/interfaces/CuratedModule.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"},{"name":"metaRegistry","type":"address","internalType":"address"}],"stateMutability":"nonpayable"},{"type":"function","name":"ACCOUNTING","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IAccounting"}],"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":"EXIT_PENALTIES","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IExitPenalties"}],"stateMutability":"view"},{"type":"function","name":"FEE_DISTRIBUTOR","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"LIDO_LOCATOR","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ILidoLocator"}],"stateMutability":"view"},{"type":"function","name":"META_REGISTRY","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IMetaRegistry"}],"stateMutability":"view"},{"type":"function","name":"OPERATOR_ADDRESSES_ADMIN_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"PARAMETERS_REGISTRY","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IParametersRegistry"}],"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_GENERAL_DELAYED_PENALTY_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"REPORT_REGULAR_WITHDRAWN_VALIDATORS_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"REPORT_SLASHED_WITHDRAWN_VALIDATORS_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_GENERAL_DELAYED_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":"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 IAccounting.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 IAccounting.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":"allocateDeposits","inputs":[{"name":"maxDepositAmount","type":"uint256","internalType":"uint256"},{"name":"pubkeys","type":"bytes[]","internalType":"bytes[]"},{"name":"keyIndices","type":"uint256[]","internalType":"uint256[]"},{"name":"operatorIds","type":"uint256[]","internalType":"uint256[]"},{"name":"topUpLimits","type":"uint256[]","internalType":"uint256[]"}],"outputs":[{"name":"allocations","type":"uint256[]","internalType":"uint256[]"}],"stateMutability":"nonpayable"},{"type":"function","name":"batchDepositInfoUpdate","inputs":[{"name":"maxCount","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"operatorsLeft","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"cancelGeneralDelayedPenalty","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"amount","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"changeNodeOperatorAddresses","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"newManagerAddress","type":"address","internalType":"address"},{"name":"newRewardAddress","type":"address","internalType":"address"}],"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":"compensateGeneralDelayedPenalty","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"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":"","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":"exitDeadlineThreshold","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getActiveNodeOperatorsCount","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getDepositAllocationTargets","inputs":[],"outputs":[{"name":"currentValidators","type":"uint256[]","internalType":"uint256[]"},{"name":"targetValidators","type":"uint256[]","internalType":"uint256[]"}],"stateMutability":"view"},{"type":"function","name":"getDepositsAllocation","inputs":[{"name":"maxDepositAmount","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"allocated","type":"uint256","internalType":"uint256"},{"name":"operatorIds","type":"uint256[]","internalType":"uint256[]"},{"name":"allocations","type":"uint256[]","internalType":"uint256[]"}],"stateMutability":"view"},{"type":"function","name":"getInitializedVersion","inputs":[],"outputs":[{"name":"","type":"uint64","internalType":"uint64"}],"stateMutability":"view"},{"type":"function","name":"getKeyAllocatedBalances","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"startIndex","type":"uint256","internalType":"uint256"},{"name":"keysCount","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"balances","type":"uint256[]","internalType":"uint256[]"}],"stateMutability":"view"},{"type":"function","name":"getKeyConfirmedBalances","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"startIndex","type":"uint256","internalType":"uint256"},{"name":"keysCount","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"balances","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"},{"name":"usedPriorityQueue","type":"bool","internalType":"bool"}]}],"stateMutability":"view"},{"type":"function","name":"getNodeOperatorBalance","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getNodeOperatorDepositInfoToUpdateCount","inputs":[],"outputs":[{"name":"count","type":"uint256","internalType":"uint256"}],"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":"getNodeOperatorOwner","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"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":"getNodeOperatorWeightAndExternalStake","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"weight","type":"uint256","internalType":"uint256"},{"name":"externalStake","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":"getOperatorWeights","inputs":[{"name":"operatorIds","type":"uint256[]","internalType":"uint256[]"}],"outputs":[{"name":"operatorWeights","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":"getRoleMembers","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"address[]","internalType":"address[]"}],"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":"keys","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":"getTopUpAllocationTargets","inputs":[],"outputs":[{"name":"currentAllocations","type":"uint256[]","internalType":"uint256[]"},{"name":"targetAllocations","type":"uint256[]","internalType":"uint256[]"}],"stateMutability":"view"},{"type":"function","name":"getTotalModuleStake","inputs":[],"outputs":[{"name":"","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":"proofSlotTimestamp","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":"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":"notifyNodeOperatorWeightChange","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"oldWeight","type":"uint256","internalType":"uint256"},{"name":"newWeight","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"obtainDepositData","inputs":[{"name":"depositsCount","type":"uint256","internalType":"uint256"},{"name":"depositCalldata","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":"view"},{"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":"elWithdrawalRequestFeePaid","type":"uint256","internalType":"uint256"},{"name":"exitType","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"onWithdrawalCredentialsChanged","inputs":[],"outputs":[],"stateMutability":"view"},{"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":"reportGeneralDelayedPenalty","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"penaltyType","type":"bytes32","internalType":"bytes32"},{"name":"amount","type":"uint256","internalType":"uint256"},{"name":"details","type":"string","internalType":"string"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"reportRegularWithdrawnValidators","inputs":[{"name":"validatorInfos","type":"tuple[]","internalType":"struct WithdrawnValidatorInfo[]","components":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"keyIndex","type":"uint256","internalType":"uint256"},{"name":"exitBalance","type":"uint256","internalType":"uint256"},{"name":"slashingPenalty","type":"uint256","internalType":"uint256"},{"name":"isSlashed","type":"bool","internalType":"bool"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"reportSlashedWithdrawnValidators","inputs":[{"name":"validatorInfos","type":"tuple[]","internalType":"struct WithdrawnValidatorInfo[]","components":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"keyIndex","type":"uint256","internalType":"uint256"},{"name":"exitBalance","type":"uint256","internalType":"uint256"},{"name":"slashingPenalty","type":"uint256","internalType":"uint256"},{"name":"isSlashed","type":"bool","internalType":"bool"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"reportValidatorBalance","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"keyIndex","type":"uint256","internalType":"uint256"},{"name":"currentBalanceWei","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"reportValidatorExitDelay","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"proofSlotTimestamp","type":"uint256","internalType":"uint256"},{"name":"publicKey","type":"bytes","internalType":"bytes"},{"name":"eligibleToExitInSec","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"reportValidatorSlashing","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"keyIndex","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"requestFullDepositInfoUpdate","inputs":[],"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":"settleGeneralDelayedPenalty","inputs":[{"name":"nodeOperatorIds","type":"uint256[]","internalType":"uint256[]"},{"name":"bondLockNonces","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":"unsafeUpdateValidatorsCount","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"exitedValidatorsCount","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateDepositInfo","inputs":[{"name":"nodeOperatorId","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":"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":"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":"FullDepositInfoUpdateRequested","inputs":[],"anonymous":false},{"type":"event","name":"GeneralDelayedPenaltyCancelled","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"GeneralDelayedPenaltyCompensated","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"GeneralDelayedPenaltyReported","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"penaltyType","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"additionalFine","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"details","type":"string","indexed":false,"internalType":"string"}],"anonymous":false},{"type":"event","name":"GeneralDelayedPenaltySettled","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"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":"KeyAllocatedBalanceChanged","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"keyIndex","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"newTotal","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"KeyConfirmedBalanceChanged","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"keyIndex","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"newBalance","type":"uint256","indexed":false,"internalType":"uint256"}],"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":"NodeOperatorBalanceUpdated","inputs":[{"name":"operatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"balanceWei","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"NodeOperatorDepositInfoFullyUpdated","inputs":[],"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":"TotalWithdrawnValidatorsRebuilt","inputs":[{"name":"totalWithdrawnValidators","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ValidatorSlashingReported","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"keyIndex","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"pubkey","type":"bytes","indexed":false,"internalType":"bytes"}],"anonymous":false},{"type":"event","name":"ValidatorWithdrawn","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"keyIndex","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"exitBalance","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"slashingPenalty","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"pubkey","type":"bytes","indexed":false,"internalType":"bytes"}],"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":"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":"CannotAddKeys","inputs":[]},{"type":"error","name":"DepositInfoIsNotUpToDate","inputs":[]},{"type":"error","name":"DepositableKeysWithUnsupportedWithdrawalCredentials","inputs":[]},{"type":"error","name":"FailedToSendEther","inputs":[]},{"type":"error","name":"InvalidAmount","inputs":[]},{"type":"error","name":"InvalidInitialization","inputs":[]},{"type":"error","name":"InvalidInput","inputs":[]},{"type":"error","name":"InvalidManagerAddress","inputs":[]},{"type":"error","name":"InvalidRewardAddress","inputs":[]},{"type":"error","name":"InvalidSigningKey","inputs":[]},{"type":"error","name":"InvalidVetKeysPointer","inputs":[]},{"type":"error","name":"InvalidWithdrawnValidatorInfo","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":"ResumedExpected","inputs":[]},{"type":"error","name":"SameAddress","inputs":[]},{"type":"error","name":"SenderIsNotEligible","inputs":[]},{"type":"error","name":"SenderIsNotManagerAddress","inputs":[]},{"type":"error","name":"SenderIsNotMetaRegistry","inputs":[]},{"type":"error","name":"SenderIsNotProposedAddress","inputs":[]},{"type":"error","name":"SenderIsNotRewardAddress","inputs":[]},{"type":"error","name":"SigningKeysInvalidOffset","inputs":[]},{"type":"error","name":"SlashingPenaltyIsNotApplicable","inputs":[]},{"type":"error","name":"UnreportableBalance","inputs":[]},{"type":"error","name":"ValidatorSlashingAlreadyReported","inputs":[]},{"type":"error","name":"ZeroAccountingAddress","inputs":[]},{"type":"error","name":"ZeroAdminAddress","inputs":[]},{"type":"error","name":"ZeroExitBalance","inputs":[]},{"type":"error","name":"ZeroExitPenaltiesAddress","inputs":[]},{"type":"error","name":"ZeroLocatorAddress","inputs":[]},{"type":"error","name":"ZeroManagerAddress","inputs":[]},{"type":"error","name":"ZeroMetaRegistryAddress","inputs":[]},{"type":"error","name":"ZeroModuleType","inputs":[]},{"type":"error","name":"ZeroParametersRegistryAddress","inputs":[]},{"type":"error","name":"ZeroPauseDuration","inputs":[]},{"type":"error","name":"ZeroPenaltyType","inputs":[]},{"type":"error","name":"ZeroRewardAddress","inputs":[]},{"type":"error","name":"ZeroSenderAddress","inputs":[]}] diff --git a/interfaces/CSEjector.json b/interfaces/Ejector.json similarity index 100% rename from interfaces/CSEjector.json rename to interfaces/Ejector.json diff --git a/interfaces/ExitPenalties.json b/interfaces/ExitPenalties.json new file mode 100644 index 00000000..7deddc0b --- /dev/null +++ b/interfaces/ExitPenalties.json @@ -0,0 +1 @@ +[{"type":"constructor","inputs":[{"name":"module","type":"address","internalType":"address"},{"name":"strikes","type":"address","internalType":"address"}],"stateMutability":"nonpayable"},{"type":"function","name":"ACCOUNTING","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IAccounting"}],"stateMutability":"view"},{"type":"function","name":"MODULE","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IBaseModule"}],"stateMutability":"view"},{"type":"function","name":"PARAMETERS_REGISTRY","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IParametersRegistry"}],"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":"delayFee","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":"elWithdrawalRequestFee","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":"elWithdrawalRequestFeePaid","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":"delayFee","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":"ZeroStrikesAddress","inputs":[]}] diff --git a/interfaces/FeeDistributor.json b/interfaces/FeeDistributor.json new file mode 100644 index 00000000..624ef1b2 --- /dev/null +++ b/interfaces/FeeDistributor.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":"cumulativeFeeShares","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":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"distributed","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"distributionDataHistoryCount","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"finalizeUpgradeV3","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"getFeesToDistribute","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"cumulativeFeeShares","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 IFeeDistributor.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":"getRoleMembers","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"address[]","internalType":"address[]"}],"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":"InvalidRebateRecipientAddress","inputs":[]},{"type":"error","name":"InvalidShares","inputs":[]},{"type":"error","name":"InvalidTreeCid","inputs":[]},{"type":"error","name":"InvalidTreeRoot","inputs":[]},{"type":"error","name":"NotAllowedToRecover","inputs":[]},{"type":"error","name":"NotEnoughShares","inputs":[]},{"type":"error","name":"NotInitializing","inputs":[]},{"type":"error","name":"SameRebateRecipientAddress","inputs":[]},{"type":"error","name":"SenderIsNotAccounting","inputs":[]},{"type":"error","name":"SenderIsNotOracle","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/FeeOracle.json similarity index 100% rename from interfaces/CSFeeOracle.json rename to interfaces/FeeOracle.json diff --git a/interfaces/MerkleGate.json b/interfaces/MerkleGate.json new file mode 100644 index 00000000..21496f41 --- /dev/null +++ b/interfaces/MerkleGate.json @@ -0,0 +1 @@ +[{"type":"function","name":"DEFAULT_ADMIN_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":"SET_TREE_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"curveId","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":"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":"getRoleMembers","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"address[]","internalType":"address[]"}],"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":"name_","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":"name","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"type":"function","name":"pauseFor","inputs":[{"name":"duration","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":"setName","inputs":[{"name":"name","type":"string","internalType":"string"}],"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":"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":"NameSet","inputs":[{"name":"name","type":"string","indexed":false,"internalType":"string"}],"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":"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":"InvalidInitialization","inputs":[]},{"type":"error","name":"InvalidName","inputs":[]},{"type":"error","name":"InvalidProof","inputs":[]},{"type":"error","name":"InvalidTreeCid","inputs":[]},{"type":"error","name":"InvalidTreeRoot","inputs":[]},{"type":"error","name":"NotInitializing","inputs":[]},{"type":"error","name":"PauseUntilMustBeInFuture","inputs":[]},{"type":"error","name":"PausedExpected","inputs":[]},{"type":"error","name":"ResumedExpected","inputs":[]},{"type":"error","name":"ZeroAdminAddress","inputs":[]},{"type":"error","name":"ZeroPauseDuration","inputs":[]}] diff --git a/interfaces/MetaRegistry.json b/interfaces/MetaRegistry.json new file mode 100644 index 00000000..b6da3a4e --- /dev/null +++ b/interfaces/MetaRegistry.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 IAccounting"}],"stateMutability":"view"},{"type":"function","name":"DEFAULT_ADMIN_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"MANAGE_OPERATOR_GROUPS_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"MODULE","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ICuratedModule"}],"stateMutability":"view"},{"type":"function","name":"NO_GROUP_ID","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"SET_BOND_CURVE_WEIGHT_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"SET_OPERATOR_INFO_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"STAKING_ROUTER","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IStakingRouter"}],"stateMutability":"view"},{"type":"function","name":"createOrUpdateOperatorGroup","inputs":[{"name":"groupId","type":"uint256","internalType":"uint256"},{"name":"groupInfo","type":"tuple","internalType":"struct IMetaRegistry.OperatorGroup","components":[{"name":"name","type":"string","internalType":"string"},{"name":"subNodeOperators","type":"tuple[]","internalType":"struct IMetaRegistry.SubNodeOperator[]","components":[{"name":"nodeOperatorId","type":"uint64","internalType":"uint64"},{"name":"share","type":"uint16","internalType":"uint16"}]},{"name":"externalOperators","type":"tuple[]","internalType":"struct IMetaRegistry.ExternalOperator[]","components":[{"name":"data","type":"bytes","internalType":"bytes"}]}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"getBondCurveWeight","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"weight","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getExternalOperatorGroupId","inputs":[{"name":"op","type":"tuple","internalType":"struct IMetaRegistry.ExternalOperator","components":[{"name":"data","type":"bytes","internalType":"bytes"}]}],"outputs":[{"name":"operatorGroupId","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getInitializedVersion","inputs":[],"outputs":[{"name":"","type":"uint64","internalType":"uint64"}],"stateMutability":"view"},{"type":"function","name":"getNodeOperatorGroupId","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"operatorGroupId","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getNodeOperatorWeight","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"weight","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getNodeOperatorWeightAndExternalStake","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"weight","type":"uint256","internalType":"uint256"},{"name":"externalStake","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getOperatorGroup","inputs":[{"name":"groupId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"groupInfo","type":"tuple","internalType":"struct IMetaRegistry.OperatorGroup","components":[{"name":"name","type":"string","internalType":"string"},{"name":"subNodeOperators","type":"tuple[]","internalType":"struct IMetaRegistry.SubNodeOperator[]","components":[{"name":"nodeOperatorId","type":"uint64","internalType":"uint64"},{"name":"share","type":"uint16","internalType":"uint16"}]},{"name":"externalOperators","type":"tuple[]","internalType":"struct IMetaRegistry.ExternalOperator[]","components":[{"name":"data","type":"bytes","internalType":"bytes"}]}]}],"stateMutability":"view"},{"type":"function","name":"getOperatorGroupsCount","inputs":[],"outputs":[{"name":"count","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getOperatorMetadata","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"metadata","type":"tuple","internalType":"struct OperatorMetadata","components":[{"name":"name","type":"string","internalType":"string"},{"name":"description","type":"string","internalType":"string"},{"name":"ownerEditsRestricted","type":"bool","internalType":"bool"}]}],"stateMutability":"view"},{"type":"function","name":"getOperatorWeights","inputs":[{"name":"nodeOperatorIds","type":"uint256[]","internalType":"uint256[]"}],"outputs":[{"name":"operatorWeights","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":"getRoleMembers","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"address[]","internalType":"address[]"}],"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":"refreshOperatorWeight","inputs":[{"name":"nodeOperatorId","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":"setBondCurveWeight","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"},{"name":"weight","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setOperatorMetadataAsAdmin","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"metadata","type":"tuple","internalType":"struct OperatorMetadata","components":[{"name":"name","type":"string","internalType":"string"},{"name":"description","type":"string","internalType":"string"},{"name":"ownerEditsRestricted","type":"bool","internalType":"bool"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setOperatorMetadataAsOwner","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"name","type":"string","internalType":"string"},{"name":"description","type":"string","internalType":"string"}],"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":"BondCurveWeightSet","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"weight","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":"NodeOperatorEffectiveWeightChanged","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"oldWeight","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"newWeight","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"OperatorGroupCleared","inputs":[{"name":"groupId","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"OperatorGroupCreated","inputs":[{"name":"groupId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"groupInfo","type":"tuple","indexed":false,"internalType":"struct IMetaRegistry.OperatorGroup","components":[{"name":"name","type":"string","internalType":"string"},{"name":"subNodeOperators","type":"tuple[]","internalType":"struct IMetaRegistry.SubNodeOperator[]","components":[{"name":"nodeOperatorId","type":"uint64","internalType":"uint64"},{"name":"share","type":"uint16","internalType":"uint16"}]},{"name":"externalOperators","type":"tuple[]","internalType":"struct IMetaRegistry.ExternalOperator[]","components":[{"name":"data","type":"bytes","internalType":"bytes"}]}]}],"anonymous":false},{"type":"event","name":"OperatorGroupUpdated","inputs":[{"name":"groupId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"groupInfo","type":"tuple","indexed":false,"internalType":"struct IMetaRegistry.OperatorGroup","components":[{"name":"name","type":"string","internalType":"string"},{"name":"subNodeOperators","type":"tuple[]","internalType":"struct IMetaRegistry.SubNodeOperator[]","components":[{"name":"nodeOperatorId","type":"uint64","internalType":"uint64"},{"name":"share","type":"uint16","internalType":"uint16"}]},{"name":"externalOperators","type":"tuple[]","internalType":"struct IMetaRegistry.ExternalOperator[]","components":[{"name":"data","type":"bytes","internalType":"bytes"}]}]}],"anonymous":false},{"type":"event","name":"OperatorMetadataSet","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"metadata","type":"tuple","indexed":false,"internalType":"struct OperatorMetadata","components":[{"name":"name","type":"string","internalType":"string"},{"name":"description","type":"string","internalType":"string"},{"name":"ownerEditsRestricted","type":"bool","internalType":"bool"}]}],"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":"AlreadyUsedAsExternalOperator","inputs":[]},{"type":"error","name":"InvalidBondCurveId","inputs":[]},{"type":"error","name":"InvalidBondCurveWeight","inputs":[]},{"type":"error","name":"InvalidExternalOperatorDataEntry","inputs":[]},{"type":"error","name":"InvalidInitialization","inputs":[]},{"type":"error","name":"InvalidOperatorGroup","inputs":[]},{"type":"error","name":"InvalidOperatorGroupId","inputs":[]},{"type":"error","name":"InvalidOperatorGroupName","inputs":[]},{"type":"error","name":"InvalidSubNodeOperatorShares","inputs":[]},{"type":"error","name":"ModuleAddressNotCached","inputs":[]},{"type":"error","name":"NodeOperatorAlreadyInGroup","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"NodeOperatorDoesNotExist","inputs":[]},{"type":"error","name":"NotInitializing","inputs":[]},{"type":"error","name":"OperatorDescriptionTooLong","inputs":[]},{"type":"error","name":"OperatorNameTooLong","inputs":[]},{"type":"error","name":"OwnerEditsRestricted","inputs":[]},{"type":"error","name":"SameBondCurveWeight","inputs":[]},{"type":"error","name":"SenderIsNotEligible","inputs":[]},{"type":"error","name":"ZeroAdminAddress","inputs":[]},{"type":"error","name":"ZeroModuleAddress","inputs":[]}] diff --git a/interfaces/ModuleAccounting.json b/interfaces/ModuleAccounting.json new file mode 100644 index 00000000..86b5eb58 --- /dev/null +++ b/interfaces/ModuleAccounting.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":"minBondLockPeriod","type":"uint256","internalType":"uint256"},{"name":"maxBondLockPeriod","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"BURNER","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IBurner"}],"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":"FEE_DISTRIBUTOR","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IFeeDistributor"}],"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_FEE_SPLITS","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":"MODULE","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IBaseModule"}],"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 IBondCurve.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":[{"name":"","type":"bool","internalType":"bool"}],"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":"compensateLockedBond","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"compensatedAmount","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"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 IAccounting.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 IAccounting.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 IAccounting.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 IAccounting.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":"finalizeUpgradeV3","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"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 IBondCurve.BondCurveData","components":[{"name":"intervals","type":"tuple[]","internalType":"struct IBondCurve.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":"getBondDebt","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getBondLockNonce","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 IBondCurve.BondCurveData","components":[{"name":"intervals","type":"tuple[]","internalType":"struct IBondCurve.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":"getCustomRewardsClaimer","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"getFeeSplitTransfers","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"splittableShares","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"transfers","type":"tuple[]","internalType":"struct IFeeSplits.SplitTransfer[]","components":[{"name":"recipient","type":"address","internalType":"address"},{"name":"shares","type":"uint256","internalType":"uint256"}]}],"stateMutability":"view"},{"type":"function","name":"getFeeSplits","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"tuple[]","internalType":"struct IFeeSplits.FeeSplit[]","components":[{"name":"recipient","type":"address","internalType":"address"},{"name":"share","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":"getLockedBond","inputs":[{"name":"nodeOperatorId","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 IBondLock.BondLockData","components":[{"name":"amount","type":"uint128","internalType":"uint128"},{"name":"until","type":"uint128","internalType":"uint128"}]}],"stateMutability":"view"},{"type":"function","name":"getNodeOperatorBondInfo","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"info","type":"tuple","internalType":"struct IAccounting.NodeOperatorBondInfo","components":[{"name":"currentBond","type":"uint256","internalType":"uint256"},{"name":"requiredBond","type":"uint256","internalType":"uint256"},{"name":"lockedBond","type":"uint256","internalType":"uint256"},{"name":"bondDebt","type":"uint256","internalType":"uint256"},{"name":"pendingSharesToSplit","type":"uint256","internalType":"uint256"}]}],"stateMutability":"view"},{"type":"function","name":"getPendingSharesToSplit","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"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":"getRoleMembers","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"address[]","internalType":"address[]"}],"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":"hasSplits","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"initialize","inputs":[{"name":"bondCurve","type":"tuple[]","internalType":"struct IBondCurve.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":"isLockExpired","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"isPaused","inputs":[],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"lockBond","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":[{"name":"penaltyCovered","type":"bool","internalType":"bool"}],"stateMutability":"nonpayable"},{"type":"function","name":"pullAndSplitFeeRewards","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":"releaseLockedBond","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"amount","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"released","type":"bool","internalType":"bool"}],"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":"setCustomRewardsClaimer","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"rewardsClaimer","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"settleLockedBond","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"bondLockNonce","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","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":"unlockExpiredLock","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateBondCurve","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"},{"name":"bondCurve","type":"tuple[]","internalType":"struct IBondCurve.BondCurveIntervalInput[]","components":[{"name":"minKeysCount","type":"uint256","internalType":"uint256"},{"name":"trend","type":"uint256","internalType":"uint256"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateFeeSplits","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"feeSplits","type":"tuple[]","internalType":"struct IFeeSplits.FeeSplit[]","components":[{"name":"recipient","type":"address","internalType":"address"},{"name":"share","type":"uint256","internalType":"uint256"}]},{"name":"cumulativeFeeShares","type":"uint256","internalType":"uint256"},{"name":"rewardsProof","type":"bytes32[]","internalType":"bytes32[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"event","name":"BondBurned","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"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":"amountToCharge","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 IBondCurve.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"},{"name":"setter","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"BondCurveUpdated","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"bondCurveIntervals","type":"tuple[]","indexed":false,"internalType":"struct IBondCurve.BondCurveIntervalInput[]","components":[{"name":"minKeysCount","type":"uint256","internalType":"uint256"},{"name":"trend","type":"uint256","internalType":"uint256"}]}],"anonymous":false},{"type":"event","name":"BondDebtCovered","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"BondDebtIncreased","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"amount","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":"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":"BondLockNonceIncremented","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"newNonce","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":"CustomRewardsClaimerSet","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"rewardsClaimer","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":"FeeSplitsSet","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"feeSplits","type":"tuple[]","indexed":false,"internalType":"struct IFeeSplits.FeeSplit[]","components":[{"name":"recipient","type":"address","internalType":"address"},{"name":"share","type":"uint256","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":"PendingSharesToSplitChanged","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"pendingSharesToSplit","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":"BondLockNotExpired","inputs":[]},{"type":"error","name":"FailedToSendEther","inputs":[]},{"type":"error","name":"FeeSplitsChangeWithUndistributedRewards","inputs":[]},{"type":"error","name":"InvalidBondCurveId","inputs":[]},{"type":"error","name":"InvalidBondCurveLength","inputs":[]},{"type":"error","name":"InvalidBondCurveValues","inputs":[]},{"type":"error","name":"InvalidBondLockAmount","inputs":[]},{"type":"error","name":"InvalidBondLockNonce","inputs":[]},{"type":"error","name":"InvalidBondLockPeriod","inputs":[]},{"type":"error","name":"InvalidChargePenaltyRecipientAddress","inputs":[]},{"type":"error","name":"InvalidInitialization","inputs":[]},{"type":"error","name":"InvalidInitializationCurveId","inputs":[]},{"type":"error","name":"InvalidSplitRecipient","inputs":[]},{"type":"error","name":"NoBondLocked","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":"PendingSharesExist","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":"SameAddress","inputs":[]},{"type":"error","name":"SameBondCurveId","inputs":[]},{"type":"error","name":"SenderIsNotEligible","inputs":[]},{"type":"error","name":"SenderIsNotModule","inputs":[]},{"type":"error","name":"TooManySplitShares","inputs":[]},{"type":"error","name":"TooManySplits","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":[]},{"type":"error","name":"ZeroSplitRecipient","inputs":[]},{"type":"error","name":"ZeroSplitShare","inputs":[]}] diff --git a/interfaces/CSParametersRegistry.json b/interfaces/ParametersRegistry.json similarity index 100% rename from interfaces/CSParametersRegistry.json rename to interfaces/ParametersRegistry.json diff --git a/interfaces/PermissionlessGate.json b/interfaces/PermissionlessGate.json new file mode 100644 index 00000000..342c7b2b --- /dev/null +++ b/interfaces/PermissionlessGate.json @@ -0,0 +1 @@ +[{"type":"constructor","inputs":[{"name":"module","type":"address","internalType":"address"},{"name":"admin","type":"address","internalType":"address"}],"stateMutability":"nonpayable"},{"type":"function","name":"CURVE_ID","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"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 IBaseModule"}],"stateMutability":"view"},{"type":"function","name":"RECOVERER_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":"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 IAccounting.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 IAccounting.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":"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":"getRoleMembers","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"address[]","internalType":"address[]"}],"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":"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":"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":"ZeroAdminAddress","inputs":[]},{"type":"error","name":"ZeroModuleAddress","inputs":[]}] diff --git a/interfaces/ReportWithdrawalsForSlashedValidators.json b/interfaces/ReportWithdrawalsForSlashedValidators.json new file mode 100644 index 00000000..71135357 --- /dev/null +++ b/interfaces/ReportWithdrawalsForSlashedValidators.json @@ -0,0 +1 @@ +[{"inputs":[{"internalType":"address","name":"_trustedCaller","type":"address"},{"internalType":"string","name":"_name","type":"string"},{"internalType":"address","name":"_module","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"_creator","type":"address"},{"internalType":"bytes","name":"_evmScriptCallData","type":"bytes"}],"name":"createEVMScript","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_evmScriptCallData","type":"bytes"}],"name":"decodeEVMScriptCallData","outputs":[{"components":[{"internalType":"uint256","name":"nodeOperatorId","type":"uint256"},{"internalType":"uint256","name":"keyIndex","type":"uint256"},{"internalType":"uint256","name":"exitBalance","type":"uint256"},{"internalType":"uint256","name":"slashingPenalty","type":"uint256"},{"internalType":"bool","name":"isSlashed","type":"bool"}],"internalType":"struct WithdrawnValidatorInfo[]","name":"","type":"tuple[]"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"module","outputs":[{"internalType":"contract IBaseModule","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"trustedCaller","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}] diff --git a/interfaces/SetMerkleGateTree.json b/interfaces/SetMerkleGateTree.json new file mode 100644 index 00000000..96fdc76f --- /dev/null +++ b/interfaces/SetMerkleGateTree.json @@ -0,0 +1 @@ +[{"inputs":[{"internalType":"address","name":"_trustedCaller","type":"address"},{"internalType":"string","name":"_name","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"_creator","type":"address"},{"internalType":"bytes","name":"_evmScriptCallData","type":"bytes"}],"name":"createEVMScript","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_evmScriptCallData","type":"bytes"}],"name":"decodeEVMScriptCallData","outputs":[{"internalType":"address","name":"gate","type":"address"},{"internalType":"bytes32","name":"currentTreeRoot","type":"bytes32"},{"internalType":"string","name":"currentTreeCid","type":"string"},{"internalType":"bytes32","name":"newTreeRoot","type":"bytes32"},{"internalType":"string","name":"newTreeCid","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"trustedCaller","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"gate","type":"address"},{"internalType":"bytes32","name":"currentTreeRoot","type":"bytes32"},{"internalType":"string","name":"currentTreeCid","type":"string"},{"internalType":"bytes32","name":"newTreeRoot","type":"bytes32"},{"internalType":"string","name":"newTreeCid","type":"string"}],"name":"validateInputData","outputs":[],"stateMutability":"view","type":"function"}] diff --git a/interfaces/SettleGeneralDelayedPenalty.json b/interfaces/SettleGeneralDelayedPenalty.json new file mode 100644 index 00000000..f7686585 --- /dev/null +++ b/interfaces/SettleGeneralDelayedPenalty.json @@ -0,0 +1 @@ +[{"inputs":[{"internalType":"address","name":"_trustedCaller","type":"address"},{"internalType":"string","name":"_name","type":"string"},{"internalType":"address","name":"_module","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"accounting","outputs":[{"internalType":"contract IAccounting","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_creator","type":"address"},{"internalType":"bytes","name":"_evmScriptCallData","type":"bytes"}],"name":"createEVMScript","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_evmScriptCallData","type":"bytes"}],"name":"decodeEVMScriptCallData","outputs":[{"components":[{"internalType":"uint256","name":"nodeOperatorId","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"internalType":"struct SettleGeneralDelayedPenalty.LockInfo[]","name":"","type":"tuple[]"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"module","outputs":[{"internalType":"contract IBaseModule","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"trustedCaller","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}] diff --git a/interfaces/UpdateStakingModuleShareLimits.json b/interfaces/UpdateStakingModuleShareLimits.json new file mode 100644 index 00000000..4a52c132 --- /dev/null +++ b/interfaces/UpdateStakingModuleShareLimits.json @@ -0,0 +1 @@ +[{"inputs":[{"internalType":"address","name":"_trustedCaller","type":"address"},{"internalType":"string","name":"_name","type":"string"},{"internalType":"address","name":"_stakingRouter","type":"address"},{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"uint16","name":"_maxStakeShareLimitIncrease","type":"uint16"},{"internalType":"uint16","name":"_maxStakeShareLimitDecrease","type":"uint16"},{"internalType":"uint16","name":"_maxPriorityExitShareThresholdIncrease","type":"uint16"},{"internalType":"uint16","name":"_maxPriorityExitShareThresholdDecrease","type":"uint16"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"_creator","type":"address"},{"internalType":"bytes","name":"_evmScriptCallData","type":"bytes"}],"name":"createEVMScript","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_evmScriptCallData","type":"bytes"}],"name":"decodeEVMScriptCallData","outputs":[{"components":[{"internalType":"uint16","name":"currentStakeShareLimit","type":"uint16"},{"internalType":"uint16","name":"newStakeShareLimit","type":"uint16"},{"internalType":"uint16","name":"currentPriorityExitShareThreshold","type":"uint16"},{"internalType":"uint16","name":"newPriorityExitShareThreshold","type":"uint16"}],"internalType":"struct IUpdateStakingModuleShareLimits.ModuleShareParams","name":"","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"maxPriorityExitShareThresholdDecrease","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxPriorityExitShareThresholdIncrease","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxStakeShareLimitDecrease","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxStakeShareLimitIncrease","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakingModuleId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakingRouter","outputs":[{"internalType":"contract IStakingRouter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"trustedCaller","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint16","name":"currentStakeShareLimit","type":"uint16"},{"internalType":"uint16","name":"newStakeShareLimit","type":"uint16"},{"internalType":"uint16","name":"currentPriorityExitShareThreshold","type":"uint16"},{"internalType":"uint16","name":"newPriorityExitShareThreshold","type":"uint16"}],"internalType":"struct IUpdateStakingModuleShareLimits.ModuleShareParams","name":"params","type":"tuple"}],"name":"validateParams","outputs":[],"stateMutability":"view","type":"function"}] diff --git a/interfaces/ValidatorStrikes.json b/interfaces/ValidatorStrikes.json new file mode 100644 index 00000000..f705ad48 --- /dev/null +++ b/interfaces/ValidatorStrikes.json @@ -0,0 +1 @@ +[{"type":"constructor","inputs":[{"name":"module","type":"address","internalType":"address"},{"name":"oracle","type":"address","internalType":"address"}],"stateMutability":"nonpayable"},{"type":"function","name":"ACCOUNTING","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IAccounting"}],"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 IExitPenalties"}],"stateMutability":"view"},{"type":"function","name":"MODULE","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IBaseModule"}],"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 IParametersRegistry"}],"stateMutability":"view"},{"type":"function","name":"ejector","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IEjector"}],"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":"getRoleMembers","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"address[]","internalType":"address[]"}],"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 IValidatorStrikes.KeyStrikes","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 IValidatorStrikes.KeyStrikes[]","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":"payable"},{"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 IValidatorStrikes.KeyStrikes[]","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":"EmptyKeyStrikesList","inputs":[]},{"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":"SameEjectorAddress","inputs":[]},{"type":"error","name":"SenderIsNotOracle","inputs":[]},{"type":"error","name":"ValueNotEvenlyDivisible","inputs":[]},{"type":"error","name":"ZeroAdminAddress","inputs":[]},{"type":"error","name":"ZeroEjectorAddress","inputs":[]},{"type":"error","name":"ZeroModuleAddress","inputs":[]},{"type":"error","name":"ZeroMsgValue","inputs":[]},{"type":"error","name":"ZeroOracleAddress","inputs":[]}] diff --git a/interfaces/Verifier.json b/interfaces/Verifier.json new file mode 100644 index 00000000..92c1b189 --- /dev/null +++ b/interfaces/Verifier.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 IVerifier.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":"gIFirstBalanceNodePrev","type":"bytes32","internalType":"GIndex"},{"name":"gIFirstBalanceNodeCurr","type":"bytes32","internalType":"GIndex"}]},{"name":"firstSupportedSlot","type":"uint64","internalType":"Slot"},{"name":"pivotSlot","type":"uint64","internalType":"Slot"},{"name":"capellaSlot","type":"uint64","internalType":"Slot"},{"name":"minWithdrawalRatio","type":"uint256","internalType":"uint256"},{"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_BALANCES_NODE_CURR","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"GIndex"}],"stateMutability":"view"},{"type":"function","name":"GI_FIRST_BALANCES_NODE_PREV","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"GIndex"}],"stateMutability":"view"},{"type":"function","name":"GI_FIRST_BLOCK_ROOT_IN_SUMMARY","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":"MIN_WITHDRAWAL_RATIO","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"MODULE","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IBaseModule"}],"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":"getRoleMembers","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"address[]","internalType":"address[]"}],"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":"processBalanceProof","inputs":[{"name":"data","type":"tuple","internalType":"struct IVerifier.ProcessBalanceProofInput","components":[{"name":"recentBlock","type":"tuple","internalType":"struct IVerifier.RecentHeaderWitness","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":"validator","type":"tuple","internalType":"struct IVerifier.ValidatorWitness","components":[{"name":"index","type":"uint64","internalType":"uint64"},{"name":"nodeOperatorId","type":"uint32","internalType":"uint32"},{"name":"keyIndex","type":"uint32","internalType":"uint32"},{"name":"object","type":"tuple","internalType":"struct Validator","components":[{"name":"pubkey","type":"bytes","internalType":"bytes"},{"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":"proof","type":"bytes32[]","internalType":"bytes32[]"}]},{"name":"balance","type":"tuple","internalType":"struct IVerifier.BalanceWitness","components":[{"name":"node","type":"bytes32","internalType":"bytes32"},{"name":"proof","type":"bytes32[]","internalType":"bytes32[]"}]}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"processHistoricalBalanceProof","inputs":[{"name":"data","type":"tuple","internalType":"struct IVerifier.ProcessHistoricalBalanceProofInput","components":[{"name":"recentBlock","type":"tuple","internalType":"struct IVerifier.RecentHeaderWitness","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":"historicalBlock","type":"tuple","internalType":"struct IVerifier.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":"validator","type":"tuple","internalType":"struct IVerifier.ValidatorWitness","components":[{"name":"index","type":"uint64","internalType":"uint64"},{"name":"nodeOperatorId","type":"uint32","internalType":"uint32"},{"name":"keyIndex","type":"uint32","internalType":"uint32"},{"name":"object","type":"tuple","internalType":"struct Validator","components":[{"name":"pubkey","type":"bytes","internalType":"bytes"},{"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":"proof","type":"bytes32[]","internalType":"bytes32[]"}]},{"name":"balance","type":"tuple","internalType":"struct IVerifier.BalanceWitness","components":[{"name":"node","type":"bytes32","internalType":"bytes32"},{"name":"proof","type":"bytes32[]","internalType":"bytes32[]"}]}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"processHistoricalWithdrawalProof","inputs":[{"name":"data","type":"tuple","internalType":"struct IVerifier.ProcessHistoricalWithdrawalInput","components":[{"name":"withdrawal","type":"tuple","internalType":"struct IVerifier.WithdrawalWitness","components":[{"name":"offset","type":"uint8","internalType":"uint8"},{"name":"object","type":"tuple","internalType":"struct Withdrawal","components":[{"name":"index","type":"uint64","internalType":"uint64"},{"name":"validatorIndex","type":"uint64","internalType":"uint64"},{"name":"withdrawalAddress","type":"address","internalType":"address"},{"name":"amount","type":"uint64","internalType":"uint64"}]},{"name":"proof","type":"bytes32[]","internalType":"bytes32[]"}]},{"name":"validator","type":"tuple","internalType":"struct IVerifier.ValidatorWitness","components":[{"name":"index","type":"uint64","internalType":"uint64"},{"name":"nodeOperatorId","type":"uint32","internalType":"uint32"},{"name":"keyIndex","type":"uint32","internalType":"uint32"},{"name":"object","type":"tuple","internalType":"struct Validator","components":[{"name":"pubkey","type":"bytes","internalType":"bytes"},{"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":"proof","type":"bytes32[]","internalType":"bytes32[]"}]},{"name":"recentBlock","type":"tuple","internalType":"struct IVerifier.RecentHeaderWitness","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":"withdrawalBlock","type":"tuple","internalType":"struct IVerifier.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[]"}]}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"processSlashedProof","inputs":[{"name":"data","type":"tuple","internalType":"struct IVerifier.ProcessSlashedInput","components":[{"name":"validator","type":"tuple","internalType":"struct IVerifier.ValidatorWitness","components":[{"name":"index","type":"uint64","internalType":"uint64"},{"name":"nodeOperatorId","type":"uint32","internalType":"uint32"},{"name":"keyIndex","type":"uint32","internalType":"uint32"},{"name":"object","type":"tuple","internalType":"struct Validator","components":[{"name":"pubkey","type":"bytes","internalType":"bytes"},{"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":"proof","type":"bytes32[]","internalType":"bytes32[]"}]},{"name":"recentBlock","type":"tuple","internalType":"struct IVerifier.RecentHeaderWitness","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"}]}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"processWithdrawalProof","inputs":[{"name":"data","type":"tuple","internalType":"struct IVerifier.ProcessWithdrawalInput","components":[{"name":"withdrawal","type":"tuple","internalType":"struct IVerifier.WithdrawalWitness","components":[{"name":"offset","type":"uint8","internalType":"uint8"},{"name":"object","type":"tuple","internalType":"struct Withdrawal","components":[{"name":"index","type":"uint64","internalType":"uint64"},{"name":"validatorIndex","type":"uint64","internalType":"uint64"},{"name":"withdrawalAddress","type":"address","internalType":"address"},{"name":"amount","type":"uint64","internalType":"uint64"}]},{"name":"proof","type":"bytes32[]","internalType":"bytes32[]"}]},{"name":"validator","type":"tuple","internalType":"struct IVerifier.ValidatorWitness","components":[{"name":"index","type":"uint64","internalType":"uint64"},{"name":"nodeOperatorId","type":"uint32","internalType":"uint32"},{"name":"keyIndex","type":"uint32","internalType":"uint32"},{"name":"object","type":"tuple","internalType":"struct Validator","components":[{"name":"pubkey","type":"bytes","internalType":"bytes"},{"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":"proof","type":"bytes32[]","internalType":"bytes32[]"}]},{"name":"withdrawalBlock","type":"tuple","internalType":"struct IVerifier.RecentHeaderWitness","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"}]}]}],"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":"HistoricalSummaryDoesNotExist","inputs":[]},{"type":"error","name":"IndexOutOfRange","inputs":[]},{"type":"error","name":"InvalidBlockHeader","inputs":[]},{"type":"error","name":"InvalidCapellaSlot","inputs":[]},{"type":"error","name":"InvalidChainConfig","inputs":[]},{"type":"error","name":"InvalidMinWithdrawalRatio","inputs":[]},{"type":"error","name":"InvalidPivotSlot","inputs":[]},{"type":"error","name":"InvalidPublicKey","inputs":[]},{"type":"error","name":"InvalidValidatorIndex","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":"ValidatorIsNotSlashed","inputs":[]},{"type":"error","name":"ValidatorIsNotWithdrawable","inputs":[]},{"type":"error","name":"ValidatorIsSlashed","inputs":[]},{"type":"error","name":"ValidatorIsWithdrawable","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/VettedGate.json b/interfaces/VettedGate.json new file mode 100644 index 00000000..a5cc9cd8 --- /dev/null +++ b/interfaces/VettedGate.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 IAccounting"}],"stateMutability":"view"},{"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 IBaseModule"}],"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_TREE_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 IAccounting.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 IAccounting.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":"curveId","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":"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":"getRoleMembers","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"address[]","internalType":"address[]"}],"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":"name","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":"name","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"type":"function","name":"pauseFor","inputs":[{"name":"duration","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":"setName","inputs":[{"name":"name","type":"string","internalType":"string"}],"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":"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":"NameSet","inputs":[{"name":"name","type":"string","indexed":false,"internalType":"string"}],"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":"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":"InvalidName","inputs":[]},{"type":"error","name":"InvalidProof","inputs":[]},{"type":"error","name":"InvalidTreeCid","inputs":[]},{"type":"error","name":"InvalidTreeRoot","inputs":[]},{"type":"error","name":"NodeOperatorDoesNotExist","inputs":[]},{"type":"error","name":"NotAllowedToClaim","inputs":[]},{"type":"error","name":"NotInitializing","inputs":[]},{"type":"error","name":"PauseUntilMustBeInFuture","inputs":[]},{"type":"error","name":"PausedExpected","inputs":[]},{"type":"error","name":"ResumedExpected","inputs":[]},{"type":"error","name":"ZeroAdminAddress","inputs":[]},{"type":"error","name":"ZeroModuleAddress","inputs":[]},{"type":"error","name":"ZeroPauseDuration","inputs":[]}] diff --git a/tests/acceptance/test_csm.py b/tests/acceptance/test_csm.py deleted file mode 100644 index e7cc2e78..00000000 --- a/tests/acceptance/test_csm.py +++ /dev/null @@ -1,280 +0,0 @@ -import pytest - -from brownie import interface, web3, Wei, reverts # type: ignore -from brownie.convert.datatypes import HexString - -from utils.config import ( - contracts, - ContractsLazyLoader, - LIDO_LOCATOR, - LIDO, - WITHDRAWAL_QUEUE, - WITHDRAWAL_VAULT, - WSTETH_TOKEN, - AGENT, - BURNER, - CSM_ADDRESS, - CS_ACCOUNTING_ADDRESS, - CS_FEE_DISTRIBUTOR_ADDRESS, - CS_FEE_ORACLE_ADDRESS, - CS_ORACLE_HASH_CONSENSUS_ADDRESS, - CHAIN_SECONDS_PER_SLOT, - CHAIN_GENESIS_TIME, - CHAIN_SLOTS_PER_EPOCH, - CS_ORACLE_EPOCHS_PER_FRAME, - ORACLE_QUORUM, - ORACLE_COMMITTEE, - CS_PARAMS_REGISTRY_ADDRESS, - CS_EXIT_PENALTIES_ADDRESS, - CS_STRIKES_ADDRESS, - CS_EJECTOR_ADDRESS, - CS_FEE_ORACLE_CONSENSUS_VERSION, -) -from utils.evm_script import encode_error - -contracts: ContractsLazyLoader = contracts - - -def _str_to_bytes32(s: str) -> str: - return "0x{:0<64}".format(s.encode("utf-8").hex()) - - -@pytest.fixture(scope="module") -def csm(): - return contracts.csm - - -@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, -): - 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 not csm.isPaused() - - -class TestAccounting: - def test_initial_state(self, accounting): - 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.FEE_DISTRIBUTOR() == CS_FEE_DISTRIBUTOR_ADDRESS - assert accounting.chargePenaltyRecipient() == AGENT - assert not accounting.isPaused() - - def test_allowances(self, lido): - uin256_max = 2**256 - 1 - assert lido.allowance(CS_ACCOUNTING_ADDRESS, WSTETH_TOKEN) == uin256_max - 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: - 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() == 3 # SRv3: finalizeUpgradeV3 -> INITIALIZED_VERSION - assert fee_oracle.getConsensusContract() == CS_ORACLE_HASH_CONSENSUS_ADDRESS - assert fee_oracle.getConsensusVersion() == CS_FEE_ORACLE_CONSENSUS_VERSION - assert not fee_oracle.isPaused() - - def test_finalize_upgrade_v3_reverts_when_already_finalized(self, fee_oracle): - # The vote already ran finalizeUpgradeV3, so the FeeOracle is at contract version 3. - # finalizeUpgradeV3 has no reinitializer/access-control guard; re-calling it must - # revert because _updateContractVersion(INITIALIZED_VERSION=3) rejects a bump when - # already at 3. Pass a different consensus version so we reach the contract-version - # check (the same version would revert earlier in _setConsensusVersion with - # VersionCannotBeSame). State rolls back on revert. - # .call() — anvil does not surface custom-error data for reverted txs. - with reverts(encode_error("InvalidContractVersionIncrement()")): - fee_oracle.finalizeUpgradeV3.call(CS_FEE_ORACLE_CONSENSUS_VERSION + 1, {"from": contracts.agent}) - - -class TestHashConsensus: - def test_initial_state(self, hash_consensus): - chain_config = hash_consensus.getChainConfig() - assert chain_config["slotsPerEpoch"] == CHAIN_SLOTS_PER_EPOCH - assert chain_config["secondsPerSlot"] == CHAIN_SECONDS_PER_SLOT - assert chain_config["genesisTime"] == CHAIN_GENESIS_TIME - - frame_config = hash_consensus.getFrameConfig() - assert frame_config["initialEpoch"] == 434490 - assert frame_config["epochsPerFrame"] == CS_ORACLE_EPOCHS_PER_FRAME - assert frame_config["fastLaneLengthSlots"] == 300 - - assert hash_consensus.getQuorum() == ORACLE_QUORUM - - assert hash_consensus.getInitialRefSlot() == 13903679 - - 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 - # v3: the immutable STAKING_MODULE_ID() getter is gone. stakingModuleId is now a mutable - # storage slot lazily filled from StakingRouter on the first ejection (_getOrCacheStakingModuleId), - # so right after enactment it is still 0 (will resolve to CS_MODULE_ID == 3 on first use). - assert ejector.stakingModuleId() == 0 - - -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 - # v3: QUEUE_LEGACY_PRIORITY was removed (chore: remove legacy code). Queue priority is now - # per-curve via defaultQueueConfig (priority, maxDeposits). - priority, _max_deposits = parameters_registry.defaultQueueConfig() - assert priority <= parameters_registry.QUEUE_LOWEST_PRIORITY() - - -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" - ) - assert verifier.GI_FIRST_WITHDRAWAL_CURR() == HexString( - "0x000000000000000000000000000000000000000000000000000000000161c004", "bytes" - ) - assert verifier.GI_FIRST_VALIDATOR_PREV() == HexString( - "0x0000000000000000000000000000000000000000000000000096000000000028", "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 diff --git a/tests/conftest.py b/tests/conftest.py index 5c028e96..a3b7bd2f 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -270,8 +270,8 @@ def preregister_unparseable_contracts(): # `eth-brownie` pins `py-solc-ast==1.2.10` (its latest release), which crashes on the # contract-level function-list directive `using {func} for Type;` (valid since Solidity # 0.8.13) with `AttributeError: 'UsingForDirective' object has no attribute 'libraryName'`. - # CSVerifierV2's verified source has one (`using { amountWei } for Withdrawal;` inside - # `contract CSVerifier`), so resolving it from Etherscan during event tracing + # CSVerifier's verified source has one (`using { amountWei } for Withdrawal;` inside + # `contract CSVerifier`), so resolving v2/v3 from Etherscan during event tracing # (e.g. display_dg_events) crashes. Pre-registering it from a local ABI makes # state._find_contract short-circuit before the Etherscan source fetch / solcast parse. # @@ -279,6 +279,7 @@ def preregister_unparseable_contracts(): # where PARSE_EVENTS_FROM_LOCAL_ABI is not set. unparseable_contracts = { "CSVerifierV2": globals().get("CS_VERIFIER_V2_ADDRESS"), + "Verifier": globals().get("CS_VERIFIER_V3_ADDRESS"), } for contract_name, addr in unparseable_contracts.items(): if not addr: diff --git a/tests/regression/test_easy_track_factories.py b/tests/regression/test_easy_track_factories.py index a8fc90ed..1928738c 100644 --- a/tests/regression/test_easy_track_factories.py +++ b/tests/regression/test_easy_track_factories.py @@ -2,13 +2,14 @@ from dataclasses import dataclass from typing import List, Dict -import eth_abi -from brownie import interface, accounts, Wei, web3 +import pytest +from brownie import interface, accounts, web3 from brownie.exceptions import VirtualMachineError from eth_typing import HexStr from eth_abi.abi import encode from configs.config_mainnet import * +from utils.balance import set_balance from utils.config import contracts, EASYTRACK_SIMPLE_DVT_TRUSTED_CALLER from utils.test.easy_track_helpers import _encode_calldata, create_and_enact_motion from utils.test.keys_helpers import random_pubkeys_batch, random_signatures_batch @@ -30,6 +31,22 @@ for i in range(1, 11) ] +CSM_FACTORY_NAME = "CSM" +CM_FACTORY_NAME = "CM" +CSM_MERKLE_GATE_ADDRESSES = [ + CS_VETTED_GATE_ADDRESS, + CS_IDENTIFIED_DVT_CLUSTER_GATE_ADDRESS, +] +CM_MERKLE_GATE_ADDRESSES = [ + CM_PROFESSIONAL_OPERATOR_GATE_ADDRESS, + "0x8c002c6eE10cf8adb78D1F9EB2e134FdaF8A7C1a", + "0x207798e6fD1aa7Ee8a63782A64c959cD6727b78C", + "0xeF273Ca4A21Ba7B414Ae3C9f9b443038cb133F72", + "0x3BbBb175f7F07954DE00052b20E1c5572223F24D", + "0x86A8d4E0db5938D21d98047544668FCCB1A9ADc8", + "0x773933F9db8964A17d62fb808f2EC7A2de4247CC", +] + def add_node_operators(operators, stranger): calldata = _encode_calldata( @@ -658,3 +675,247 @@ def test_sdvt_reverts_on_unused_key(stranger): assert False, "Expected UNUSED_PUBKEY revert" except VirtualMachineError as error: assert "UNUSED_PUBKEY" in error.message + + +def _permissions_include(factory_address, target_address, method): + return _permission_call(target_address, method) in _permission_entries(factory_address) + + +def _permission_entries(factory_address): + permissions = bytes(contracts.easy_track.evmScriptFactoryPermissions(factory_address)) + assert len(permissions) % 24 == 0 + entries = [permissions[i : i + 24] for i in range(0, len(permissions), 24)] + assert len(entries) == len(set(entries)) + return set(entries) + + +def _permission_call(target_address, method): + return bytes.fromhex(str(target_address)[2:]) + bytes.fromhex(method.signature[2:]) + + +def _bytes32_hex(value): + if isinstance(value, (bytes, bytearray)): + return "0x" + bytes(value).hex() + return str(value).lower() + + +def _set_merkle_gate_tree_calldata(gate): + current_root = gate.treeRoot() + current_cid = gate.treeCid() + new_root = web3.keccak(text=f"scripts-regression-{gate.address}") + new_cid = f"ipfs://scripts-regression-{gate.address[-8:]}" + if _bytes32_hex(new_root) == _bytes32_hex(current_root): + new_root = web3.keccak(text=f"scripts-regression-{gate.address}-next") + if new_cid == current_cid: + new_cid = f"{new_cid}-next" + + calldata = _encode_calldata( + ["address", "bytes32", "string", "bytes32", "string"], + [gate.address, current_root, current_cid, new_root, new_cid], + ) + return calldata, _bytes32_hex(new_root), new_cid + + +@pytest.mark.parametrize( + "factory_address,allowed_gate_addresses", + [ + (EASYTRACK_CSM_SET_MERKLE_GATE_TREE_FACTORY, CSM_MERKLE_GATE_ADDRESSES), + (EASYTRACK_CM_SET_MERKLE_GATE_TREE_FACTORY, CM_MERKLE_GATE_ADDRESSES), + ], +) +def test_set_merkle_gate_tree_factory_permissions(factory_address, allowed_gate_addresses): + factory = interface.SetMerkleGateTree(factory_address) + expected_permissions = {_permission_call(factory.address, factory.validateInputData)} + + for gate_address in allowed_gate_addresses: + gate = interface.MerkleGate(gate_address) + expected_permissions.add(_permission_call(gate.address, gate.setTreeParams)) + + assert _permission_entries(factory.address) == expected_permissions + + +@pytest.mark.parametrize( + "factory_address,wrong_gate_address", + [ + (EASYTRACK_CM_SET_MERKLE_GATE_TREE_FACTORY, CS_VETTED_GATE_ADDRESS), + (EASYTRACK_CSM_SET_MERKLE_GATE_TREE_FACTORY, CM_PROFESSIONAL_OPERATOR_GATE_ADDRESS), + ], +) +def test_set_merkle_gate_tree_factory_reverts_for_other_module_gate(factory_address, wrong_gate_address): + factory = interface.SetMerkleGateTree(factory_address) + wrong_gate = interface.MerkleGate(wrong_gate_address) + calldata, _, _ = _set_merkle_gate_tree_calldata(wrong_gate) + + try: + contracts.easy_track.createMotion( + factory, + calldata, + {"from": set_balance(factory.trustedCaller(), 100000)}, + ) + assert False, "Expected HAS_NO_PERMISSIONS revert" + except VirtualMachineError as error: + assert "HAS_NO_PERMISSIONS" in error.message + + +@pytest.mark.parametrize( + "factory_address,expected_name,gate_address", + [ + ( + EASYTRACK_CSM_SET_MERKLE_GATE_TREE_FACTORY, + CSM_FACTORY_NAME, + CS_VETTED_GATE_ADDRESS, + ), + ( + EASYTRACK_CM_SET_MERKLE_GATE_TREE_FACTORY, + CM_FACTORY_NAME, + CM_PROFESSIONAL_OPERATOR_GATE_ADDRESS, + ), + ], +) +def test_set_merkle_gate_tree_factories(factory_address, expected_name, gate_address, stranger): + factory = interface.SetMerkleGateTree(factory_address) + gate = interface.MerkleGate(gate_address) + assert factory.name() == expected_name + calldata, new_root, new_cid = _set_merkle_gate_tree_calldata(gate) + + create_and_enact_motion( + contracts.easy_track, + set_balance(factory.trustedCaller(), 100000), + factory, + calldata, + stranger, + ) + + assert _bytes32_hex(gate.treeRoot()) == new_root + assert gate.treeCid() == new_cid + + +def test_csm_report_withdrawals_for_slashed_validators_factory(): + factory = interface.ReportWithdrawalsForSlashedValidators( + EASYTRACK_CSM_REPORT_WITHDRAWALS_FOR_SLASHED_VALIDATORS_FACTORY + ) + module = interface.BaseModule(CSM_ADDRESS) + + assert factory.module() == module.address + assert factory.name() == CSM_FACTORY_NAME + assert _permissions_include(factory.address, module.address, module.reportSlashedWithdrawnValidators) + + calldata = _encode_calldata(["(uint256,uint256,uint256,uint256,bool)[]"], [[]]) + try: + factory.createEVMScript(factory.trustedCaller(), calldata) + assert False, "Expected EMPTY_VALIDATOR_INFO_LIST revert" + except VirtualMachineError as error: + assert "EMPTY_VALIDATOR_INFO_LIST" in error.message + + +def test_cm_report_withdrawals_for_slashed_validators_factory(): + factory = interface.ReportWithdrawalsForSlashedValidators( + EASYTRACK_CM_REPORT_WITHDRAWALS_FOR_SLASHED_VALIDATORS_FACTORY + ) + module = interface.BaseModule(CM_MODULE_ADDRESS) + + assert factory.module() == module.address + assert factory.name() == CM_FACTORY_NAME + assert _permissions_include(factory.address, module.address, module.reportSlashedWithdrawnValidators) + + calldata = _encode_calldata(["(uint256,uint256,uint256,uint256,bool)[]"], [[]]) + try: + factory.createEVMScript(factory.trustedCaller(), calldata) + assert False, "Expected EMPTY_VALIDATOR_INFO_LIST revert" + except VirtualMachineError as error: + assert "EMPTY_VALIDATOR_INFO_LIST" in error.message + + +def test_csm_settle_general_delayed_penalty_factory(): + factory = interface.SettleGeneralDelayedPenalty(EASYTRACK_CSM_SETTLE_GENERAL_DELAYED_PENALTY_FACTORY) + module = interface.BaseModule(CSM_ADDRESS) + + assert factory.module() == module.address + assert factory.accounting() == module.ACCOUNTING() + assert factory.name() == CSM_FACTORY_NAME + assert _permissions_include(factory.address, module.address, module.settleGeneralDelayedPenalty) + + calldata = _encode_calldata(["(uint256,uint256)[]"], [[]]) + try: + factory.createEVMScript(factory.trustedCaller(), calldata) + assert False, "Expected EMPTY_LOCK_INFO_LIST revert" + except VirtualMachineError as error: + assert "EMPTY_LOCK_INFO_LIST" in error.message + + +def test_cm_settle_general_delayed_penalty_factory(): + factory = interface.SettleGeneralDelayedPenalty(EASYTRACK_CM_SETTLE_GENERAL_DELAYED_PENALTY_FACTORY) + module = interface.BaseModule(CM_MODULE_ADDRESS) + + assert factory.module() == module.address + assert factory.accounting() == module.ACCOUNTING() + assert factory.name() == CM_FACTORY_NAME + assert _permissions_include(factory.address, module.address, module.settleGeneralDelayedPenalty) + + calldata = _encode_calldata(["(uint256,uint256)[]"], [[]]) + try: + factory.createEVMScript(factory.trustedCaller(), calldata) + assert False, "Expected EMPTY_LOCK_INFO_LIST revert" + except VirtualMachineError as error: + assert "EMPTY_LOCK_INFO_LIST" in error.message + + +def test_cm_create_or_update_operator_group_factory(): + module = interface.CuratedModule(CM_MODULE_ADDRESS) + meta_registry = interface.MetaRegistry(module.META_REGISTRY()) + factory = interface.CreateOrUpdateOperatorGroup(EASYTRACK_CM_CREATE_OR_UPDATE_OPERATOR_GROUP_FACTORY) + assert factory.module() == module.address + assert factory.metaRegistry() == meta_registry.address + assert factory.name() == CM_FACTORY_NAME + assert factory.allowedExternalModuleId() == CURATED_STAKING_MODULE_ID + assert _permissions_include(factory.address, factory.address, factory.validateInputData) + assert _permissions_include(factory.address, meta_registry.address, meta_registry.createOrUpdateOperatorGroup) + + external_operator_data = factory.encodeNORExtOperatorData(CURATED_STAKING_MODULE_ID, 1) + module_id, node_operator_id = factory.decodeNORExtOperatorData(external_operator_data) + assert module_id == CURATED_STAKING_MODULE_ID + assert node_operator_id == 1 + + +def test_update_staking_module_share_limits_factory(stranger): + factory = interface.UpdateStakingModuleShareLimits(EASYTRACK_UPDATE_STAKING_MODULE_SHARE_LIMITS_FACTORY) + assert factory.stakingRouter() == STAKING_ROUTER + assert factory.stakingModuleId() == CS_MODULE_ID + assert _permissions_include(factory.address, factory.address, factory.validateParams) + assert _permissions_include(factory.address, STAKING_ROUTER, contracts.staking_router.updateModuleShares) + + module_id = factory.stakingModuleId() + module = contracts.staking_router.getStakingModule(module_id) + current_share = module["stakeShareLimit"] + current_priority_exit_threshold = module["priorityExitShareThreshold"] + + new_share = current_share + new_priority_exit_threshold = current_priority_exit_threshold + + if current_share > 0 and factory.maxStakeShareLimitDecrease() > 0: + new_share = current_share - 1 + elif current_share < current_priority_exit_threshold and factory.maxStakeShareLimitIncrease() > 0: + new_share = current_share + 1 + elif current_priority_exit_threshold < 10000 and factory.maxPriorityExitShareThresholdIncrease() > 0: + new_priority_exit_threshold = current_priority_exit_threshold + 1 + elif current_priority_exit_threshold > current_share and factory.maxPriorityExitShareThresholdDecrease() > 0: + new_priority_exit_threshold = current_priority_exit_threshold - 1 + else: + pytest.skip("No safe one-basis-point share-limits update is possible with current factory caps") + + calldata = _encode_calldata( + ["uint16", "uint16", "uint16", "uint16"], + [current_share, new_share, current_priority_exit_threshold, new_priority_exit_threshold], + ) + + create_and_enact_motion( + contracts.easy_track, + set_balance(factory.trustedCaller(), 100000), + factory, + calldata, + stranger, + ) + + module_after = contracts.staking_router.getStakingModule(module_id) + assert module_after["stakeShareLimit"] == new_share + assert module_after["priorityExitShareThreshold"] == new_priority_exit_threshold diff --git a/tests/regression/test_permissions.py b/tests/regression/test_permissions.py index 22c20d24..41f4ba3e 100644 --- a/tests/regression/test_permissions.py +++ b/tests/regression/test_permissions.py @@ -50,8 +50,12 @@ SIMPLE_DVT, CSM_ADDRESS, CS_ACCOUNTING_ADDRESS, + CS_EJECTOR_V3_ADDRESS, CS_GATE_SEAL_V2_ADDRESS, + CS_IDENTIFIED_DVT_CLUSTER_GATE_ADDRESS, + CS_PERMISSIONLESS_GATE_V3_ADDRESS, CS_VERIFIER_V2_ADDRESS, + CS_VERIFIER_V3_ADDRESS, CS_FEE_DISTRIBUTOR_ADDRESS, CS_FEE_ORACLE_ADDRESS, CS_ORACLE_HASH_CONSENSUS_ADDRESS, @@ -62,6 +66,8 @@ CS_PARAMS_REGISTRY_ADDRESS, CS_STRIKES_ADDRESS, CS_EJECTOR_ADDRESS, + CM_ACCOUNTING_ADDRESS, + CM_EJECTOR_ADDRESS, L1_EMERGENCY_BRAKES_MULTISIG, DUAL_GOVERNANCE_EXECUTORS, RESEAL_MANAGER, @@ -81,6 +87,78 @@ @pytest.fixture(scope="function") def protocol_permissions(): + is_csm_v3 = contracts.csm.getInitializedVersion() >= 3 + csm_pause_manager = CIRCUIT_BREAKER + cs_ejector_address = CS_EJECTOR_V3_ADDRESS if is_csm_v3 else CS_EJECTOR_ADDRESS + cs_permissionless_gate_address = ( + CS_PERMISSIONLESS_GATE_V3_ADDRESS if is_csm_v3 else CS_PERMISSIONLESS_GATE_ADDRESS + ) + cs_verifier = ( + interface.Verifier(CS_VERIFIER_V3_ADDRESS) + if is_csm_v3 + else interface.CSVerifierV2(CS_VERIFIER_V2_ADDRESS) + ) + cs_verifier_address = cs_verifier.address + burner_request_burn_my_steth_holders = ( + [contracts.csm.accounting(), CM_ACCOUNTING_ADDRESS] if is_csm_v3 else [] + ) + burner_request_burn_shares_holders = [contracts.accounting] + if not is_csm_v3: + burner_request_burn_shares_holders.append(contracts.csm.accounting()) + csm_create_node_operator_holders = [cs_permissionless_gate_address, CS_VETTED_GATE_ADDRESS] + if is_csm_v3: + csm_create_node_operator_holders.append(CS_IDENTIFIED_DVT_CLUSTER_GATE_ADDRESS) + cs_accounting_set_bond_curve_holders = [CS_VETTED_GATE_ADDRESS, CSM_COMMITTEE_MS] + if is_csm_v3: + cs_accounting_set_bond_curve_holders.append(CS_IDENTIFIED_DVT_CLUSTER_GATE_ADDRESS) + twg_full_withdrawal_request_holders = [VALIDATORS_EXIT_BUS_ORACLE, cs_ejector_address] + if is_csm_v3: + twg_full_withdrawal_request_holders.append(CM_EJECTOR_ADDRESS) + csm_roles = { + "DEFAULT_ADMIN_ROLE": [contracts.agent], + "STAKING_ROUTER_ROLE": [STAKING_ROUTER], + "PAUSE_ROLE": [csm_pause_manager, RESEAL_MANAGER], + "REPORT_EL_REWARDS_STEALING_PENALTY_ROLE": [] if is_csm_v3 else [CSM_COMMITTEE_MS], + "SETTLE_EL_REWARDS_STEALING_PENALTY_ROLE": [] if is_csm_v3 else [EASYTRACK_EVMSCRIPT_EXECUTOR], + "CREATE_NODE_OPERATOR_ROLE": csm_create_node_operator_holders, + "VERIFIER_ROLE": [cs_verifier_address], + "RESUME_ROLE": [RESEAL_MANAGER], + "RECOVERER_ROLE": [], + } + if is_csm_v3: + csm_roles.update({ + "MANAGE_TOP_UP_QUEUE_ROLE": [], + "REWIND_TOP_UP_QUEUE_ROLE": [], + "OPERATOR_ADDRESSES_ADMIN_ROLE": [], + "REPORT_GENERAL_DELAYED_PENALTY_ROLE": [CSM_COMMITTEE_MS], + "SETTLE_GENERAL_DELAYED_PENALTY_ROLE": [EASYTRACK_EVMSCRIPT_EXECUTOR], + "REPORT_REGULAR_WITHDRAWN_VALIDATORS_ROLE": [cs_verifier_address], + "REPORT_SLASHED_WITHDRAWN_VALIDATORS_ROLE": [EASYTRACK_EVMSCRIPT_EXECUTOR], + }) + csm_role_preimages = { + "REPORT_EL_REWARDS_STEALING_PENALTY_ROLE": "REPORT_EL_REWARDS_STEALING_PENALTY_ROLE", + "SETTLE_EL_REWARDS_STEALING_PENALTY_ROLE": "SETTLE_EL_REWARDS_STEALING_PENALTY_ROLE", + } + if is_csm_v3: + csm_role_preimages.update({ + "REPORT_GENERAL_DELAYED_PENALTY_ROLE": "REPORT_GENERAL_DELAYED_PENALTY_ROLE", + "SETTLE_GENERAL_DELAYED_PENALTY_ROLE": "SETTLE_GENERAL_DELAYED_PENALTY_ROLE", + "REPORT_REGULAR_WITHDRAWN_VALIDATORS_ROLE": "REPORT_REGULAR_WITHDRAWN_VALIDATORS_ROLE", + "REPORT_SLASHED_WITHDRAWN_VALIDATORS_ROLE": "REPORT_SLASHED_WITHDRAWN_VALIDATORS_ROLE", + }) + vetted_gate_roles = { + "DEFAULT_ADMIN_ROLE": [contracts.agent], + "PAUSE_ROLE": [csm_pause_manager, RESEAL_MANAGER], + "RESUME_ROLE": [RESEAL_MANAGER], + "RECOVERER_ROLE": [], + "SET_TREE_ROLE": [EASYTRACK_EVMSCRIPT_EXECUTOR], + } + if not is_csm_v3: + vetted_gate_roles.update({ + "START_REFERRAL_SEASON_ROLE": [contracts.agent], + "END_REFERRAL_SEASON_ROLE": [CSM_COMMITTEE_MS], + }) + return { LIDO_LOCATOR: { "contract_name": "LidoLocator", @@ -95,8 +173,8 @@ def protocol_permissions(): "type": "CustomApp", "roles": { "DEFAULT_ADMIN_ROLE": [contracts.agent], - "REQUEST_BURN_MY_STETH_ROLE": [], - "REQUEST_BURN_SHARES_ROLE": [contracts.accounting, contracts.csm.accounting()], + "REQUEST_BURN_MY_STETH_ROLE": burner_request_burn_my_steth_holders, + "REQUEST_BURN_SHARES_ROLE": burner_request_burn_shares_holders, }, }, STAKING_ROUTER: { @@ -343,34 +421,25 @@ def protocol_permissions(): "contract": contracts.csm, "type": "CustomApp", "proxy_owner": contracts.agent, - "roles": { - "DEFAULT_ADMIN_ROLE": [contracts.agent], - "STAKING_ROUTER_ROLE": [STAKING_ROUTER], - "PAUSE_ROLE": [CIRCUIT_BREAKER, RESEAL_MANAGER], - "REPORT_EL_REWARDS_STEALING_PENALTY_ROLE": [CSM_COMMITTEE_MS], - "SETTLE_EL_REWARDS_STEALING_PENALTY_ROLE": [EASYTRACK_EVMSCRIPT_EXECUTOR], - "CREATE_NODE_OPERATOR_ROLE": [CS_PERMISSIONLESS_GATE_ADDRESS, CS_VETTED_GATE_ADDRESS], - "VERIFIER_ROLE": [CS_VERIFIER_V2_ADDRESS], - "RESUME_ROLE": [RESEAL_MANAGER], - "RECOVERER_ROLE": [], - }, + "roles": csm_roles, + "role_preimages": csm_role_preimages, }, CS_ACCOUNTING_ADDRESS: { - "contract_name": "CSAccounting", + "contract_name": "Accounting", "contract": contracts.cs_accounting, "type": "CustomApp", "proxy_owner": contracts.agent, "roles": { "DEFAULT_ADMIN_ROLE": [contracts.agent], - "SET_BOND_CURVE_ROLE": [CS_VETTED_GATE_ADDRESS, CSM_COMMITTEE_MS], - "PAUSE_ROLE": [CIRCUIT_BREAKER, RESEAL_MANAGER], + "SET_BOND_CURVE_ROLE": cs_accounting_set_bond_curve_holders, + "PAUSE_ROLE": [csm_pause_manager, RESEAL_MANAGER], "RESUME_ROLE": [RESEAL_MANAGER], "MANAGE_BOND_CURVES_ROLE": [], "RECOVERER_ROLE": [], }, }, CS_FEE_DISTRIBUTOR_ADDRESS: { - "contract_name": "CSFeeDistributor", + "contract_name": "FeeDistributor", "contract": contracts.cs_fee_distributor, "type": "CustomApp", "proxy_owner": contracts.agent, @@ -380,7 +449,7 @@ def protocol_permissions(): }, }, CS_FEE_ORACLE_ADDRESS: { - "contract_name": "CSFeeOracle", + "contract_name": "FeeOracle", "contract": contracts.cs_fee_oracle, "type": "CustomApp", "proxy_owner": contracts.agent, @@ -388,7 +457,7 @@ def protocol_permissions(): "DEFAULT_ADMIN_ROLE": [contracts.agent], "MANAGE_CONSENSUS_CONTRACT_ROLE": [], "MANAGE_CONSENSUS_VERSION_ROLE": [], - "PAUSE_ROLE": [CIRCUIT_BREAKER, RESEAL_MANAGER], + "PAUSE_ROLE": [csm_pause_manager, RESEAL_MANAGER], "SUBMIT_DATA_ROLE": [], "RESUME_ROLE": [RESEAL_MANAGER], "RECOVERER_ROLE": [], @@ -407,18 +476,18 @@ def protocol_permissions(): "MANAGE_REPORT_PROCESSOR_ROLE": [], }, }, - CS_VERIFIER_V2_ADDRESS: { - "contract_name": "CSVerifier", - "contract": contracts.cs_verifier, + cs_verifier_address: { + "contract_name": "Verifier", + "contract": cs_verifier, "type": "CustomApp", "roles": { "DEFAULT_ADMIN_ROLE": [contracts.agent], - "PAUSE_ROLE": [CIRCUIT_BREAKER, RESEAL_MANAGER], + "PAUSE_ROLE": [csm_pause_manager, RESEAL_MANAGER], "RESUME_ROLE": [RESEAL_MANAGER], } }, CS_PARAMS_REGISTRY_ADDRESS: { - "contract_name": "CSParametersRegistry", + "contract_name": "ParametersRegistry", "contract": contracts.cs_parameters_registry, "type": "CustomApp", "proxy_owner": contracts.agent, @@ -427,7 +496,7 @@ def protocol_permissions(): }, }, CS_STRIKES_ADDRESS: { - "contract_name": "CSStrikes", + "contract_name": "ValidatorStrikes", "contract": contracts.cs_strikes, "type": "CustomApp", "proxy_owner": contracts.agent, @@ -435,13 +504,13 @@ def protocol_permissions(): "DEFAULT_ADMIN_ROLE": [contracts.agent], }, }, - CS_EJECTOR_ADDRESS: { - "contract_name": "CSEjector", - "contract": contracts.cs_ejector, + cs_ejector_address: { + "contract_name": "Ejector", + "contract": interface.Ejector(cs_ejector_address), "type": "CustomApp", "roles": { "DEFAULT_ADMIN_ROLE": [contracts.agent], - "PAUSE_ROLE": [CIRCUIT_BREAKER, RESEAL_MANAGER], + "PAUSE_ROLE": [csm_pause_manager, RESEAL_MANAGER], "RESUME_ROLE": [RESEAL_MANAGER], "RECOVERER_ROLE": [], } @@ -451,33 +520,26 @@ def protocol_permissions(): "contract": contracts.cs_vetted_gate, "type": "CustomApp", "proxy_owner": contracts.agent, - "roles": { - "DEFAULT_ADMIN_ROLE": [contracts.agent], - "PAUSE_ROLE": [CIRCUIT_BREAKER, RESEAL_MANAGER], - "RESUME_ROLE": [RESEAL_MANAGER], - "RECOVERER_ROLE": [], - "SET_TREE_ROLE": [EASYTRACK_EVMSCRIPT_EXECUTOR], - "START_REFERRAL_SEASON_ROLE": [contracts.agent], - "END_REFERRAL_SEASON_ROLE": [CSM_COMMITTEE_MS], - } + "roles": vetted_gate_roles, }, - CS_PERMISSIONLESS_GATE_ADDRESS: { + cs_permissionless_gate_address: { "contract_name": "PermissionlessGate", - "contract": contracts.cs_permissionless_gate, + "contract": interface.PermissionlessGate(cs_permissionless_gate_address), "type": "CustomApp", "roles": { "DEFAULT_ADMIN_ROLE": [contracts.agent], "RECOVERER_ROLE": [], } }, + # TODO: add Curated Module v2 permission matrix once scripts has CMv2 interfaces and config bindings. TRIGGERABLE_WITHDRAWALS_GATEWAY: { "contract_name": "TriggerableWithdrawalsGateway", "contract": contracts.triggerable_withdrawals_gateway, "type": "CustomApp", "roles": { "DEFAULT_ADMIN_ROLE": [contracts.agent], - "ADD_FULL_WITHDRAWAL_REQUEST_ROLE": [VALIDATORS_EXIT_BUS_ORACLE, CS_EJECTOR_ADDRESS], - "PAUSE_ROLE": [CIRCUIT_BREAKER, RESEAL_MANAGER], + "ADD_FULL_WITHDRAWAL_REQUEST_ROLE": twg_full_withdrawal_request_holders, + "PAUSE_ROLE": [csm_pause_manager, RESEAL_MANAGER], "RESUME_ROLE": [RESEAL_MANAGER], "TW_EXIT_LIMIT_MANAGER_ROLE": [], } @@ -604,21 +666,24 @@ def test_protocol_permissions(protocol_permissions): abi_roles_list = [ method for method in permissions_config["contract"].signatures.keys() if method.endswith("_ROLE") ] + abi_roles = set(abi_roles_list) + configured_roles = set(permissions_config["roles"]) + custom_role_preimages = set(permissions_config.get("role_preimages", {})) if contract_address in [NODE_OPERATORS_REGISTRY, SIMPLE_DVT]: abi_roles_list.append("MANAGE_SIGNING_KEYS") + abi_roles.add("MANAGE_SIGNING_KEYS") roles = permissions_config["roles"] - assert len(abi_roles_list) == len( - roles.keys() - ), "Contract {} . number of roles doesn't match. expected {} actual {}".format( - permissions_config["contract_name"], abi_roles_list, roles.keys() + assert abi_roles.issubset(configured_roles), "Contract {} has undescribed ABI roles {}".format( + permissions_config["contract_name"], abi_roles - configured_roles ) - for role in set(permissions_config["roles"].keys()): - assert role in abi_roles_list, "no {} described for contract {}".format( - role, permissions_config["contract_name"] + assert configured_roles.issubset(abi_roles | custom_role_preimages), ( + "Contract {} has configured roles absent from ABI and role_preimages {}".format( + permissions_config["contract_name"], configured_roles - abi_roles - custom_role_preimages ) + ) if permissions_config["type"] == "AragonApp": for role, holders in permissions_config["roles"].items(): @@ -653,8 +718,9 @@ def test_protocol_permissions(protocol_permissions): role_keccak = web3.keccak(text=role_preimage).hex() if role != "DEFAULT_ADMIN_ROLE" else ZERO_BYTES32.hex() - role_signature = permissions_config["contract"].signatures[role] - assert permissions_config["contract"].get_method_object(role_signature)() == role_keccak + if role in permissions_config["contract"].signatures: + role_signature = permissions_config["contract"].signatures[role] + assert permissions_config["contract"].get_method_object(role_signature)() == role_keccak try: role_member_count = permissions_config["contract"].getRoleMemberCount(role_keccak) diff --git a/utils/config.py b/utils/config.py index 9c004697..6ec07161 100644 --- a/utils/config.py +++ b/utils/config.py @@ -211,48 +211,50 @@ def csm(self) -> interface.CSModule: return interface.CSModule(CSM_ADDRESS) @property - def cs_permissionless_gate(self) -> interface.CSPermissionlessGate: - return interface.CSPermissionlessGate(CS_PERMISSIONLESS_GATE_ADDRESS) + def cs_permissionless_gate(self) -> interface.PermissionlessGate: + return interface.PermissionlessGate(CS_PERMISSIONLESS_GATE_ADDRESS) @property - def cs_vetted_gate(self) -> interface.CSVettedGate: - return interface.CSVettedGate(CS_VETTED_GATE_ADDRESS) + def cs_vetted_gate(self) -> interface.VettedGate: + return interface.VettedGate(CS_VETTED_GATE_ADDRESS) @property - def cs_accounting(self) -> interface.CSAccounting: - return interface.CSAccounting(CS_ACCOUNTING_ADDRESS) + def cs_accounting(self) -> interface.ModuleAccounting: + return interface.ModuleAccounting(CS_ACCOUNTING_ADDRESS) @property - def cs_parameters_registry(self) -> interface.CSParametersRegistry: - return interface.CSParametersRegistry(CS_PARAMS_REGISTRY_ADDRESS) + def cs_parameters_registry(self) -> interface.ParametersRegistry: + return interface.ParametersRegistry(CS_PARAMS_REGISTRY_ADDRESS) @property - def cs_fee_distributor(self) -> interface.CSFeeDistributor: - return interface.CSFeeDistributor(CS_FEE_DISTRIBUTOR_ADDRESS) + def cs_fee_distributor(self) -> interface.FeeDistributor: + return interface.FeeDistributor(CS_FEE_DISTRIBUTOR_ADDRESS) @property - def cs_fee_oracle(self) -> interface.CSFeeOracle: - return interface.CSFeeOracle(CS_FEE_ORACLE_ADDRESS) + def cs_fee_oracle(self) -> interface.FeeOracle: + return interface.FeeOracle(CS_FEE_ORACLE_ADDRESS) @property def csm_hash_consensus(self) -> interface.CSHashConsensus: return interface.CSHashConsensus(CS_ORACLE_HASH_CONSENSUS_ADDRESS) @property - def cs_verifier(self) -> interface.CSVerifierV2: + def cs_verifier(self): + if globals().get("CS_VERIFIER_V3_ADDRESS"): + return interface.Verifier(CS_VERIFIER_V3_ADDRESS) return interface.CSVerifierV2(CS_VERIFIER_V2_ADDRESS) @property - def cs_exit_penalties(self) -> interface.CSExitPenalties: - return interface.CSExitPenalties(CS_EXIT_PENALTIES_ADDRESS) + def cs_exit_penalties(self) -> interface.ExitPenalties: + return interface.ExitPenalties(CS_EXIT_PENALTIES_ADDRESS) @property - def cs_ejector(self) -> interface.CSEjector: - return interface.CSEjector(CS_EJECTOR_ADDRESS) + def cs_ejector(self) -> interface.Ejector: + return interface.Ejector(CS_EJECTOR_ADDRESS) @property - def cs_strikes(self) -> interface.CSStrikes: - return interface.CSStrikes(CS_STRIKES_ADDRESS) + def cs_strikes(self) -> interface.ValidatorStrikes: + return interface.ValidatorStrikes(CS_STRIKES_ADDRESS) @property def sandbox(self) -> interface.SimpleDVT: From 61bd7a1297314cdd903b1dc5c4ad9490d2d9be3f Mon Sep 17 00:00:00 2001 From: skhomuti Date: Thu, 9 Jul 2026 13:12:03 +0500 Subject: [PATCH 11/30] ci: keep staking modules workflow dispatchable --- .github/workflows/{sm-tests.yml => csm_tests.yml} | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) rename .github/workflows/{sm-tests.yml => csm_tests.yml} (85%) diff --git a/.github/workflows/sm-tests.yml b/.github/workflows/csm_tests.yml similarity index 85% rename from .github/workflows/sm-tests.yml rename to .github/workflows/csm_tests.yml index 0a14c7bb..4aee5d41 100644 --- a/.github/workflows/sm-tests.yml +++ b/.github/workflows/csm_tests.yml @@ -93,17 +93,9 @@ jobs: id: modules-regression-vote-block shell: bash run: | - response=$(curl -sS --fail \ - -X POST \ - -H "Content-Type: application/json" \ - --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' \ - ${{ env.HARDHAT_NODE_URL }}) - block_hex=$(printf "%s" "$response" | sed -E 's/.*"result":"([^"]+)".*/\1/') - if [ -z "$block_hex" ] || [ "$block_hex" = "$response" ]; then - echo "Unable to parse block number from response: $response" >&2 - exit 1 - fi - echo "vote_prev_block=$((16#${block_hex#0x}))" >> "$GITHUB_OUTPUT" + vote_prev_block=$(make --no-print-directory __get_rpc_latest_block_number CORE_TESTS_TARGET_RPC_URL=${{ env.HARDHAT_NODE_URL }}) + echo "vote_prev_block=$vote_prev_block" >> "$GITHUB_OUTPUT" + working-directory: scripts - name: Prepare test environment with Brownie run: PYTHONPATH=$PWD poetry run brownie run scripts/ci/prepare_environment --network mfh-1 From 8ea20e29e0dd7ecbe155a53221e4012704c3bd87 Mon Sep 17 00:00:00 2001 From: skhomuti Date: Thu, 9 Jul 2026 14:02:56 +0500 Subject: [PATCH 12/30] test: harden merkle gate permission revert check --- tests/regression/test_easy_track_factories.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/regression/test_easy_track_factories.py b/tests/regression/test_easy_track_factories.py index 1928738c..0a9e6320 100644 --- a/tests/regression/test_easy_track_factories.py +++ b/tests/regression/test_easy_track_factories.py @@ -746,15 +746,15 @@ def test_set_merkle_gate_tree_factory_reverts_for_other_module_gate(factory_addr wrong_gate = interface.MerkleGate(wrong_gate_address) calldata, _, _ = _set_merkle_gate_tree_calldata(wrong_gate) - try: + assert _permissions_include(factory.address, factory.address, factory.validateInputData) + assert not _permissions_include(factory.address, wrong_gate.address, wrong_gate.setTreeParams) + + with pytest.raises(VirtualMachineError): contracts.easy_track.createMotion( factory, calldata, {"from": set_balance(factory.trustedCaller(), 100000)}, ) - assert False, "Expected HAS_NO_PERMISSIONS revert" - except VirtualMachineError as error: - assert "HAS_NO_PERMISSIONS" in error.message @pytest.mark.parametrize( From cddf4194cb8577c68cea6fcf6e3ee8764f137530 Mon Sep 17 00:00:00 2001 From: skhomuti Date: Thu, 9 Jul 2026 21:42:10 +0500 Subject: [PATCH 13/30] test: update staking modules regression workflow --- .../workflows/{csm_tests.yml => sm-tests.yml} | 6 +- scripts/ci/prepare_environment.py | 14 +- scripts/upgrade_2026_07_15_srv3_cmv2.py | 16 +- tests/regression/test_csm.py | 611 ------------------ 4 files changed, 29 insertions(+), 618 deletions(-) rename .github/workflows/{csm_tests.yml => sm-tests.yml} (94%) delete mode 100644 tests/regression/test_csm.py diff --git a/.github/workflows/csm_tests.yml b/.github/workflows/sm-tests.yml similarity index 94% rename from .github/workflows/csm_tests.yml rename to .github/workflows/sm-tests.yml index 4aee5d41..d9c26730 100644 --- a/.github/workflows/csm_tests.yml +++ b/.github/workflows/sm-tests.yml @@ -105,10 +105,10 @@ jobs: ETHERSCAN_TOKEN: ${{ secrets.ETHERSCAN_TOKEN }} - name: Run staking modules regression tests - uses: lidofinance/community-staking-module/.github/actions/regression-tests@agent/staking-modules-regression-action + uses: lidofinance/staking-modules/.github/actions/regression-tests@develop with: - repository: lidofinance/community-staking-module + repository: lidofinance/staking-modules ref: develop - path: community-staking-module + path: staking-modules rpc_url: ${{ env.HARDHAT_NODE_URL }} vote_prev_block: ${{ steps.modules-regression-vote-block.outputs.vote_prev_block }} diff --git a/scripts/ci/prepare_environment.py b/scripts/ci/prepare_environment.py index 8ad53279..86ff5a56 100644 --- a/scripts/ci/prepare_environment.py +++ b/scripts/ci/prepare_environment.py @@ -20,9 +20,10 @@ def execute_votings_and_process_created_proposals(): vote_script = retrieve_vote_script() votings_to_execute = list(votings_in_flight) + post_vote_on_fork = None if vote_script: - start_vote, get_vote_items = vote_script + start_vote, get_vote_items, post_vote_on_fork = vote_script is_already_in_flight = any( is_vote_script_equal_to_voting_in_flight(vote_id, get_vote_items) @@ -42,6 +43,9 @@ def execute_votings_and_process_created_proposals(): for vote_id in votings_to_execute: pass_and_exec_dao_vote(vote_id=vote_id) + if post_vote_on_fork: + post_vote_on_fork() + def is_vote_script_equal_to_voting_in_flight( voting_id: int, get_vote_items: Callable[[], Tuple[List, List]] ): @@ -76,7 +80,7 @@ def retrieve_votings_in_flight() -> List[int]: print(f"Found votings in flight: {votings_in_flight}") return votings_in_flight -def retrieve_vote_script() -> Tuple[Callable, Callable] | None: +def retrieve_vote_script() -> Tuple[Callable, Callable, Callable | None] | None: vote_files = get_vote_script_files() vote_files.extend(get_upgrade_script_files()) @@ -94,7 +98,11 @@ def retrieve_vote_script() -> Tuple[Callable, Callable] | None: try: exec(f"from {module_name} import start_vote, get_vote_items") - return locals()['start_vote'], locals()['get_vote_items'] + try: + exec(f"from {module_name} import post_vote_on_fork") + except ImportError: + pass + return locals()['start_vote'], locals()['get_vote_items'], locals().get('post_vote_on_fork') except ImportError: raise AttributeError( f"'start_vote' and/or 'get_vote_items' not found in {script_path}." diff --git a/scripts/upgrade_2026_07_15_srv3_cmv2.py b/scripts/upgrade_2026_07_15_srv3_cmv2.py index 08b845be..34cded26 100644 --- a/scripts/upgrade_2026_07_15_srv3_cmv2.py +++ b/scripts/upgrade_2026_07_15_srv3_cmv2.py @@ -104,6 +104,7 @@ from utils.config import ( UPGRADE_VOTE_SCRIPT, + contracts, get_deployer_account, get_is_live, get_priority_fee, @@ -221,6 +222,15 @@ def main(upgrade_vote_script: Optional[str] = None): vote_id >= 0 and print(f"Vote created: {vote_id}.") +def post_vote_on_fork(): + if get_is_live(): + raise Exception("This hook is for local testing only.") + + print("Rebuilding CSM total withdrawn validators after vote...") + contracts.csm.rebuildTotalWithdrawnValidators({"from": get_deployer_account(), "silent": True}) + print("[ok] CSM total withdrawn validators rebuilt") + + def start_and_execute_vote_on_fork_manual(upgrade_vote_script: Optional[str] = None): if get_is_live(): raise Exception("This script is for local testing only.") @@ -232,4 +242,8 @@ def start_and_execute_vote_on_fork_manual(upgrade_vote_script: Optional[str] = N upgrade_vote_script=upgrade_vote_script, ) print(f"Vote created: {vote_id}.") - pass_and_exec_dao_vote(int(vote_id), step_by_step=True) + pass_and_exec_dao_vote( + int(vote_id), + step_by_step=True, + ) + post_vote_on_fork() diff --git a/tests/regression/test_csm.py b/tests/regression/test_csm.py deleted file mode 100644 index 151c626b..00000000 --- a/tests/regression/test_csm.py +++ /dev/null @@ -1,611 +0,0 @@ -import pytest - -from brownie import reverts, web3, ZERO_ADDRESS, accounts, chain - -from tests.conftest import Helpers -from utils.balance import set_balance_in_wei -from utils.config import ( - contracts, - ContractsLazyLoader, - CSM_COMMITTEE_MS, - EASYTRACK_CSM_SETTLE_EL_REWARDS_STEALING_PENALTY_FACTORY, - EASYTRACK_CS_SET_VETTED_GATE_TREE_FACTORY, -) -from utils.dsm import UnvetArgs, to_bytes, set_single_guardian -from utils.staking_module import calc_module_reward_shares -from utils.test.csm_helpers import ( - csm_add_node_operator, csm_upload_keys, csm_add_ics_node_operator, - csm_set_ics_tree_members, -) -from utils.test.deposits_helpers import fill_deposit_buffer -from utils.test.easy_track_helpers import _encode_calldata -from utils.test.helpers import ETH -from utils.test.merkle_tree import StrikesTree -from utils.test.oracle_report_helpers import ( - oracle_report, - wait_to_next_available_report_time, - prepare_csm_report, - reach_consensus, -) -from utils.test.staking_router_helpers import ( - set_staking_module_status, - StakingModuleStatus, - increase_staking_module_share, -) - -contracts: ContractsLazyLoader = contracts - -CSM_MODULE_ID = 3 -MAX_DEPOSITS = 50 - - -@pytest.fixture(scope="module", autouse=True) -def prefetch_contracts_from_etherscan(): - Helpers.prefetch_contracts_from_etherscan() - - -@pytest.fixture(scope="module") -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 - - -@pytest.fixture(scope="module") -def fee_oracle(): - return contracts.cs_fee_oracle - - -@pytest.fixture(scope="module") -def ejector(): - return contracts.cs_ejector - - -@pytest.fixture(scope="module") -def strikes(): - return contracts.cs_strikes - -@pytest.fixture(params=[pytest.param(1, id="1 key")]) -def keys_count(request): - return request.param - -@pytest.fixture -def depositable_node_operator(keys_count, csm, accounting, permissionless_gate, stranger): - return _depositable_node_operator(keys_count, csm, accounting, permissionless_gate, stranger) - - -def _depositable_node_operator(keys_count, csm, accounting, permissionless_gate, stranger): - increase_staking_module_share(module_id=CSM_MODULE_ID, share_multiplier=2) - csm.cleanDepositQueue(2 * csm.getNonce(), {"from": stranger.address}) - keys_to_deposit = 0 - for queue_priority in range(0, 6): - deposit_batch = csm.depositQueueItem(queue_priority, csm.depositQueuePointers(queue_priority)["head"]) - if deposit_batch: - node_operator_id = (deposit_batch >> 192) & ((1 << 64) - 1) - batch_keys_count = (deposit_batch >> 128) & ((1 << 64) - 1) - if batch_keys_count >= keys_count: - break - else: - address = accounts[7].address - node_operator_id = csm_add_node_operator(csm, permissionless_gate, accounting, address, keys_count=keys_count) - return node_operator_id, keys_to_deposit - - -@pytest.fixture() -def node_operator(keys_count, csm, accounting, permissionless_gate, stranger) -> int: - total_node_operators = contracts.csm.getNodeOperatorsCount() - for no_id in range(0, total_node_operators): - no = csm.getNodeOperator(no_id) - if no["totalDepositedKeys"] - no["totalWithdrawnKeys"] >= keys_count: - return no_id - - # Fallback: use _depositable_node_operator - node_operator, required_deposits = _depositable_node_operator(keys_count, csm, accounting, permissionless_gate, stranger) - to_deposit = required_deposits + keys_count - fill_deposit_buffer(to_deposit) - contracts.lido.deposit(to_deposit, CSM_MODULE_ID, "0x", {"from": contracts.deposit_security_module}) - return node_operator - - -@pytest.fixture -def pause_modules(): - # pause deposit to all modules except csm - # to be sure that all deposits goes to csm - modules = contracts.staking_router.getStakingModules() - for module in modules: - if module[0] != CSM_MODULE_ID: - set_staking_module_status(module[0], StakingModuleStatus.Stopped) - - -@pytest.fixture -def remove_stake_limit(): - contracts.acl.grantPermission(contracts.agent, contracts.lido, web3.keccak(text="STAKING_CONTROL_ROLE"), {"from": contracts.agent}) - contracts.lido.removeStakingLimit({"from": accounts.at(contracts.agent, force=True)}) - - -@pytest.fixture -def ref_slot(): - wait_to_next_available_report_time(contracts.csm_hash_consensus) - ref_slot, _ = contracts.csm_hash_consensus.getCurrentFrame() - return ref_slot - - -def distribute_reward_tree(node_operator, ref_slot): - consensus_version = contracts.cs_fee_oracle.getConsensusVersion() - oracle_version = contracts.cs_fee_oracle.getContractVersion() - distributed_before = contracts.lido.sharesOf(contracts.cs_fee_distributor) - claimed_before = contracts.cs_fee_distributor.distributedShares(node_operator) - - rewards = ETH(0.05) - oracle_report(cl_diff=rewards) - distributed_shares = contracts.lido.sharesOf(contracts.cs_fee_distributor) - distributed_before - assert distributed_shares > 0 - - report, report_hash, tree = prepare_csm_report({node_operator: claimed_before + distributed_shares}, ref_slot, distributed_shares) - - submitter = reach_consensus( - ref_slot, - report_hash, - consensus_version, - contracts.csm_hash_consensus, - ) - - contracts.cs_fee_oracle.submitReportData(report, oracle_version, {"from": submitter}) - return distributed_shares, tree.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") - - -def test_add_node_operators_ics(csm, vetted_gate, accounting, accounts): - members = [account.address for account in accounts[3:5]] - tree = csm_set_ics_tree_members(members) - for address in members: - proof = list(tree.tree.get_proof(tree.tree.find(tree.tree.leaf([address])))) - 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) == vetted_gate.curveId() - - -def test_add_node_operator_permissionless(csm, permissionless_gate, accounting, accounts): - address = accounts[8].address - no_id = csm_add_node_operator(csm, permissionless_gate, accounting, address) - no = csm.getNodeOperator(no_id) - - assert no["managerAddress"] == address - assert no["rewardAddress"] == address - assert accounting.getBondCurveId(no_id) == accounting.DEFAULT_BOND_CURVE_ID() - - -@pytest.mark.usefixtures("pause_modules") -def test_deposit(depositable_node_operator, csm, remove_stake_limit, keys_count): - (node_operator, required_deposits) = depositable_node_operator - to_deposit = required_deposits + keys_count - fill_deposit_buffer(to_deposit) - total_deposited_before = csm.getNodeOperator(node_operator)["totalDepositedKeys"] - contracts.lido.deposit(to_deposit, CSM_MODULE_ID, "0x", {"from": contracts.deposit_security_module}) - - no = csm.getNodeOperator(node_operator) - assert no["totalDepositedKeys"] == total_deposited_before + keys_count - - -def test_mint_rewards_happy_path(csm, fee_distributor): - csm_shares_before = contracts.lido.sharesOf(csm) - fee_distributor_shares_before = contracts.lido.sharesOf(fee_distributor) - (report_tx, _) = oracle_report() - minted_shares = report_tx.events["TokenRebased"]["sharesMintedAsFees"] - csm_distributed_rewards = calc_module_reward_shares(CSM_MODULE_ID, minted_shares) - - assert csm_shares_before == contracts.lido.sharesOf(csm) - assert contracts.lido.sharesOf(fee_distributor) == fee_distributor_shares_before + csm_distributed_rewards - - -def test_csm_target_limits(csm, node_operator): - target_limit_mode = 1 - target_limit = 2 - contracts.staking_router.updateTargetValidatorsLimits( - CSM_MODULE_ID, node_operator, target_limit_mode, target_limit, {"from": contracts.agent} - ) - - no = csm.getNodeOperator(node_operator) - assert no["targetLimitMode"] == target_limit_mode - assert no["targetLimit"] == target_limit - - -def test_csm_report_exited(csm, node_operator, extra_data_service): - total_exited = csm.getStakingModuleSummary()["totalExitedValidators"] - no = csm.getNodeOperator(node_operator) - exited_keys = no["totalExitedKeys"] + 1 - 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, - extraDataItemsCount=1, - extraDataList=extra_data.extra_data_list, - stakingModuleIdsWithNewlyExitedValidators=[CSM_MODULE_ID], - numExitedValidatorsByStakingModule=[total_exited + exited_keys], - ) - - no = csm.getNodeOperator(node_operator) - assert no["totalExitedKeys"] == exited_keys - - -@pytest.mark.usefixtures("pause_modules") -def test_csm_get_staking_module_summary(csm, accounting, node_operator, extra_data_service, remove_stake_limit, permissionless_gate, stranger): - - # Assure there are new exited keys - (exited_before, _, _) = contracts.staking_router.getStakingModuleSummary(CSM_MODULE_ID) - no = csm.getNodeOperator(node_operator) - exited_keys = no["totalExitedKeys"] + 1 - 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, - extraDataItemsCount=1, - extraDataList=extra_data.extra_data_list, - stakingModuleIdsWithNewlyExitedValidators=[CSM_MODULE_ID], - numExitedValidatorsByStakingModule=[exited_before + exited_keys], - ) - - # Assure there are new deposited keys - keys_to_deposit = 2 - depositable_no, required_deposits = _depositable_node_operator(keys_to_deposit, csm, accounting, permissionless_gate, stranger) - (_, deposited_before, _) = contracts.staking_router.getStakingModuleSummary(CSM_MODULE_ID) - to_deposit = required_deposits + keys_to_deposit - fill_deposit_buffer(to_deposit) - contracts.lido.deposit(to_deposit, CSM_MODULE_ID, "0x", {"from": contracts.deposit_security_module}) - - - # Assure there are new depositable keys - (_, _, depositable_before) = contracts.staking_router.getStakingModuleSummary(CSM_MODULE_ID) - new_depositable = 5 - csm_upload_keys(csm, accounting, node_operator, new_depositable) - - (exited_after, deposited_after, depositable_after) = contracts.staking_router.getStakingModuleSummary(CSM_MODULE_ID) - - assert exited_after == exited_before + exited_keys - assert deposited_after == deposited_before + to_deposit - assert depositable_after == depositable_before + new_depositable - - -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 = no["totalExitedKeys"] + 1 - 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, - extraDataItemsCount=1, - extraDataList=extra_data.extra_data_list, - stakingModuleIdsWithNewlyExitedValidators=[CSM_MODULE_ID], - numExitedValidatorsByStakingModule=[total_exited], - ) - - summary = contracts.staking_router.getNodeOperatorSummary(CSM_MODULE_ID, node_operator) - assert summary["targetLimitMode"] == no["targetLimitMode"] - assert summary["targetValidatorsCount"] == no["targetLimit"] - # 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"] == no["depositableValidatorsCount"] - - -def test_csm_decrease_vetted_keys(csm, depositable_node_operator, stranger): - (node_operator, _) = depositable_node_operator - no = csm.getNodeOperator(node_operator) - depositable_keys = no["depositableValidatorsCount"] - no["totalWithdrawnKeys"] - total_added_keys = csm.getNodeOperator(node_operator)["totalAddedKeys"] - block_number = web3.eth.get_block_number() - block = web3.eth.get_block(block_number) - staking_module_nonce = contracts.staking_router.getStakingModuleNonce(CSM_MODULE_ID) - unvet_args = UnvetArgs( - block_number=block_number, - block_hash=block.hash, - staking_module_id=CSM_MODULE_ID, - nonce=staking_module_nonce, - node_operator_ids=to_bytes(node_operator, 16), - vetted_signing_keys_counts=to_bytes(total_added_keys - depositable_keys, 32), - ) - - set_single_guardian(contracts.deposit_security_module, contracts.agent, stranger) - - contracts.deposit_security_module.unvetSigningKeys(*unvet_args.to_tuple(), (0, 0), {"from": stranger.address}) - - no = csm.getNodeOperator(node_operator) - assert no["totalVettedKeys"] == total_added_keys - depositable_keys - - -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}) - assert "StETHBurnRequested" in tx.events - burnt_shares = tx.events["StETHBurnRequested"]["amountOfShares"] - assert accounting.getBondShares(node_operator) == bond_shares_before - burnt_shares - - -def test_csm_eth_bond(csm, accounting, node_operator): - manager_address = csm.getNodeOperator(node_operator)["managerAddress"] - set_balance_in_wei(manager_address, ETH(2)) - - bond_shares_before = accounting.getBondShares(node_operator) - shares = contracts.lido.getSharesByPooledEth(ETH(1)) - accounting.depositETH(node_operator, {"from": manager_address, "value": ETH(1)}) - assert accounting.getBondShares(node_operator) == bond_shares_before + shares - - -def test_csm_steth_bond(csm, accounting, node_operator): - manager_address = csm.getNodeOperator(node_operator)["managerAddress"] - set_balance_in_wei(manager_address, ETH(2)) - - bond_shares_before = accounting.getBondShares(node_operator) - contracts.lido.submit(ZERO_ADDRESS, {"from": manager_address, "value": ETH(1.5)}) - 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}) - assert accounting.getBondShares(node_operator) == bond_shares_before + shares - - -def test_csm_wsteth_bond(csm, accounting, node_operator): - manager_address = csm.getNodeOperator(node_operator)["managerAddress"] - set_balance_in_wei(manager_address, ETH(2)) - contracts.lido.submit(ZERO_ADDRESS, {"from": manager_address, "value": ETH(1.5)}) - contracts.lido.approve(contracts.wsteth, ETH(1.5), {"from": manager_address}) - contracts.wsteth.wrap(ETH(1.5), {"from": manager_address}) - contracts.wsteth.approve(accounting, contracts.wsteth.balanceOf(manager_address), {"from": manager_address}) - - shares = contracts.lido.getSharesByPooledEth( - contracts.wsteth.getStETHByWstETH(contracts.wsteth.balanceOf(manager_address)) - ) - bond_shares_before = accounting.getBondShares(node_operator) - 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 - - -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) - - distributed_shares, tree = distribute_reward_tree(node_operator, ref_slot) - cumulative_shares = tree.values[0]["value"][1] - proof = list(tree.get_proof(tree.find(tree.leaf((node_operator, cumulative_shares))))) - claimable_bond_shares_before = accounting.getClaimableBondShares(node_operator) - - accounting.claimRewardsStETH(node_operator, ETH(999), cumulative_shares, proof, {"from": reward_address}) - - shares_after = contracts.lido.sharesOf(reward_address) - assert shares_after == shares_before + distributed_shares + claimable_bond_shares_before - - -def test_csm_claim_rewards_wsteth(csm, accounting, node_operator, ref_slot): - _, tree = distribute_reward_tree(node_operator, ref_slot) - 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}) - assert contracts.wsteth.balanceOf(reward_address) > wsteth_before - - -def test_csm_claim_rewards_eth(csm, accounting, node_operator, ref_slot): - _, tree = distribute_reward_tree(node_operator, ref_slot) - 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}) - - assert len(contracts.withdrawal_queue.getWithdrawalRequests(reward_address)) == len(withdrawal_requests) + 1 - - -def test_csm_remove_key(csm, parameters_registry, accounting, node_operator): - csm_upload_keys(csm, accounting, node_operator, 1) - - no = csm.getNodeOperator(node_operator) - keys_before = no["totalAddedKeys"] - manager_address = csm.getNodeOperator(node_operator)["managerAddress"] - tx = csm.removeKeys(node_operator, keys_before - 1, 1, {"from": manager_address}) - - assert "KeyRemovalChargeApplied" in tx.events - assert "BondCharged" in tx.events - - curve_id = accounting.getBondCurveId(node_operator) - expected_charge_amount = contracts.lido.getPooledEthByShares( - contracts.lido.getSharesByPooledEth(parameters_registry.getKeyRemovalCharge(curve_id)) - ) - assert tx.events["BondCharged"]["toChargeAmount"] == expected_charge_amount - no = csm.getNodeOperator(node_operator) - assert no["totalAddedKeys"] == keys_before - 1 - - -@pytest.mark.parametrize("keys_count", [pytest.param(2, id="2 keys")], indirect=True) -def test_eject_bad_performer(csm, accounting, ejector, strikes, node_operator, stranger, keys_count): - no = csm.getNodeOperator(node_operator) - index_to_eject = no["totalDepositedKeys"] - 2 - pubkey_to_eject = csm.getSigningKeys(node_operator, index_to_eject, 1) - leaf_to_eject = (node_operator, pubkey_to_eject, [1, 1, 1, 1, 1, 1]) - another_pubkey = csm.getSigningKeys(node_operator, index_to_eject + 1, 1) - strikes_tree = StrikesTree.new( - [leaf_to_eject, (node_operator, another_pubkey, [1, 1, 0, 0, 0, 0])] - ) - index_in_tree = strikes_tree.tree.find(strikes_tree.tree.leaf(leaf_to_eject)) - proof, flags = strikes_tree.tree.get_multi_proof([index_in_tree]) - strikes.processOracleReport( - strikes_tree.root, - "QmTest123456789", - {"from": contracts.cs_fee_oracle} - ) - - eject_payment_value = get_sys_fee_to_eject() - - bad_performer = (node_operator, index_to_eject, [1, 1, 1, 1, 1, 1]) - tx = strikes.processBadPerformanceProof( - [bad_performer], - proof, - flags, - ZERO_ADDRESS, - {"value": eject_payment_value, "from": stranger} - ) - assert "StrikesPenaltyProcessed" in tx.events - assert tx.events["StrikesPenaltyProcessed"]["nodeOperatorId"] == node_operator - assert tx.events["StrikesPenaltyProcessed"]["pubkey"] == pubkey_to_eject - - curve_id = accounting.getBondCurveId(node_operator) - penalty = contracts.cs_parameters_registry.getBadPerformancePenalty(curve_id) - assert tx.events["StrikesPenaltyProcessed"]["strikesPenalty"] == penalty - - assert "TriggeredExitFeeRecorded" in tx.events - assert tx.events["TriggeredExitFeeRecorded"]["nodeOperatorId"] == node_operator - assert tx.events["TriggeredExitFeeRecorded"]["pubkey"] == pubkey_to_eject - assert tx.events["TriggeredExitFeeRecorded"]["exitType"] == 1 - assert tx.events["TriggeredExitFeeRecorded"]["withdrawalRequestPaidFee"] == eject_payment_value - assert tx.events["TriggeredExitFeeRecorded"]["withdrawalRequestRecordedFee"] == eject_payment_value - - -def test_voluntary_eject(csm, ejector, node_operator): - eject_payment_value = get_sys_fee_to_eject() - operator_address = csm.getNodeOperatorOwner(node_operator) - no = csm.getNodeOperator(node_operator) - index_to_eject = no["totalDepositedKeys"] - 1 - - tx = ejector.voluntaryEject( - node_operator, index_to_eject, 1, ZERO_ADDRESS, {"value": eject_payment_value, "from": operator_address} - ) - assert "TriggeredExitFeeRecorded" not in tx.events - - -def test_report_validator_exit_delay(csm, accounting, parameters_registry, node_operator): - day_in_seconds = 60 * 60 * 24 - no = csm.getNodeOperator(node_operator) - index_to_report = no["totalDepositedKeys"] - 1 - pubkey = csm.getSigningKeys(node_operator, index_to_report, 1) - - tx = csm.reportValidatorExitDelay(node_operator, index_to_report, 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 - - curve_id = accounting.getBondCurveId(node_operator) - penalty = parameters_registry.getExitDelayPenalty(curve_id) - assert tx.events["ValidatorExitDelayProcessed"]["delayPenalty"] == penalty - - -def test_on_validator_exit_triggered(csm, node_operator): - eject_payment_value = 1 - no = csm.getNodeOperator(node_operator) - index_to_report = no["totalDepositedKeys"] - 1 - pubkey = csm.getSigningKeys(node_operator, index_to_report, 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 - - -def test_easy_track_csm_settle_el_stealing_penalty(csm, accounting, node_operator, stranger): - manager_address = csm.getNodeOperator(node_operator)["managerAddress"] - set_balance_in_wei(manager_address, ETH(2)) - accounting.depositETH(node_operator, {"from": manager_address, "value": ETH(1)}) - - csm.reportELRewardsStealingPenalty(node_operator, b'\x00' * 32, ETH(0.5), {"from": CSM_COMMITTEE_MS}) - - motions_before = contracts.easy_track.getMotions() - - calldata = _encode_calldata(["uint256[]"], [[node_operator]]) - tx = contracts.easy_track.createMotion(EASYTRACK_CSM_SETTLE_EL_REWARDS_STEALING_PENALTY_FACTORY, calldata, {"from": CSM_COMMITTEE_MS}) - - motions = contracts.easy_track.getMotions() - assert len(motions) == len(motions_before) + 1 - - chain.sleep(60 * 60 * 24 * 3) - chain.mine() - - bond_before = accounting.getBond(node_operator) - - contracts.easy_track.enactMotion( - motions[-1][0], - tx.events["MotionCreated"]["_evmScriptCallData"], - {"from": stranger}, - ) - - bond_after = accounting.getBond(node_operator) - - assert bond_before > bond_after, "Bond should be decreased after settling penalty" - - -def test_easy_track_csm_set_vetted_gate_tree( - csm, accounting, node_operator, stranger -): - motions_before = contracts.easy_track.getMotions() - - new_tree_root = bytes.fromhex("1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef") - new_tree_cid = "QmTest123456789" - calldata = _encode_calldata(["bytes32", "string"], [new_tree_root, new_tree_cid]) - - tx = contracts.easy_track.createMotion(EASYTRACK_CS_SET_VETTED_GATE_TREE_FACTORY, calldata, {"from": CSM_COMMITTEE_MS}) - - motions = contracts.easy_track.getMotions() - assert len(motions) == len(motions_before) + 1 - - chain.sleep(60 * 60 * 24 * 3) - chain.mine() - - contracts.easy_track.enactMotion( - motions[-1][0], - tx.events["MotionCreated"]["_evmScriptCallData"], - {"from": stranger}, - ) - - vetted_gate_tree_root_after = contracts.cs_vetted_gate.treeRoot() - vetted_gate_tree_cid_after = contracts.cs_vetted_gate.treeCid() - - assert vetted_gate_tree_root_after == ("0x" + new_tree_root.hex()), "Tree root not updated" - assert vetted_gate_tree_cid_after == new_tree_cid, "Tree CID not updated" From 794aa09abe7c7d16c6cd474d2b94526803ea061f Mon Sep 17 00:00:00 2001 From: skhomuti Date: Thu, 9 Jul 2026 23:34:02 +0500 Subject: [PATCH 14/30] test: fix staking modules ABI references --- tests/regression/test_permissions.py | 44 ++++++++++++++++++---- tests/test_upgrade_2026_07_15_srv3_cmv2.py | 8 ++-- utils/config.py | 4 +- 3 files changed, 42 insertions(+), 14 deletions(-) diff --git a/tests/regression/test_permissions.py b/tests/regression/test_permissions.py index 41f4ba3e..02ebe2df 100644 --- a/tests/regression/test_permissions.py +++ b/tests/regression/test_permissions.py @@ -100,11 +100,11 @@ def protocol_permissions(): ) cs_verifier_address = cs_verifier.address burner_request_burn_my_steth_holders = ( - [contracts.csm.accounting(), CM_ACCOUNTING_ADDRESS] if is_csm_v3 else [] + [CS_ACCOUNTING_ADDRESS, CM_ACCOUNTING_ADDRESS] if is_csm_v3 else [] ) burner_request_burn_shares_holders = [contracts.accounting] if not is_csm_v3: - burner_request_burn_shares_holders.append(contracts.csm.accounting()) + burner_request_burn_shares_holders.append(CS_ACCOUNTING_ADDRESS) csm_create_node_operator_holders = [cs_permissionless_gate_address, CS_VETTED_GATE_ADDRESS] if is_csm_v3: csm_create_node_operator_holders.append(CS_IDENTIFIED_DVT_CLUSTER_GATE_ADDRESS) @@ -135,6 +135,17 @@ def protocol_permissions(): "REPORT_REGULAR_WITHDRAWN_VALIDATORS_ROLE": [cs_verifier_address], "REPORT_SLASHED_WITHDRAWN_VALIDATORS_ROLE": [EASYTRACK_EVMSCRIPT_EXECUTOR], }) + csm_ignored_abi_roles = set() + if not is_csm_v3: + csm_ignored_abi_roles.update({ + "MANAGE_TOP_UP_QUEUE_ROLE", + "REWIND_TOP_UP_QUEUE_ROLE", + "OPERATOR_ADDRESSES_ADMIN_ROLE", + "REPORT_GENERAL_DELAYED_PENALTY_ROLE", + "SETTLE_GENERAL_DELAYED_PENALTY_ROLE", + "REPORT_REGULAR_WITHDRAWN_VALIDATORS_ROLE", + "REPORT_SLASHED_WITHDRAWN_VALIDATORS_ROLE", + }) csm_role_preimages = { "REPORT_EL_REWARDS_STEALING_PENALTY_ROLE": "REPORT_EL_REWARDS_STEALING_PENALTY_ROLE", "SETTLE_EL_REWARDS_STEALING_PENALTY_ROLE": "SETTLE_EL_REWARDS_STEALING_PENALTY_ROLE", @@ -158,6 +169,22 @@ def protocol_permissions(): "START_REFERRAL_SEASON_ROLE": [contracts.agent], "END_REFERRAL_SEASON_ROLE": [CSM_COMMITTEE_MS], }) + vetted_gate_role_preimages = {} + if not is_csm_v3: + vetted_gate_role_preimages.update({ + "START_REFERRAL_SEASON_ROLE": "START_REFERRAL_SEASON_ROLE", + "END_REFERRAL_SEASON_ROLE": "END_REFERRAL_SEASON_ROLE", + }) + cs_parameters_registry_roles = { + "DEFAULT_ADMIN_ROLE": [contracts.agent], + "MANAGE_GENERAL_PENALTIES_AND_CHARGES_ROLE": [CSM_COMMITTEE_MS] if is_csm_v3 else [], + "MANAGE_KEYS_LIMIT_ROLE": [], + "MANAGE_QUEUE_CONFIG_ROLE": [], + "MANAGE_PERFORMANCE_PARAMETERS_ROLE": [], + "MANAGE_REWARD_SHARE_ROLE": [], + "MANAGE_VALIDATOR_EXIT_PARAMETERS_ROLE": [], + "MANAGE_CURVE_PARAMETERS_ROLE": [], + } return { LIDO_LOCATOR: { @@ -423,6 +450,7 @@ def protocol_permissions(): "proxy_owner": contracts.agent, "roles": csm_roles, "role_preimages": csm_role_preimages, + "ignored_abi_roles": csm_ignored_abi_roles, }, CS_ACCOUNTING_ADDRESS: { "contract_name": "Accounting", @@ -491,9 +519,7 @@ def protocol_permissions(): "contract": contracts.cs_parameters_registry, "type": "CustomApp", "proxy_owner": contracts.agent, - "roles": { - "DEFAULT_ADMIN_ROLE": [contracts.agent], - }, + "roles": cs_parameters_registry_roles, }, CS_STRIKES_ADDRESS: { "contract_name": "ValidatorStrikes", @@ -521,6 +547,7 @@ def protocol_permissions(): "type": "CustomApp", "proxy_owner": contracts.agent, "roles": vetted_gate_roles, + "role_preimages": vetted_gate_role_preimages, }, cs_permissionless_gate_address: { "contract_name": "PermissionlessGate", @@ -669,6 +696,7 @@ def test_protocol_permissions(protocol_permissions): abi_roles = set(abi_roles_list) configured_roles = set(permissions_config["roles"]) custom_role_preimages = set(permissions_config.get("role_preimages", {})) + ignored_abi_roles = set(permissions_config.get("ignored_abi_roles", {})) if contract_address in [NODE_OPERATORS_REGISTRY, SIMPLE_DVT]: abi_roles_list.append("MANAGE_SIGNING_KEYS") @@ -676,8 +704,10 @@ def test_protocol_permissions(protocol_permissions): roles = permissions_config["roles"] - assert abi_roles.issubset(configured_roles), "Contract {} has undescribed ABI roles {}".format( - permissions_config["contract_name"], abi_roles - configured_roles + assert (abi_roles - ignored_abi_roles).issubset(configured_roles), ( + "Contract {} has undescribed ABI roles {}".format( + permissions_config["contract_name"], abi_roles - configured_roles - ignored_abi_roles + ) ) assert configured_roles.issubset(abi_roles | custom_role_preimages), ( "Contract {} has configured roles absent from ABI and role_preimages {}".format( diff --git a/tests/test_upgrade_2026_07_15_srv3_cmv2.py b/tests/test_upgrade_2026_07_15_srv3_cmv2.py index b593e547..93a31de7 100644 --- a/tests/test_upgrade_2026_07_15_srv3_cmv2.py +++ b/tests/test_upgrade_2026_07_15_srv3_cmv2.py @@ -541,9 +541,9 @@ def runtime_upgrade_context(): # Load ABIs for Brownie receipt event decoding. interface.CircuitBreaker(global_config["circuitBreaker"]) interface.ValidatorsExitBusOracle(core_config["validatorsExitBusOracle"]) - interface.CSParametersRegistry(csm_config["parametersRegistry"]) + interface.ParametersRegistry(csm_config["parametersRegistry"]) interface.OneShotCurveSetup(csm_config["identifiedDVTClusterCurveSetup"]) - interface.CSAccounting(csm_config["accounting"]) # BondCurveAdded (curve setup item) + interface.ModuleAccounting(csm_config["accounting"]) # BondCurveAdded (curve setup item) # ExitBalanceLimitSet exists only in the new ValidatorsExitBusOracle impl ABI (not in the # local interfaces/*.json), so fetch that impl from the explorer to make it decodable. Contract.from_explorer(convert.to_address(core_config["newValidatorsExitBusOracleImpl"])) @@ -969,7 +969,7 @@ def test_vote( # ========================================================================= if expected_dg_proposal_id is not None: # --- pre-DG state snapshots used by the after-DG acceptance checks --- - initial_cs_fee_oracle_consensus_version = interface.CSFeeOracle(ctx["cs_fee_oracle"]).getConsensusVersion() + initial_cs_fee_oracle_consensus_version = interface.FeeOracle(ctx["cs_fee_oracle"]).getConsensusVersion() details = timelock.getProposalDetails(expected_dg_proposal_id) if details["status"] != PROPOSAL_STATUS["executed"]: @@ -1614,7 +1614,7 @@ def test_vote( ) assert interface.WithdrawalVault(ctx["withdrawal_vault"]).getContractVersion() == WITHDRAWAL_VAULT_CONTRACT_VERSION assert interface.Lido(ctx["lido"]).getContractVersion() == LIDO_CONTRACT_VERSION - assert interface.CSFeeOracle(ctx["cs_fee_oracle"]).getConsensusVersion() == ctx["cs_fee_oracle_consensus_version"] + assert interface.FeeOracle(ctx["cs_fee_oracle"]).getConsensusVersion() == ctx["cs_fee_oracle_consensus_version"] # Staking Router role migration & new roles. assert staking_router.hasRole(STAKING_MODULE_SHARE_MANAGE_ROLE, ctx["easytrack_evm_script_executor"]) diff --git a/utils/config.py b/utils/config.py index 6ec07161..8347ac96 100644 --- a/utils/config.py +++ b/utils/config.py @@ -239,9 +239,7 @@ def csm_hash_consensus(self) -> interface.CSHashConsensus: return interface.CSHashConsensus(CS_ORACLE_HASH_CONSENSUS_ADDRESS) @property - def cs_verifier(self): - if globals().get("CS_VERIFIER_V3_ADDRESS"): - return interface.Verifier(CS_VERIFIER_V3_ADDRESS) + def cs_verifier(self) -> interface.CSVerifierV2: return interface.CSVerifierV2(CS_VERIFIER_V2_ADDRESS) @property From d7f6c8e82170e08720e2b192680e13d6fe6e2b6f Mon Sep 17 00:00:00 2001 From: KRogLA Date: Thu, 9 Jul 2026 22:45:55 +0200 Subject: [PATCH 15/30] test: skip some changed by upgrade slots from snapshot --- tests/snapshot/test_first_slots.py | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/tests/snapshot/test_first_slots.py b/tests/snapshot/test_first_slots.py index 9e6a4385..a5011d26 100644 --- a/tests/snapshot/test_first_slots.py +++ b/tests/snapshot/test_first_slots.py @@ -47,8 +47,27 @@ def test_first_slots(sandwich_upgrade: SandwichFn): @pytest.fixture(scope="module") def skip_slots() -> Sequence[tuple[str, int]]: - """Slots that are not checked for equality""" - return [] + """Slots intentionally modified by the SRV3/CMV2 upgrade.""" + return [ + ( + # EasyTrack factories array: the vote removes two factories and adds nine. + contracts.easy_track.address, + 0x05, + ), + ( + # CSM v3 repurposes the old DepositQueueLib.Queue pointers as + # totalWithdrawnValidators; finalizeUpgradeV3 resets this value. + contracts.csm.address, + 0x01, + ), + ( + # CSM v3 repurposes this formerly unused mapping slot as + # upToDateOperatorDepositInfoCount and initializes it from + # nodeOperatorsCount during finalizeUpgradeV3. + contracts.csm.address, + 0x02, + ), + ] @pytest.fixture(scope="module") From 66ea219a3826cce49b60d08307072e4c2053b3c1 Mon Sep 17 00:00:00 2001 From: KRogLA Date: Thu, 9 Jul 2026 22:48:41 +0200 Subject: [PATCH 16/30] test: exclude aggregate/view slots touched by mandatory oracle report before upgrade migration --- tests/snapshot/test_lido_snapshot.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/snapshot/test_lido_snapshot.py b/tests/snapshot/test_lido_snapshot.py index a12c693d..f59f03e5 100644 --- a/tests/snapshot/test_lido_snapshot.py +++ b/tests/snapshot/test_lido_snapshot.py @@ -36,10 +36,30 @@ class Frame(TypedDict): EXPECTED_SNAPSHOT_DIFFS: dict[str, Any] = { + # Lido v4 migrates these v3 packed slots to new storage locations and clears + # the legacy slots. They must stay cleared after every scenario action. + "lido.Lido.clBalanceAndClValidators": ZERO_BYTES32, + "lido.Lido.bufferedEtherAndDepositedValidators": ZERO_BYTES32, } IGNORED_SNAPSHOT_KEYS: set[str] = { + # The upgrade requires an AccountingOracle report before Lido v4 migration. + # That report rebases stETH; v4 also changes the representation returned by + # getBeaconStat. Their absolute values are therefore not comparable across + # the pre-upgrade and post-upgrade frames. + "totalSupply", + "balanceOf(eth_whale)", + "balanceOf(steth_whale)", + "sharesOf(eth_whale)", + "getBeaconStat", + "getBufferedEther", + "getTotalPooledEther", + "getTotalELRewardsCollected", + "getTotalShares", + "getSharesByPooledEth(1 ETH)", + "lido.Lido.totalELRewardsCollected", + "lido.StETH.totalAndExternalShares", "getFeeDistribution", } From cc2a3c622108e2d34f042fe56f948ef3e07556fd Mon Sep 17 00:00:00 2001 From: KRogLA Date: Thu, 9 Jul 2026 22:52:02 +0200 Subject: [PATCH 17/30] test: workaround for deposit flor before/after upgrade --- .../snapshot/test_node_operators_registry.py | 39 ++++++++++++++++++- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/tests/snapshot/test_node_operators_registry.py b/tests/snapshot/test_node_operators_registry.py index 554f23b0..bfe0b039 100644 --- a/tests/snapshot/test_node_operators_registry.py +++ b/tests/snapshot/test_node_operators_registry.py @@ -3,7 +3,7 @@ from web3 import Web3 from datetime import datetime from typing import Any, Dict, Callable -from brownie import ZERO_ADDRESS, Wei, convert, chain, multicall +from brownie import Contract, ZERO_ADDRESS, Wei, convert, chain, multicall from brownie.convert.datatypes import ReturnValue from tests.snapshot.utils import get_slot @@ -16,6 +16,21 @@ SIGNATURE_LENGTH = 96 DEPOSIT_SIZE = Wei("32 ether") RANDOM_SEED = datetime.now().timestamp() +NODE_OPERATORS_REGISTRY_MODULE_ID = 1 + +LEGACY_LIDO_DEPOSIT_ABI = [ + { + "inputs": [ + {"internalType": "uint256", "name": "_maxDepositsCount", "type": "uint256"}, + {"internalType": "uint256", "name": "_stakingModuleId", "type": "uint256"}, + {"internalType": "bytes", "name": "_depositCalldata", "type": "bytes"}, + ], + "name": "deposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function", + } +] def grant_roles(voting_eoa, agent_eoa): @@ -84,6 +99,26 @@ def test_node_operator_basic_flow( } def create_actions(dsm_eoa, manager_eoa): + def deposit(): + if contracts.lido.getContractVersion() < 4: + # In Lido v3, DSM calls Lido, which forwards ETH and the request + # to the StakingRouter. The v4 Lido ABI no longer exposes it. + legacy_lido = Contract.from_abi("LegacyLidoDeposit", contracts.lido.address, LEGACY_LIDO_DEPOSIT_ABI) + return legacy_lido.deposit( + deposits_count, + NODE_OPERATORS_REGISTRY_MODULE_ID, + "0x", + {"from": dsm_eoa}, + ) + + # In Lido v4, DSM calls the StakingRouter directly; it determines + # the actual deposit count from current allocation and module keys. + return contracts.staking_router.deposit( + NODE_OPERATORS_REGISTRY_MODULE_ID, + "0x", + {"from": dsm_eoa}, + ) + actions = { "add_node_operator": lambda: contracts.node_operators_registry.addNodeOperator( "new_node_operator", new_node_operator["reward_address"], {"from": manager_eoa} @@ -99,7 +134,7 @@ def create_actions(dsm_eoa, manager_eoa): new_node_operator["id"], new_node_operator["staking_limit"], {"from": manager_eoa} ), "submit": lambda: contracts.lido.submit(ZERO_ADDRESS, {"from": staker, "amount": submit_amount}), - "deposit": lambda: contracts.lido.deposit(deposits_count, 1, "0x", {"from": dsm_eoa}), + "deposit": deposit, "remove_signing_keys": lambda: contracts.node_operators_registry.removeSigningKeys( new_node_operator["id"], new_node_operator["staking_limit"], From d3600a6e45648bb1ea024e83f26b172f9b781272 Mon Sep 17 00:00:00 2001 From: KRogLA Date: Thu, 9 Jul 2026 22:53:33 +0200 Subject: [PATCH 18/30] test: exclude slots updated by mandatory oracle report before upgrade --- tests/snapshot/test_plain_submit.py | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/tests/snapshot/test_plain_submit.py b/tests/snapshot/test_plain_submit.py index b53ef739..a70723e2 100644 --- a/tests/snapshot/test_plain_submit.py +++ b/tests/snapshot/test_plain_submit.py @@ -20,6 +20,23 @@ from utils.test.helpers import ONE_ETH from utils.test.governance_helpers import execute_vote_and_process_dg_proposals +IGNORED_SNAPSHOT_KEYS = { + # Lido v4 finalization requires an AccountingOracle report. The report rebases + # stETH and v4 changes CL-accounting representation, so these values cannot be + # compared directly between the pre- and post-upgrade scenarios. + "totalSupply", + "getTotalPooledEther()", + "getBufferedEther()", + "getBeaconStat()", + "getTotalShares()", + "getSharesByPooledEth(1 ETH)", + "getTotalELRewardsCollected()", + "balanceOf(TREASURY)", + "sharesOf(TREASURY)", + "balanceOf(accounts[0])", + "sharesOf(accounts[0])", +} + @pytest.fixture(scope="module") def staker(): @@ -85,8 +102,7 @@ def steps() -> Dict[str, Dict[str, any]]: after: Dict[str, Dict[str, any]] = steps() step_diffs: Dict[str, Dict[str, ValueChanged]] = {} - expected_diffs = { - } + expected_diffs = {} for step, pair_of_snapshots in dict_zip(before, after).items(): (before, after) = pair_of_snapshots @@ -96,5 +112,8 @@ def steps() -> Dict[str, Dict[str, any]]: if key in step_diffs[step] and step_diffs[step][key] == expected_diffs[key]: del step_diffs[step][key] + for key in IGNORED_SNAPSHOT_KEYS: + step_diffs[step].pop(key, None) + for step_name, diff in step_diffs.items(): assert_no_diffs(step_name, diff) From da4f0fd7396e66713d4d50dac8d8dcc8a0db936d Mon Sep 17 00:00:00 2001 From: Anna Mukharram Date: Fri, 10 Jul 2026 02:10:39 +0400 Subject: [PATCH 19/30] fix: update target share via old method --- configs/config_mainnet.py | 1 - .../test_staking_router_stake_distribution.py | 29 +++++++------------ 2 files changed, 10 insertions(+), 20 deletions(-) diff --git a/configs/config_mainnet.py b/configs/config_mainnet.py index ab981981..3dde12d7 100644 --- a/configs/config_mainnet.py +++ b/configs/config_mainnet.py @@ -81,7 +81,6 @@ EASYTRACK_CURATED_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY = "0x4F716AD3Cc7A3A5cdA2359e5B2c84335c171dCde" EASYTRACK_SIMPLE_DVT_SUBMIT_VALIDATOR_EXIT_REQUEST_HASHES_FACTORY = "0x58A59dDC6Aea9b1D5743D024E15DfA4badB56E37" EASYTRACK_CS_SET_VETTED_GATE_TREE_FACTORY = "0xBc5642bDD6F2a54b01A75605aAe9143525D97308" -EASYTRACK_UPDATE_STAKING_MODULE_SHARE_LIMITS_FACTORY = "0xCF44d533A7766Ba299579eA0262fa61c0da81bA3" # SRV3 # Liquidity Observation Lab (LOL) stETH AllowedRecipientsRegistry LOL_ALLOWED_RECIPIENTS_REGISTRY = "0x48c4929630099b217136b64089E8543dB0E5163a" diff --git a/tests/regression/test_staking_router_stake_distribution.py b/tests/regression/test_staking_router_stake_distribution.py index 3d557e61..c1774e9d 100644 --- a/tests/regression/test_staking_router_stake_distribution.py +++ b/tests/regression/test_staking_router_stake_distribution.py @@ -2,11 +2,9 @@ from brownie import chain, interface -from utils.config import EASYTRACK_UPDATE_STAKING_MODULE_SHARE_LIMITS_FACTORY, contracts -from utils.evm_script import encode_call_script +from utils.config import contracts from utils.test.csm_helpers import csm_add_node_operator, fill_csm_operators_with_keys from utils.test.deposits_helpers import fill_deposit_buffer -from utils.test.easy_track_helpers import create_and_enact_motion from utils.test.simple_dvt_helpers import fill_simple_dvt_ops_vetted_keys from utils.test.staking_router_helpers import StakingModuleStatus @@ -274,22 +272,15 @@ def test_target_share_distribution(stranger): elif module.id == 3: fill_csm_operators_with_keys(3, min_keys_cnt) - motion_calldata = encode_call_script( - [ - ( - contracts.staking_router.address, - contracts.staking_router.updateModuleShares.encode_input( - module.id, target_share, module.priorityExitShareThreshold - ), - ) - ] - ) - create_and_enact_motion( - contracts.easy_track, - stranger, - EASYTRACK_UPDATE_STAKING_MODULE_SHARE_LIMITS_FACTORY, - motion_calldata, - stranger, + contracts.staking_router.updateStakingModule( + module.id, + target_share, + module.priorityExitShareThreshold, + module.module_fee, + module.treasury_fee, + module.maxDepositsPerBlock, + module.minDepositBlockDistance, + {"from": contracts.agent}, ) modules = get_modules_info(contracts.staking_router) From e6ae58820384abac2c999339e6a1d2581cb68767 Mon Sep 17 00:00:00 2001 From: Anna Mukharram Date: Fri, 10 Jul 2026 10:04:22 +0400 Subject: [PATCH 20/30] fix: top up gateway acceptance --- tests/acceptance/test_top_up_gateway.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/acceptance/test_top_up_gateway.py b/tests/acceptance/test_top_up_gateway.py index 81bf1922..ddea5086 100644 --- a/tests/acceptance/test_top_up_gateway.py +++ b/tests/acceptance/test_top_up_gateway.py @@ -56,7 +56,7 @@ def test_immutables(contract): assert contract.SLOTS_PER_EPOCH() == CHAIN_SLOTS_PER_EPOCH assert contract.PIVOT_SLOT() == 0 assert contract.GI_FIRST_VALIDATOR_PREV() == HexString( - "0x0000000000000000000000000000000000000000000000000056000000000028", "bytes" + "0x0000000000000000000000000000000000000000000000000096000000000028", "bytes" ) assert contract.GI_FIRST_VALIDATOR_CURR() == HexString( "0x0000000000000000000000000000000000000000000000000096000000000028", "bytes" From 9c9bedefed58dc908652bd1d8a053ec53f1fe467 Mon Sep 17 00:00:00 2001 From: Anna Mukharram Date: Fri, 10 Jul 2026 11:20:02 +0400 Subject: [PATCH 21/30] fix: test_pause_resume --- tests/regression/test_pause_resume.py | 79 ++++++++++++++++++++------- 1 file changed, 59 insertions(+), 20 deletions(-) diff --git a/tests/regression/test_pause_resume.py b/tests/regression/test_pause_resume.py index 987e94e4..410cb37d 100644 --- a/tests/regression/test_pause_resume.py +++ b/tests/regression/test_pause_resume.py @@ -8,6 +8,7 @@ from utils.evm_script import encode_error from utils.import_current_votes import is_there_any_vote_scripts, start_and_execute_votes from utils.staking_module import calc_module_reward_shares +from utils.test.deposits_helpers import fill_deposit_buffer from utils.test.oracle_report_helpers import oracle_report, prepare_exit_bus_report from utils.test.helpers import almostEqEth, almostEqWithDiff @@ -26,10 +27,18 @@ def burner() -> Contract: @pytest.fixture(scope="module", autouse=True) def agent_permission(): - contracts.acl.grantPermission(contracts.agent, contracts.lido, web3.keccak(text="PAUSE_ROLE"), {"from": contracts.agent}) - contracts.acl.grantPermission(contracts.agent, contracts.lido, web3.keccak(text="RESUME_ROLE"), {"from": contracts.agent}) - contracts.acl.grantPermission(contracts.agent, contracts.lido, web3.keccak(text="STAKING_PAUSE_ROLE"), {"from": contracts.agent}) - contracts.acl.grantPermission(contracts.agent, contracts.lido, web3.keccak(text="STAKING_CONTROL_ROLE"), {"from": contracts.agent}) + contracts.acl.grantPermission( + contracts.agent, contracts.lido, web3.keccak(text="PAUSE_ROLE"), {"from": contracts.agent} + ) + contracts.acl.grantPermission( + contracts.agent, contracts.lido, web3.keccak(text="RESUME_ROLE"), {"from": contracts.agent} + ) + contracts.acl.grantPermission( + contracts.agent, contracts.lido, web3.keccak(text="STAKING_PAUSE_ROLE"), {"from": contracts.agent} + ) + contracts.acl.grantPermission( + contracts.agent, contracts.lido, web3.keccak(text="STAKING_CONTROL_ROLE"), {"from": contracts.agent} + ) class StakingModuleStatus(IntEnum): @@ -209,9 +218,12 @@ def test_stopped_lido_cant_stake(stranger): @pytest.mark.usefixtures("stopped_lido") -def test_stopped_lido_cant_deposit(): +def test_stopped_lido_cant_withdraw_depositable_ether(stranger): + # withdrawDepositableEther is callable only by the StakingRouter (_auth check), + # but require(canDeposit()) is the first statement in its body, so on a stopped + # Lido any caller hits CAN_NOT_DEPOSIT before the auth check with brownie.reverts("CAN_NOT_DEPOSIT"): - contracts.lido.deposit(1, 1, "0x", {"from": contracts.deposit_security_module}), + contracts.lido.withdrawDepositableEther(1, 0, {"from": stranger}) def test_resumed_staking_can_stake(stranger): @@ -219,6 +231,7 @@ def test_resumed_staking_can_stake(stranger): contracts.lido.resumeStaking({"from": contracts.agent}) stranger.transfer(contracts.lido, DEPOSIT_AMOUNT) + @pytest.mark.usefixtures("stopped_lido") def test_cant_resume_staking_on_stopped_lido(): with brownie.reverts("CONTRACT_IS_STOPPED"): @@ -234,7 +247,34 @@ def test_resumed_lido_can_stake(stranger): @pytest.mark.usefixtures("stopped_lido") def test_resumed_lido_can_deposit(stranger): contracts.lido.resume({"from": contracts.agent}) - contracts.lido.deposit(1, 1, "0x", {"from": contracts.deposit_security_module}), + fill_deposit_buffer(1) + # min-first allocation gives the buffer to the least filled module, so the + # deposit goes to whichever module actually got a non-zero allocation + deposit_amount = contracts.lido.getDepositableEther() + module_id = next( + id + for id in contracts.staking_router.getStakingModuleIds() + if contracts.staking_router.getStakingModuleMaxDepositsCount(id, deposit_amount) > 0 + ) + contracts.staking_router.deposit(module_id, "0x", {"from": contracts.deposit_security_module}) + + +def test_cant_deposit_to_module_with_zero_allocation(): + deposit_amount = contracts.lido.getDepositableEther() + module_id = next( + ( + id + for id in contracts.staking_router.getStakingModuleIds() + if contracts.staking_router.getStakingModuleStatus(id) == StakingModuleStatus.Active + and contracts.staking_router.getStakingModuleMaxDepositsCount(id, deposit_amount) == 0 + ), + None, + ) + if module_id is None: + pytest.skip("every active staking module has a non-zero allocation") + + with brownie.reverts(encode_error("ZeroDeposits()")): + contracts.staking_router.deposit(module_id, "0x", {"from": contracts.deposit_security_module}) def test_paused_staking_can_report(): @@ -247,24 +287,24 @@ def test_paused_staking_can_report(): def test_paused_staking_module_cant_stake(stranger): contracts.staking_router.grantRole( - web3.keccak(text="STAKING_MODULE_MANAGE_ROLE"), - stranger, - {"from": contracts.agent}, - ) + web3.keccak(text="STAKING_MODULE_MANAGE_ROLE"), + stranger, + {"from": contracts.agent}, + ) contracts.staking_router.setStakingModuleStatus(1, StakingModuleStatus.DepositsPaused, {"from": stranger}) with brownie.reverts(encode_error("StakingModuleNotActive()")): - contracts.lido.deposit(1, 1, "0x", {"from": contracts.deposit_security_module}), + contracts.staking_router.deposit(1, "0x", {"from": contracts.deposit_security_module}) def test_paused_staking_module_can_reward(burner: Contract, stranger): _, module_address, *_ = contracts.staking_router.getStakingModule(1) contracts.staking_router.grantRole( - web3.keccak(text="STAKING_MODULE_MANAGE_ROLE"), - stranger, - {"from": contracts.agent}, - ) + web3.keccak(text="STAKING_MODULE_MANAGE_ROLE"), + stranger, + {"from": contracts.agent}, + ) contracts.staking_router.setStakingModuleStatus(1, StakingModuleStatus.DepositsPaused, {"from": stranger}) (report_tx, _) = oracle_report() @@ -275,7 +315,7 @@ def test_paused_staking_module_can_reward(burner: Contract, stranger): simple_dvt_index = 2 csm_index = 3 - if report_tx.events["TransferShares"][module_index-1]["to"] == burner.address: + if report_tx.events["TransferShares"][module_index - 1]["to"] == burner.address: module_index += 1 simple_dvt_index += 1 csm_index += 1 @@ -290,7 +330,6 @@ def test_paused_staking_module_can_reward(burner: Contract, stranger): assert report_tx.events["TransferShares"][agent_index]["to"] == contracts.agent assert report_tx.events["TransferShares"][agent_index]["from"] == contracts.accounting.address - # the staking modules ids starts from 1 module_stats = contracts.staking_router.getStakingModule(1) # module_treasury_fee = module_share / share_pct * treasury_pct @@ -382,7 +421,7 @@ def test_stopped_staking_module_cant_stake(stranger): contracts.staking_router.setStakingModuleStatus(1, StakingModuleStatus.Stopped, {"from": stranger}) with brownie.reverts(encode_error("StakingModuleNotActive()")): - contracts.lido.deposit(1, 1, "0x", {"from": contracts.deposit_security_module}), + contracts.staking_router.deposit(1, "0x", {"from": contracts.deposit_security_module}) def test_stopped_staking_module_cant_reward(stranger): @@ -498,4 +537,4 @@ def test_stopped_lido_can_exit_validators(stranger): contracts.lido.stop({"from": contracts.agent}) report, member = prepare_report() - contracts.validators_exit_bus_oracle.submitReportData(report, contract_version, {"from": member}) \ No newline at end of file + contracts.validators_exit_bus_oracle.submitReportData(report, contract_version, {"from": member}) From 2c9af44e0152c4fd8ea1e92f6e73d3d5e783f164 Mon Sep 17 00:00:00 2001 From: skhomuti Date: Fri, 10 Jul 2026 12:25:38 +0500 Subject: [PATCH 22/30] add curated module v2 helpers + adjust sr distribution tests --- .../test_staking_router_stake_distribution.py | 31 ++- utils/config.py | 20 ++ utils/test/csm_helpers.py | 4 +- utils/test/curated_v2_helpers.py | 181 ++++++++++++++++++ utils/test/merkle_tree.py | 16 +- 5 files changed, 236 insertions(+), 16 deletions(-) create mode 100644 utils/test/curated_v2_helpers.py diff --git a/tests/regression/test_staking_router_stake_distribution.py b/tests/regression/test_staking_router_stake_distribution.py index c1774e9d..21cb0077 100644 --- a/tests/regression/test_staking_router_stake_distribution.py +++ b/tests/regression/test_staking_router_stake_distribution.py @@ -2,8 +2,15 @@ from brownie import chain, interface -from utils.config import contracts +from utils.config import ( + CS_MODULE_ID, + CURATED_STAKING_MODULE_ID, + CURATED_V2_STAKING_MODULE_ID, + SIMPLE_DVT_MODULE_ID, + contracts, +) from utils.test.csm_helpers import csm_add_node_operator, fill_csm_operators_with_keys +from utils.test.curated_v2_helpers import ensure_curated_v2_depositable_keys from utils.test.deposits_helpers import fill_deposit_buffer from utils.test.simple_dvt_helpers import fill_simple_dvt_ops_vetted_keys from utils.test.staking_router_helpers import StakingModuleStatus @@ -166,12 +173,14 @@ def calc_allocation(modules: Dict[int, Module], deposit_amount: int, is_top_up: def assure_depositable_keys(stranger): modules = get_modules_info(contracts.staking_router) - if not modules[1].depositable_keys: + if not modules[CURATED_STAKING_MODULE_ID].depositable_keys: pass - if not modules[2].depositable_keys: + if not modules[SIMPLE_DVT_MODULE_ID].depositable_keys: fill_simple_dvt_ops_vetted_keys(stranger, 3, 5) - if not modules[3].depositable_keys: + if not modules[CS_MODULE_ID].depositable_keys: csm_add_node_operator(contracts.csm, contracts.cs_permissionless_gate, contracts.cs_accounting, stranger) + if not modules[CURATED_V2_STAKING_MODULE_ID].depositable_keys: + ensure_curated_v2_depositable_keys(5, stranger) def test_stake_distribution(stranger): @@ -240,8 +249,12 @@ def test_target_share_distribution(stranger): total_allocation = prep_modules_info(modules, deposit_size) # target module: the least filled active module which can be topped up with keys - # (no key onboarding helper for Curated Module v2 yet, so ids 2-3 only) - candidates = [m for m in modules.values() if m.status == StakingModuleStatus.Active.value and m.id in (2, 3)] + candidates = [ + m + for m in modules.values() + if m.status == StakingModuleStatus.Active.value + and m.id in (SIMPLE_DVT_MODULE_ID, CS_MODULE_ID, CURATED_V2_STAKING_MODULE_ID) + ] module = min(candidates, key=lambda m: m.current_allocation) module_idx = list(modules.keys()).index(module.id) @@ -267,10 +280,12 @@ def test_target_share_distribution(stranger): # so the share limit is the binding constraint, not the keys if module.depositable_keys < required_depositable_keys: min_keys_cnt = (required_depositable_keys + 2) // 3 - if module.id == 2: + if module.id == SIMPLE_DVT_MODULE_ID: fill_simple_dvt_ops_vetted_keys(stranger, 3, min_keys_cnt) - elif module.id == 3: + elif module.id == CS_MODULE_ID: fill_csm_operators_with_keys(3, min_keys_cnt) + elif module.id == CURATED_V2_STAKING_MODULE_ID: + ensure_curated_v2_depositable_keys(required_depositable_keys, stranger) contracts.staking_router.updateStakingModule( module.id, diff --git a/utils/config.py b/utils/config.py index 8347ac96..c0540699 100644 --- a/utils/config.py +++ b/utils/config.py @@ -210,6 +210,26 @@ def simple_dvt(self) -> interface.SimpleDVT: def csm(self) -> interface.CSModule: return interface.CSModule(CSM_ADDRESS) + @property + def cm(self) -> interface.CuratedModule: + return interface.CuratedModule(CM_MODULE_ADDRESS) + + @property + def cm_accounting(self) -> interface.ModuleAccounting: + return interface.ModuleAccounting(self.cm.ACCOUNTING()) + + @property + def cm_meta_registry(self) -> interface.MetaRegistry: + return interface.MetaRegistry(self.cm.META_REGISTRY()) + + @property + def cm_professional_operator_gate(self) -> interface.CuratedGate: + return interface.CuratedGate(CM_PROFESSIONAL_OPERATOR_GATE_ADDRESS) + + @property + def cm_parameters_registry(self) -> interface.ParametersRegistry: + return interface.ParametersRegistry(self.cm.PARAMETERS_REGISTRY()) + @property def cs_permissionless_gate(self) -> interface.PermissionlessGate: return interface.PermissionlessGate(CS_PERMISSIONLESS_GATE_ADDRESS) diff --git a/utils/test/csm_helpers.py b/utils/test/csm_helpers.py index db9787d0..13380ec7 100644 --- a/utils/test/csm_helpers.py +++ b/utils/test/csm_helpers.py @@ -5,12 +5,12 @@ from utils.test.helpers import ETH from utils.test.keys_helpers import random_pubkeys_batch, random_signatures_batch from utils.config import contracts, CSM_COMMITTEE_MS, EASYTRACK_CS_SET_VETTED_GATE_TREE_FACTORY -from utils.test.merkle_tree import ICSTree +from utils.test.merkle_tree import AddressTree def csm_set_ics_tree_members(members): - tree = ICSTree.new(members) + tree = AddressTree.new(members) calldata = _encode_calldata(["bytes32", "string"], [tree.root, "0xabc"]) tx = contracts.easy_track.createMotion(EASYTRACK_CS_SET_VETTED_GATE_TREE_FACTORY, calldata, {"from": CSM_COMMITTEE_MS}) chain.sleep(60 * 60 * 24 * 3) diff --git a/utils/test/curated_v2_helpers.py b/utils/test/curated_v2_helpers.py new file mode 100644 index 00000000..1cd5ddac --- /dev/null +++ b/utils/test/curated_v2_helpers.py @@ -0,0 +1,181 @@ +from brownie import ZERO_ADDRESS + +from utils.balance import set_balance_in_wei +from utils.config import contracts +from utils.test.helpers import ETH +from utils.test.keys_helpers import random_pubkeys_batch, random_signatures_batch +from utils.test.merkle_tree import AddressTree + +MAX_KEYS_BATCH_SIZE = 30 +DEFAULT_OPERATOR_WEIGHT = 10_000 +HELPER_ROLE_HOLDER = "0xce00000000000000000000000000000000000001" +GENERATED_NODE_OPERATOR_PREFIX = "cf" +TREE_EXTRA_MEMBER_PREFIX = "df" + + +def _get_role_member_or_grant(contract, role): + if contract.getRoleMemberCount(role) > 0: + return set_balance_in_wei(contract.getRoleMember(role, 0), ETH(10)) + + admin = set_balance_in_wei( + contract.getRoleMember(contract.DEFAULT_ADMIN_ROLE(), 0), + ETH(10), + ) + role_holder = set_balance_in_wei(HELPER_ROLE_HOLDER, ETH(10)) + contract.grantRole(role, role_holder, {"from": admin}) + return role_holder + + +def _ensure_meta_registry_setup(node_operator_id): + meta_registry = contracts.cm_meta_registry + + group_manager = _get_role_member_or_grant(meta_registry, meta_registry.MANAGE_OPERATOR_GROUPS_ROLE()) + + if meta_registry.getNodeOperatorGroupId(node_operator_id) == meta_registry.NO_GROUP_ID(): + meta_registry.createOrUpdateOperatorGroup( + meta_registry.NO_GROUP_ID(), + ( + "test", + [(node_operator_id, DEFAULT_OPERATOR_WEIGHT)], + [], + ), + {"from": group_manager}, + ) + + assert meta_registry.getNodeOperatorWeight(node_operator_id) > 0 + + +def _prepare_curated_gate(node_operator): + gate = contracts.cm_professional_operator_gate + tree_manager = _get_role_member_or_grant(gate, gate.SET_TREE_ROLE()) + + nonce = contracts.cm.getNodeOperatorsCount() + extra_member = f"0x{TREE_EXTRA_MEMBER_PREFIX}{nonce:038x}" + tree = AddressTree.new([node_operator.address, extra_member]) + tree_cid = f"ipfs://scripts-regression-cm-{nonce}" + + gate.setTreeParams(tree.root, tree_cid, {"from": tree_manager}) + proof = tree.get_proof(node_operator.address) + assert gate.verifyProof(node_operator, proof) + return gate, proof + + +def _get_fresh_node_operator(node_operator): + gate = contracts.cm_professional_operator_gate + if not gate.isConsumed(node_operator): + return node_operator + + nonce = contracts.cm.getNodeOperatorsCount() + while True: + candidate = f"0x{GENERATED_NODE_OPERATOR_PREFIX}{nonce:038x}" + if not gate.isConsumed(candidate): + return set_balance_in_wei(candidate, ETH(10)) + nonce += 1 + + +def _get_remaining_keys_capacity(node_operator_id): + module = contracts.cm + accounting = contracts.cm_accounting + parameters_registry = contracts.cm_parameters_registry + + curve_id = accounting.getBondCurveId(node_operator_id) + keys_limit = parameters_registry.getKeysLimit(curve_id) + non_withdrawn_keys = module.getNodeOperatorNonWithdrawnKeys(node_operator_id) + return max(keys_limit - non_withdrawn_keys, 0) + + +def curated_v2_upload_keys(node_operator_id, keys_count): + if keys_count <= 0: + return + + assert keys_count <= _get_remaining_keys_capacity(node_operator_id) + + module = contracts.cm + accounting = contracts.cm_accounting + node_operator = module.getNodeOperator(node_operator_id) + manager_address = node_operator["managerAddress"] + + remaining_keys = keys_count + while remaining_keys > 0: + batch_size = min(remaining_keys, MAX_KEYS_BATCH_SIZE) + value = accounting.getRequiredBondForNextKeys(node_operator_id, batch_size) + manager = set_balance_in_wei(manager_address, value + ETH(10)) + + module.addValidatorKeysETH( + manager_address, + node_operator_id, + batch_size, + random_pubkeys_batch(batch_size), + random_signatures_batch(batch_size), + {"from": manager, "value": value}, + ) + remaining_keys -= batch_size + + +def curated_v2_add_node_operator(node_operator, keys_count): + module = contracts.cm + gate, proof = _prepare_curated_gate(node_operator) + + node_operators_count_before = module.getNodeOperatorsCount() + gate.createNodeOperator( + "test", + "test", + ZERO_ADDRESS, + ZERO_ADDRESS, + proof, + {"from": node_operator}, + ) + assert module.getNodeOperatorsCount() == node_operators_count_before + 1 + + node_operator_id = node_operators_count_before + _ensure_meta_registry_setup(node_operator_id) + curated_v2_upload_keys(node_operator_id, keys_count) + assert module.getNodeOperator(node_operator_id)["depositableValidatorsCount"] >= keys_count + + return node_operator_id + + +def ensure_curated_v2_depositable_keys(required_depositable_keys, node_operator): + module = contracts.cm + meta_registry = contracts.cm_meta_registry + + module_depositable_keys = module.getStakingModuleSummary()["depositableValidatorsCount"] + if module_depositable_keys >= required_depositable_keys: + return + + # Prefer topping up an existing active operator without changing its group or share. + for node_operator_id in range(module.getNodeOperatorsCount()): + if not module.getNodeOperatorIsActive(node_operator_id): + continue + if meta_registry.getNodeOperatorWeight(node_operator_id) == 0: + continue + + remaining_keys_capacity = _get_remaining_keys_capacity(node_operator_id) + if remaining_keys_capacity == 0: + continue + + keys_to_add = min( + required_depositable_keys - module_depositable_keys, + remaining_keys_capacity, + ) + curated_v2_upload_keys( + node_operator_id, + keys_to_add, + ) + module_depositable_keys = module.getStakingModuleSummary()["depositableValidatorsCount"] + if module_depositable_keys >= required_depositable_keys: + return + + gate_curve_id = contracts.cm_professional_operator_gate.curveId() + keys_limit = contracts.cm_parameters_registry.getKeysLimit(gate_curve_id) + + while module_depositable_keys < required_depositable_keys: + node_operator = _get_fresh_node_operator(node_operator) + keys_to_add = min(required_depositable_keys - module_depositable_keys, keys_limit) + curated_v2_add_node_operator(node_operator, keys_to_add) + + updated_depositable_keys = module.getStakingModuleSummary()["depositableValidatorsCount"] + assert updated_depositable_keys > module_depositable_keys + module_depositable_keys = updated_depositable_keys + + assert module.getStakingModuleSummary()["depositableValidatorsCount"] >= required_depositable_keys diff --git a/utils/test/merkle_tree.py b/utils/test/merkle_tree.py index ed170293..a94490e5 100644 --- a/utils/test/merkle_tree.py +++ b/utils/test/merkle_tree.py @@ -16,7 +16,7 @@ Strikes: TypeAlias = list[int] RewardTreeLeaf: TypeAlias = tuple[NodeOperatorId, Shares] StrikesTreeLeaf: TypeAlias = tuple[NodeOperatorId, Pubkey, Strikes] -ICSTreeLeaf: TypeAlias = str +AddressTreeLeaf: TypeAlias = str class TreeJSONEncoder(json.JSONEncoder): @@ -320,10 +320,10 @@ def new(cls, values: Sequence[StrikesTreeLeaf]): @dataclass -class ICSTree: - """A wrapper around StandardMerkleTree to cover use cases of the CSM ICS Vetted Gate""" +class AddressTree: + """A StandardMerkleTree wrapper for Merkle gates with address leaves.""" - tree: StandardMerkleTree[ICSTreeLeaf] + tree: StandardMerkleTree[AddressTreeLeaf] @property def root(self) -> HexBytes: @@ -351,11 +351,15 @@ def encode(self) -> bytes: .encode() ) - def dump(self) -> Dump[ICSTreeLeaf]: + def dump(self) -> Dump[AddressTreeLeaf]: return self.tree.dump() + def get_proof(self, value: AddressTreeLeaf) -> list[HexBytes]: + leaf = self.tree.leaf([value]) + return [HexBytes(item) for item in self.tree.get_proof(self.tree.find(leaf))] + @classmethod - def new(cls, values: Sequence[ICSTreeLeaf]): + def new(cls, values: Sequence[AddressTreeLeaf]): """Create new instance around the wrapped tree out of the given values""" values = [[value] for value in values] return cls(StandardMerkleTree(values, ("address",))) From 7337150cfed46c0bfd18aaf7e8a2d631aedcf9ac Mon Sep 17 00:00:00 2001 From: KRogLA Date: Fri, 10 Jul 2026 12:25:33 +0200 Subject: [PATCH 23/30] fix: disable balance_check_middleware for snapshots --- tests/conftest.py | 20 +++++++++++++++++++- tests/snapshot/conftest.py | 9 +++++++++ tests/snapshot/test_lido_snapshot.py | 21 +++++++++++++++------ 3 files changed, 43 insertions(+), 7 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index a3b7bd2f..f8d73f6a 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,4 +1,5 @@ import json +from contextlib import contextmanager from typing import List import brownie.exceptions @@ -126,7 +127,10 @@ def execute_votes(accounts, vote_ids, dao_voting, topup="10 ether"): if accounts.at(holder_addr, force=True).balance() < topup: accounts[0].transfer(holder_addr, topup) account = accounts.at(holder_addr, force=True) - dao_voting.vote(vote_id, True, False, {"from": account}) + # Voting accounts are topped up above, so bypass the middleware + # that temporarily replaces their balances and then restores them. + with without_balance_check_middleware(): + dao_voting.vote(vote_id, True, False, {"from": account}) # wait for the vote to end # time_to_end = dao_voting.getVote(vote_id)["startDate"] + get_vote_duration() - chain.time() @@ -327,6 +331,20 @@ def middleware(method, params): return middleware +@contextmanager +def without_balance_check_middleware(): + middleware = web3.middleware_onion.get("balance_check") + if middleware is None: + yield + return + + web3.middleware_onion.remove("balance_check") + try: + yield + finally: + web3.middleware_onion.add(middleware, name="balance_check") + + def get_active_proposals_from_env() -> [int]: if os.getenv(ENV_DG_PROPOSAL_IDS): try: diff --git a/tests/snapshot/conftest.py b/tests/snapshot/conftest.py index 08d2c47a..32eb21dd 100644 --- a/tests/snapshot/conftest.py +++ b/tests/snapshot/conftest.py @@ -1,7 +1,16 @@ import pytest +from tests.conftest import without_balance_check_middleware from utils.import_current_votes import is_there_any_upgrade_scripts + +@pytest.fixture(scope="function", autouse=True) +def disable_balance_check_for_snapshot_tests(): + """Snapshot tests must retain the senders' real balances after each transaction.""" + with without_balance_check_middleware(): + yield + + @pytest.fixture(scope="function", autouse=True) def skip_if_there_no_upgrade_scripts(): if not is_there_any_upgrade_scripts(): diff --git a/tests/snapshot/test_lido_snapshot.py b/tests/snapshot/test_lido_snapshot.py index f59f03e5..e3dd5358 100644 --- a/tests/snapshot/test_lido_snapshot.py +++ b/tests/snapshot/test_lido_snapshot.py @@ -10,9 +10,11 @@ from web3.types import Wei from tests.conftest import Helpers +from utils.balance import set_balance from utils.config import contracts, LDO_TOKEN, VOTING, AGENT, INITIAL_MAX_EXTERNAL_RATIO_BP from utils.evm_script import EMPTY_CALLSCRIPT from utils.test.governance_helpers import execute_vote_and_process_dg_proposals +from utils.test.helpers import ETH from utils.test.snapshot_helpers import _chain_snapshot from .utils import get_slot @@ -64,6 +66,16 @@ class Frame(TypedDict): } +@pytest.fixture(scope="function", autouse=True) +def fund_lido_snapshot_senders(eth_whale: Account, some_contract: Account, stranger: Account): + """Fund impersonated external senders without relying on balance middleware.""" + funding_balance = ETH(100_000) + set_balance(eth_whale.address, funding_balance) + set_balance(some_contract.address, funding_balance) + set_balance(stranger.address, funding_balance) + set_balance(contracts.execution_layer_rewards_vault.address, funding_balance) + + def test_lido_no_changes_in_views(sandwich_upgrade: SandwichFn): """Test that no views change during the upgrade process.""" @@ -88,12 +100,9 @@ def test_lido_end_user_snapshot( actions = ( # send ether to Lido to mint stETH _call( - web3.eth.send_transaction, - { - "from": eth_whale.address, - "to": lido.address, - "value": Wei(eth_amount // 2), - }, + eth_whale.transfer, + lido.address, + Wei(eth_amount // 2), ), _call( lido.submit, From 3268630bea0cc07d32198c811b85f3d24a3c6155 Mon Sep 17 00:00:00 2001 From: Anna Mukharram Date: Fri, 10 Jul 2026 14:37:19 +0400 Subject: [PATCH 24/30] fix: permissions tests --- configs/config_mainnet.py | 2 +- tests/regression/test_permissions.py | 218 ++++++++++++++++++--------- 2 files changed, 146 insertions(+), 74 deletions(-) diff --git a/configs/config_mainnet.py b/configs/config_mainnet.py index 0d2ade2d..e306990a 100644 --- a/configs/config_mainnet.py +++ b/configs/config_mainnet.py @@ -379,7 +379,7 @@ TOP_UP_GATEWAY_TARGET_BALANCE_GWEI = 2_046_750_000_000 # 2046.75 ETH (1.25 ETH margin below MaxEB) TOP_UP_GATEWAY_MIN_TOP_UP_GWEI = 2_000_000_000 # 2 ETH # sole TOP_UP_ROLE holder (coreUpgrade.topUpGatewayDepositor, stable deploy input) -TOP_UP_GATEWAY_DEPOSITOR = "0xF82aC5937A20dC862F9bc0668779031E06000f17" +TOP_UP_GATEWAY_DEPOSITOR = "0x57Cc953D3d27E7E8bAd04566bfd4Cd416c3B0855" # CircuitBreaker — TW-upgrade pause hub; the SRv3 vote registers it as pauser for the new gateways CIRCUIT_BREAKER = "0x6019CB557978296BA3C08a7B73225C0975DFB2F7" diff --git a/tests/regression/test_permissions.py b/tests/regression/test_permissions.py index 02ebe2df..a4c2020f 100644 --- a/tests/regression/test_permissions.py +++ b/tests/regression/test_permissions.py @@ -61,6 +61,12 @@ CS_ORACLE_HASH_CONSENSUS_ADDRESS, CS_PERMISSIONLESS_GATE_ADDRESS, TRIGGERABLE_WITHDRAWALS_GATEWAY, + TOP_UP_GATEWAY, + TOP_UP_GATEWAY_DEPOSITOR, + CONSOLIDATION_GATEWAY, + CONSOLIDATION_BUS, + CONSOLIDATION_MIGRATOR, + CONSOLIDATION_COMMITTEE, VEB_TWG_GATE_SEAL, CS_VETTED_GATE_ADDRESS, CS_PARAMS_REGISTRY_ADDRESS, @@ -81,7 +87,7 @@ GATE_SEAL_V3, L1_TOKEN_RATE_NOTIFIER, STAKING_VAULT_BEACON, - TWO_PHASE_FRAME_CONFIG_UPDATE + TWO_PHASE_FRAME_CONFIG_UPDATE, ) @@ -90,18 +96,12 @@ def protocol_permissions(): is_csm_v3 = contracts.csm.getInitializedVersion() >= 3 csm_pause_manager = CIRCUIT_BREAKER cs_ejector_address = CS_EJECTOR_V3_ADDRESS if is_csm_v3 else CS_EJECTOR_ADDRESS - cs_permissionless_gate_address = ( - CS_PERMISSIONLESS_GATE_V3_ADDRESS if is_csm_v3 else CS_PERMISSIONLESS_GATE_ADDRESS - ) + cs_permissionless_gate_address = CS_PERMISSIONLESS_GATE_V3_ADDRESS if is_csm_v3 else CS_PERMISSIONLESS_GATE_ADDRESS cs_verifier = ( - interface.Verifier(CS_VERIFIER_V3_ADDRESS) - if is_csm_v3 - else interface.CSVerifierV2(CS_VERIFIER_V2_ADDRESS) + interface.Verifier(CS_VERIFIER_V3_ADDRESS) if is_csm_v3 else interface.CSVerifierV2(CS_VERIFIER_V2_ADDRESS) ) cs_verifier_address = cs_verifier.address - burner_request_burn_my_steth_holders = ( - [CS_ACCOUNTING_ADDRESS, CM_ACCOUNTING_ADDRESS] if is_csm_v3 else [] - ) + burner_request_burn_my_steth_holders = [CS_ACCOUNTING_ADDRESS, CM_ACCOUNTING_ADDRESS] if is_csm_v3 else [] burner_request_burn_shares_holders = [contracts.accounting] if not is_csm_v3: burner_request_burn_shares_holders.append(CS_ACCOUNTING_ADDRESS) @@ -126,37 +126,43 @@ def protocol_permissions(): "RECOVERER_ROLE": [], } if is_csm_v3: - csm_roles.update({ - "MANAGE_TOP_UP_QUEUE_ROLE": [], - "REWIND_TOP_UP_QUEUE_ROLE": [], - "OPERATOR_ADDRESSES_ADMIN_ROLE": [], - "REPORT_GENERAL_DELAYED_PENALTY_ROLE": [CSM_COMMITTEE_MS], - "SETTLE_GENERAL_DELAYED_PENALTY_ROLE": [EASYTRACK_EVMSCRIPT_EXECUTOR], - "REPORT_REGULAR_WITHDRAWN_VALIDATORS_ROLE": [cs_verifier_address], - "REPORT_SLASHED_WITHDRAWN_VALIDATORS_ROLE": [EASYTRACK_EVMSCRIPT_EXECUTOR], - }) + csm_roles.update( + { + "MANAGE_TOP_UP_QUEUE_ROLE": [], + "REWIND_TOP_UP_QUEUE_ROLE": [], + "OPERATOR_ADDRESSES_ADMIN_ROLE": [], + "REPORT_GENERAL_DELAYED_PENALTY_ROLE": [CSM_COMMITTEE_MS], + "SETTLE_GENERAL_DELAYED_PENALTY_ROLE": [EASYTRACK_EVMSCRIPT_EXECUTOR], + "REPORT_REGULAR_WITHDRAWN_VALIDATORS_ROLE": [cs_verifier_address], + "REPORT_SLASHED_WITHDRAWN_VALIDATORS_ROLE": [EASYTRACK_EVMSCRIPT_EXECUTOR], + } + ) csm_ignored_abi_roles = set() if not is_csm_v3: - csm_ignored_abi_roles.update({ - "MANAGE_TOP_UP_QUEUE_ROLE", - "REWIND_TOP_UP_QUEUE_ROLE", - "OPERATOR_ADDRESSES_ADMIN_ROLE", - "REPORT_GENERAL_DELAYED_PENALTY_ROLE", - "SETTLE_GENERAL_DELAYED_PENALTY_ROLE", - "REPORT_REGULAR_WITHDRAWN_VALIDATORS_ROLE", - "REPORT_SLASHED_WITHDRAWN_VALIDATORS_ROLE", - }) + csm_ignored_abi_roles.update( + { + "MANAGE_TOP_UP_QUEUE_ROLE", + "REWIND_TOP_UP_QUEUE_ROLE", + "OPERATOR_ADDRESSES_ADMIN_ROLE", + "REPORT_GENERAL_DELAYED_PENALTY_ROLE", + "SETTLE_GENERAL_DELAYED_PENALTY_ROLE", + "REPORT_REGULAR_WITHDRAWN_VALIDATORS_ROLE", + "REPORT_SLASHED_WITHDRAWN_VALIDATORS_ROLE", + } + ) csm_role_preimages = { "REPORT_EL_REWARDS_STEALING_PENALTY_ROLE": "REPORT_EL_REWARDS_STEALING_PENALTY_ROLE", "SETTLE_EL_REWARDS_STEALING_PENALTY_ROLE": "SETTLE_EL_REWARDS_STEALING_PENALTY_ROLE", } if is_csm_v3: - csm_role_preimages.update({ - "REPORT_GENERAL_DELAYED_PENALTY_ROLE": "REPORT_GENERAL_DELAYED_PENALTY_ROLE", - "SETTLE_GENERAL_DELAYED_PENALTY_ROLE": "SETTLE_GENERAL_DELAYED_PENALTY_ROLE", - "REPORT_REGULAR_WITHDRAWN_VALIDATORS_ROLE": "REPORT_REGULAR_WITHDRAWN_VALIDATORS_ROLE", - "REPORT_SLASHED_WITHDRAWN_VALIDATORS_ROLE": "REPORT_SLASHED_WITHDRAWN_VALIDATORS_ROLE", - }) + csm_role_preimages.update( + { + "REPORT_GENERAL_DELAYED_PENALTY_ROLE": "REPORT_GENERAL_DELAYED_PENALTY_ROLE", + "SETTLE_GENERAL_DELAYED_PENALTY_ROLE": "SETTLE_GENERAL_DELAYED_PENALTY_ROLE", + "REPORT_REGULAR_WITHDRAWN_VALIDATORS_ROLE": "REPORT_REGULAR_WITHDRAWN_VALIDATORS_ROLE", + "REPORT_SLASHED_WITHDRAWN_VALIDATORS_ROLE": "REPORT_SLASHED_WITHDRAWN_VALIDATORS_ROLE", + } + ) vetted_gate_roles = { "DEFAULT_ADMIN_ROLE": [contracts.agent], "PAUSE_ROLE": [csm_pause_manager, RESEAL_MANAGER], @@ -165,16 +171,20 @@ def protocol_permissions(): "SET_TREE_ROLE": [EASYTRACK_EVMSCRIPT_EXECUTOR], } if not is_csm_v3: - vetted_gate_roles.update({ - "START_REFERRAL_SEASON_ROLE": [contracts.agent], - "END_REFERRAL_SEASON_ROLE": [CSM_COMMITTEE_MS], - }) + vetted_gate_roles.update( + { + "START_REFERRAL_SEASON_ROLE": [contracts.agent], + "END_REFERRAL_SEASON_ROLE": [CSM_COMMITTEE_MS], + } + ) vetted_gate_role_preimages = {} if not is_csm_v3: - vetted_gate_role_preimages.update({ - "START_REFERRAL_SEASON_ROLE": "START_REFERRAL_SEASON_ROLE", - "END_REFERRAL_SEASON_ROLE": "END_REFERRAL_SEASON_ROLE", - }) + vetted_gate_role_preimages.update( + { + "START_REFERRAL_SEASON_ROLE": "START_REFERRAL_SEASON_ROLE", + "END_REFERRAL_SEASON_ROLE": "END_REFERRAL_SEASON_ROLE", + } + ) cs_parameters_registry_roles = { "DEFAULT_ADMIN_ROLE": [contracts.agent], "MANAGE_GENERAL_PENALTIES_AND_CHARGES_ROLE": [CSM_COMMITTEE_MS] if is_csm_v3 else [], @@ -214,6 +224,7 @@ def protocol_permissions(): "MANAGE_WITHDRAWAL_CREDENTIALS_ROLE": [], "STAKING_MODULE_UNVETTING_ROLE": [contracts.deposit_security_module], "STAKING_MODULE_MANAGE_ROLE": [contracts.agent], + "STAKING_MODULE_SHARE_MANAGE_ROLE": [EASYTRACK_EVMSCRIPT_EXECUTOR], "REPORT_EXITED_VALIDATORS_ROLE": [contracts.accounting_oracle], "UNSAFE_SET_EXITED_VALIDATORS_ROLE": [], "REPORT_REWARDS_MINTED_ROLE": [contracts.accounting], @@ -375,6 +386,7 @@ def protocol_permissions(): "RESUME_ROLE": [], "STAKING_PAUSE_ROLE": [], "UNSAFE_CHANGE_DEPOSITED_VALIDATORS_ROLE": [], + "BUFFER_RESERVE_MANAGER_ROLE": [contracts.agent], }, }, AGENT: { @@ -512,7 +524,7 @@ def protocol_permissions(): "DEFAULT_ADMIN_ROLE": [contracts.agent], "PAUSE_ROLE": [csm_pause_manager, RESEAL_MANAGER], "RESUME_ROLE": [RESEAL_MANAGER], - } + }, }, CS_PARAMS_REGISTRY_ADDRESS: { "contract_name": "ParametersRegistry", @@ -539,7 +551,7 @@ def protocol_permissions(): "PAUSE_ROLE": [csm_pause_manager, RESEAL_MANAGER], "RESUME_ROLE": [RESEAL_MANAGER], "RECOVERER_ROLE": [], - } + }, }, CS_VETTED_GATE_ADDRESS: { "contract_name": "VettedGate", @@ -556,9 +568,57 @@ def protocol_permissions(): "roles": { "DEFAULT_ADMIN_ROLE": [contracts.agent], "RECOVERER_ROLE": [], - } + }, }, # TODO: add Curated Module v2 permission matrix once scripts has CMv2 interfaces and config bindings. + TOP_UP_GATEWAY: { + "contract_name": "TopUpGateway", + "contract": interface.TopUpGateway(TOP_UP_GATEWAY), + "type": "CustomApp", + "proxy_owner": contracts.agent, + "roles": { + "DEFAULT_ADMIN_ROLE": [contracts.agent], + "PAUSE_ROLE": [CIRCUIT_BREAKER, RESEAL_MANAGER], + "RESUME_ROLE": [RESEAL_MANAGER], + "TOP_UP_ROLE": [TOP_UP_GATEWAY_DEPOSITOR], + "MANAGE_LIMITS_ROLE": [], + }, + }, + CONSOLIDATION_GATEWAY: { + "contract_name": "ConsolidationGateway", + "contract": interface.ConsolidationGateway(CONSOLIDATION_GATEWAY), + "type": "CustomApp", + "roles": { + "DEFAULT_ADMIN_ROLE": [contracts.agent], + "PAUSE_ROLE": [CIRCUIT_BREAKER, RESEAL_MANAGER], + "RESUME_ROLE": [RESEAL_MANAGER], + "ADD_CONSOLIDATION_REQUEST_ROLE": [CONSOLIDATION_BUS], + "EXIT_LIMIT_MANAGER_ROLE": [], + }, + }, + CONSOLIDATION_BUS: { + "contract_name": "ConsolidationBus", + "contract": interface.ConsolidationBus(CONSOLIDATION_BUS), + "type": "CustomApp", + "proxy_owner": contracts.agent, + "roles": { + "DEFAULT_ADMIN_ROLE": [contracts.agent], + "PUBLISH_ROLE": [CONSOLIDATION_MIGRATOR], + "REMOVE_ROLE": [CONSOLIDATION_COMMITTEE], + "MANAGE_ROLE": [], + }, + }, + CONSOLIDATION_MIGRATOR: { + "contract_name": "ConsolidationMigrator", + "contract": interface.ConsolidationMigrator(CONSOLIDATION_MIGRATOR), + "type": "CustomApp", + "proxy_owner": contracts.agent, + "roles": { + "DEFAULT_ADMIN_ROLE": [contracts.agent], + "ALLOW_PAIR_ROLE": [EASYTRACK_EVMSCRIPT_EXECUTOR], + "DISALLOW_PAIR_ROLE": [CONSOLIDATION_COMMITTEE], + }, + }, TRIGGERABLE_WITHDRAWALS_GATEWAY: { "contract_name": "TriggerableWithdrawalsGateway", "contract": contracts.triggerable_withdrawals_gateway, @@ -568,8 +628,8 @@ def protocol_permissions(): "ADD_FULL_WITHDRAWAL_REQUEST_ROLE": twg_full_withdrawal_request_holders, "PAUSE_ROLE": [csm_pause_manager, RESEAL_MANAGER], "RESUME_ROLE": [RESEAL_MANAGER], - "TW_EXIT_LIMIT_MANAGER_ROLE": [], - } + "TW_EXIT_LIMIT_MANAGER_ROLE": [contracts.agent], + }, }, INSURANCE_FUND: { "contract_name": "InsuranceFund", @@ -704,15 +764,15 @@ def test_protocol_permissions(protocol_permissions): roles = permissions_config["roles"] - assert (abi_roles - ignored_abi_roles).issubset(configured_roles), ( - "Contract {} has undescribed ABI roles {}".format( - permissions_config["contract_name"], abi_roles - configured_roles - ignored_abi_roles - ) + assert (abi_roles - ignored_abi_roles).issubset( + configured_roles + ), "Contract {} has undescribed ABI roles {}".format( + permissions_config["contract_name"], abi_roles - configured_roles - ignored_abi_roles ) - assert configured_roles.issubset(abi_roles | custom_role_preimages), ( - "Contract {} has configured roles absent from ABI and role_preimages {}".format( - permissions_config["contract_name"], configured_roles - abi_roles - custom_role_preimages - ) + assert configured_roles.issubset( + abi_roles | custom_role_preimages + ), "Contract {} has configured roles absent from ABI and role_preimages {}".format( + permissions_config["contract_name"], configured_roles - abi_roles - custom_role_preimages ) if permissions_config["type"] == "AragonApp": @@ -746,7 +806,9 @@ def test_protocol_permissions(protocol_permissions): if "role_preimages" in permissions_config and role in permissions_config["role_preimages"]: role_preimage = permissions_config["role_preimages"][role] - role_keccak = web3.keccak(text=role_preimage).hex() if role != "DEFAULT_ADMIN_ROLE" else ZERO_BYTES32.hex() + role_keccak = ( + web3.keccak(text=role_preimage).hex() if role != "DEFAULT_ADMIN_ROLE" else ZERO_BYTES32.hex() + ) if role in permissions_config["contract"].signatures: role_signature = permissions_config["contract"].signatures[role] @@ -755,11 +817,17 @@ def test_protocol_permissions(protocol_permissions): try: role_member_count = permissions_config["contract"].getRoleMemberCount(role_keccak) except Exception as e: - print("Unable to count role members for {0} at {1}: {2}".format(role, permissions_config["contract_name"], e)) + print( + "Unable to count role members for {0} at {1}: {2}".format( + role, permissions_config["contract_name"], e + ) + ) role_member_count = None finally: if role_member_count is not None: - assert role_member_count == len(holders), "number of {0} role holders in contract {1} mismatched".format( + assert role_member_count == len( + holders + ), "number of {0} role holders in contract {1} mismatched".format( role, permissions_config["contract_name"] ) @@ -816,17 +884,17 @@ def assert_curated_manage_signing_keys_permission(permissions_config, current_ho assert_expected_role_holders(role, expected_holders, current_holders, contract_name) for holder in current_holders: - assert not contracts.acl.hasPermission(holder, contract_address, role_hash), ( - "Unexpected unparameterized {} holder {} at {}".format(role, holder, contract_name) - ) + assert not contracts.acl.hasPermission( + holder, contract_address, role_hash + ), "Unexpected unparameterized {} holder {} at {}".format(role, holder, contract_name) for node_operator_id, holder in CURATED_MANAGE_SIGNING_KEYS_HOLDERS.items(): expected_params = [Param(0, Op.EQ, ArgumentValue(node_operator_id))] actual_params = get_acl_permission_params(holder, contract_address, role_hash) - assert actual_params == expected_params, ( - "Unexpected params for {} holder {} at {}. expected {}, actual {}".format( - role, holder, contract_name, expected_params, actual_params - ) + assert ( + actual_params == expected_params + ), "Unexpected params for {} holder {} at {}. expected {}, actual {}".format( + role, holder, contract_name, expected_params, actual_params ) @@ -866,7 +934,7 @@ def get_http_w3_provider_url(): if os.getenv("ETH_RPC_URL") is not None: return os.getenv("ETH_RPC_URL") - assert False, 'Web3 HTTP Provider token env var not found' + assert False, "Web3 HTTP Provider token env var not found" def get_http_provider_timeout(): @@ -906,18 +974,22 @@ def fetch_events_in_batches(start_block, end_block, provider=local_rpc_provider, for batch_start in range(start_block, end_block, step): batch_end = min(batch_start + step - 1, end_block) - batch_events = provider.eth.get_logs({ - "address": contracts.acl.address, - "fromBlock": batch_start, - "toBlock": batch_end, - "topics": [event_signature_hash], - }) + batch_events = provider.eth.get_logs( + { + "address": contracts.acl.address, + "fromBlock": batch_start, + "toBlock": batch_end, + "topics": [event_signature_hash], + } + ) events.extend(batch_events) pbar.update(1) return events - events_before_voting = fetch_events_in_batches(ACL_DEPLOY_BLOCK_NUMBER, remote_rpc_provider.eth.block_number, remote_rpc_provider) + events_before_voting = fetch_events_in_batches( + ACL_DEPLOY_BLOCK_NUMBER, remote_rpc_provider.eth.block_number, remote_rpc_provider + ) permission_events = _decode_logs(events_before_voting)["SetPermission"]._ordered From 9991535ab1df3a1f05ada4dcc55712b3497118eb Mon Sep 17 00:00:00 2001 From: KRogLA Date: Fri, 10 Jul 2026 16:37:36 +0200 Subject: [PATCH 25/30] fix: refactor and temp bypass deposit in nor snapshot test --- .../snapshot/test_node_operators_registry.py | 88 ++++--------------- 1 file changed, 18 insertions(+), 70 deletions(-) diff --git a/tests/snapshot/test_node_operators_registry.py b/tests/snapshot/test_node_operators_registry.py index bfe0b039..d8e20fc3 100644 --- a/tests/snapshot/test_node_operators_registry.py +++ b/tests/snapshot/test_node_operators_registry.py @@ -3,7 +3,7 @@ from web3 import Web3 from datetime import datetime from typing import Any, Dict, Callable -from brownie import Contract, ZERO_ADDRESS, Wei, convert, chain, multicall +from brownie import ZERO_ADDRESS, Wei, convert, chain, multicall from brownie.convert.datatypes import ReturnValue from tests.snapshot.utils import get_slot @@ -18,28 +18,15 @@ RANDOM_SEED = datetime.now().timestamp() NODE_OPERATORS_REGISTRY_MODULE_ID = 1 -LEGACY_LIDO_DEPOSIT_ABI = [ - { - "inputs": [ - {"internalType": "uint256", "name": "_maxDepositsCount", "type": "uint256"}, - {"internalType": "uint256", "name": "_stakingModuleId", "type": "uint256"}, - {"internalType": "bytes", "name": "_depositCalldata", "type": "bytes"}, - ], - "name": "deposit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function", - } -] - - -def grant_roles(voting_eoa, agent_eoa): - contracts.staking_router.grantRole( - contracts.staking_router.MANAGE_WITHDRAWAL_CREDENTIALS_ROLE(), voting_eoa, {"from": agent_eoa} - ) - +def grant_roles(agent_eoa): + # contracts.acl.grantPermission( + # contracts.agent, + # contracts.node_operators_registry, + # convert.to_uint(Web3.keccak(text="MANAGE_SIGNING_KEYS")), + # {"from": contracts.agent}, + # ) contracts.acl.grantPermission( - contracts.voting, + agent_eoa, contracts.node_operators_registry, convert.to_uint(Web3.keccak(text="MANAGE_NODE_OPERATOR_ROLE")), {"from": agent_eoa}, @@ -69,16 +56,10 @@ def new_deposit_security_module_eoa(accounts, EtherFunder): return accounts.at(DEPOSIT_SECURITY_MODULE, force=True) -@pytest.fixture(scope="module") -def voting_eoa(accounts): - return accounts.at(contracts.voting.address, force=True) - - def test_node_operator_basic_flow( accounts, helpers, new_deposit_security_module_eoa, - voting_eoa, agent_eoa, vote_ids_from_env, dg_proposal_ids_from_env, @@ -99,25 +80,6 @@ def test_node_operator_basic_flow( } def create_actions(dsm_eoa, manager_eoa): - def deposit(): - if contracts.lido.getContractVersion() < 4: - # In Lido v3, DSM calls Lido, which forwards ETH and the request - # to the StakingRouter. The v4 Lido ABI no longer exposes it. - legacy_lido = Contract.from_abi("LegacyLidoDeposit", contracts.lido.address, LEGACY_LIDO_DEPOSIT_ABI) - return legacy_lido.deposit( - deposits_count, - NODE_OPERATORS_REGISTRY_MODULE_ID, - "0x", - {"from": dsm_eoa}, - ) - - # In Lido v4, DSM calls the StakingRouter directly; it determines - # the actual deposit count from current allocation and module keys. - return contracts.staking_router.deposit( - NODE_OPERATORS_REGISTRY_MODULE_ID, - "0x", - {"from": dsm_eoa}, - ) actions = { "add_node_operator": lambda: contracts.node_operators_registry.addNodeOperator( @@ -134,7 +96,14 @@ def deposit(): new_node_operator["id"], new_node_operator["staking_limit"], {"from": manager_eoa} ), "submit": lambda: contracts.lido.submit(ZERO_ADDRESS, {"from": staker, "amount": submit_amount}), - "deposit": deposit, + # In Lido v4, DSM calls the StakingRouter directly; it determines + # the actual deposit count from current allocation and module keys. + # TODO: uncomment after SRV# upgrade, as it don't work on this upgrade + # "deposit": lambda: contracts.staking_router.deposit( + # 1, + # "0x", + # {"from": dsm_eoa}, + # ), "remove_signing_keys": lambda: contracts.node_operators_registry.removeSigningKeys( new_node_operator["id"], new_node_operator["staking_limit"], @@ -154,9 +123,7 @@ def deposit(): snapshot_before_update = {} snapshot_after_update = {} - grant_roles(voting_eoa, agent_eoa) - - make_snapshot(contracts.node_operators_registry) + grant_roles(agent_eoa) with chain_snapshot(): snapshot_before_update = run_scenario( @@ -166,25 +133,6 @@ def deposit(): with chain_snapshot(): execute_vote_and_process_dg_proposals(helpers, vote_ids_from_env, dg_proposal_ids_from_env) - contracts.acl.grantPermission( - contracts.agent, - contracts.node_operators_registry, - convert.to_uint(Web3.keccak(text="MANAGE_NODE_OPERATOR_ROLE")), - {"from": contracts.agent}, - ) - contracts.acl.grantPermission( - contracts.agent, - contracts.node_operators_registry, - convert.to_uint(Web3.keccak(text="SET_NODE_OPERATOR_LIMIT_ROLE")), - {"from": contracts.agent}, - ) - contracts.acl.grantPermission( - contracts.agent, - contracts.node_operators_registry, - convert.to_uint(Web3.keccak(text="MANAGE_SIGNING_KEYS")), - {"from": contracts.agent}, - ) - snapshot_after_update = run_scenario( actions=create_actions(new_deposit_security_module_eoa, agent_eoa), snapshooter=make_snapshot ) From 87fafd65535f6f22935c70a317a2f7a77e3d4387 Mon Sep 17 00:00:00 2001 From: KRogLA Date: Fri, 10 Jul 2026 16:41:47 +0200 Subject: [PATCH 26/30] chore: del commented code --- tests/snapshot/test_node_operators_registry.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/tests/snapshot/test_node_operators_registry.py b/tests/snapshot/test_node_operators_registry.py index d8e20fc3..a9c7caec 100644 --- a/tests/snapshot/test_node_operators_registry.py +++ b/tests/snapshot/test_node_operators_registry.py @@ -19,12 +19,6 @@ NODE_OPERATORS_REGISTRY_MODULE_ID = 1 def grant_roles(agent_eoa): - # contracts.acl.grantPermission( - # contracts.agent, - # contracts.node_operators_registry, - # convert.to_uint(Web3.keccak(text="MANAGE_SIGNING_KEYS")), - # {"from": contracts.agent}, - # ) contracts.acl.grantPermission( agent_eoa, contracts.node_operators_registry, @@ -68,8 +62,6 @@ def test_node_operator_basic_flow( submit_amount = deposits_count * DEPOSIT_SIZE staker, _ = accounts[0], accounts[1] - # new_node_operator_id = contracts.node_operators_registry_v1.getNodeOperatorsCount() - # new_node_operator_validators_count = 10 new_node_operator = { "id": contracts.node_operators_registry.getNodeOperatorsCount(), "reward_address": accounts[3].address, From 551164f1bba893eac0752d30c29fc6ea4ba896d9 Mon Sep 17 00:00:00 2001 From: KRogLA Date: Fri, 10 Jul 2026 16:56:04 +0200 Subject: [PATCH 27/30] fix: test accounts fund --- tests/snapshot/test_voting.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/snapshot/test_voting.py b/tests/snapshot/test_voting.py index 905bfeab..f5e35191 100644 --- a/tests/snapshot/test_voting.py +++ b/tests/snapshot/test_voting.py @@ -14,6 +14,10 @@ contracts, ) from utils.test.governance_helpers import execute_vote_and_process_dg_proposals +from utils.balance import set_balance + + +SENDER_BALANCE_IN_ETH = 10 @pytest.fixture(scope="module") @@ -66,6 +70,11 @@ def snapshot(voting, vote_id): def steps(voting, call_target, vote_time) -> Dict[str, Dict[str, ValueChanged]]: result = {} + # Snapshot tests disable the implicit balance middleware. Fund every sender + # explicitly on both sides of chain.revert() so the two runs start alike. + for sender in {LDO_HOLDER_ADDRESS_FOR_TESTS, *LDO_VOTE_EXECUTORS_FOR_TESTS}: + set_balance(sender, SENDER_BALANCE_IN_ETH) + params = {"from": LDO_HOLDER_ADDRESS_FOR_TESTS} vote_items = [(call_target.address, call_target.perform_call.encode_input())] vote_id = create_vote(bake_vote_items(["Test voting"], vote_items), params)[0] From ac7632bec8a82ffb4a9048d784b38e8743b7c905 Mon Sep 17 00:00:00 2001 From: KRogLA Date: Fri, 10 Jul 2026 17:38:47 +0200 Subject: [PATCH 28/30] feat: allowconsolidationpair easytrack factory test --- configs/config_mainnet.py | 1 + tests/regression/test_easy_track_factories.py | 207 +++++++++++++++++- 2 files changed, 207 insertions(+), 1 deletion(-) diff --git a/configs/config_mainnet.py b/configs/config_mainnet.py index e306990a..926f0c1a 100644 --- a/configs/config_mainnet.py +++ b/configs/config_mainnet.py @@ -89,6 +89,7 @@ EASYTRACK_CM_SETTLE_GENERAL_DELAYED_PENALTY_FACTORY = "0xfffEFC16231eDC6Dc9C93e364ff4D4E3f787f416" EASYTRACK_CM_CREATE_OR_UPDATE_OPERATOR_GROUP_FACTORY = "0x2fC78638b77381e9D040163Bd6EB1cac967bDBdF" EASYTRACK_UPDATE_STAKING_MODULE_SHARE_LIMITS_FACTORY = "0x0C6703F1d8D9DdfB6c6e5F57b4f7432a6500D6D8" +EASYTRACK_ALLOW_CONSOLIDATION_PAIR_FACTORY = "0x29e23B1EF0c9fffAc8330F9abaCebDDD827E4b5C" # Liquidity Observation Lab (LOL) stETH AllowedRecipientsRegistry LOL_ALLOWED_RECIPIENTS_REGISTRY = "0x48c4929630099b217136b64089E8543dB0E5163a" diff --git a/tests/regression/test_easy_track_factories.py b/tests/regression/test_easy_track_factories.py index 0a9e6320..11994995 100644 --- a/tests/regression/test_easy_track_factories.py +++ b/tests/regression/test_easy_track_factories.py @@ -3,7 +3,7 @@ from typing import List, Dict import pytest -from brownie import interface, accounts, web3 +from brownie import interface, accounts, web3, ZERO_ADDRESS from brownie.exceptions import VirtualMachineError from eth_typing import HexStr from eth_abi.abi import encode @@ -13,6 +13,12 @@ from utils.config import contracts, EASYTRACK_SIMPLE_DVT_TRUSTED_CALLER from utils.test.easy_track_helpers import _encode_calldata, create_and_enact_motion from utils.test.keys_helpers import random_pubkeys_batch, random_signatures_batch +from utils.test.curated_v2_helpers import ( + DEFAULT_OPERATOR_WEIGHT, + _get_fresh_node_operator, + _get_role_member_or_grant, + curated_v2_add_node_operator, +) from utils.test.simple_dvt_helpers import ( fill_simple_dvt_ops_keys, get_managers_address, @@ -919,3 +925,202 @@ def test_update_staking_module_share_limits_factory(stranger): module_after = contracts.staking_router.getStakingModule(module_id) assert module_after["stakeShareLimit"] == new_share assert module_after["priorityExitShareThreshold"] == new_priority_exit_threshold + + +# --------------------------------------------------------------------------- +# AllowConsolidationPair +# --------------------------------------------------------------------------- + +CONSOLIDATION_GROUP_NAME = "scripts-regression-consolidation" + + +def _encode_nor_external_operator_data(module_id, node_operator_id): + # ExternalOperatorLib NOR entry: bytes1(OperatorType.NOR == 0) + uint8(moduleId) + uint64(nodeOperatorId) + return b"\x00" + int(module_id).to_bytes(1, "big") + int(node_operator_id).to_bytes(8, "big") + + +def _find_active_source_operator(): + nor = contracts.node_operators_registry + for no_id in range(nor.getNodeOperatorsCount()): + if nor.getNodeOperatorIsActive(no_id): + return no_id + raise AssertionError("No active operator found in the curated (source) module") + + +def _split_operator_shares(count): + # MetaRegistry requires sub-operator shares to sum to MAX_BP (10000); the factory ignores the actual split + share = DEFAULT_OPERATOR_WEIGHT // count + shares = [share] * count + shares[0] += DEFAULT_OPERATOR_WEIGHT - sum(shares) + return shares + + +def _link_consolidation_pair(stranger, targets_count=1): + """Link a curated (source, module 1) operator with `targets_count` fresh CM (target, module 4) operators. + + Mirrors the precondition the factory validates on-chain: source and target operators must belong to the + same MetaRegistry group — the source registered as an `externalOperators` NOR entry and each target as a + `subNodeOperators` entry. Returns (source_operator_id, source_reward_address, sorted target_operator_ids). + """ + source_id = _find_active_source_operator() + reward_address = contracts.node_operators_registry.getNodeOperator(source_id, False)["rewardAddress"] + + # fresh CM operators have no bonded keys but are enough for the allowlist; each starts in its own group. + # the professional gate consumes an address on use, so rotate to an unconsumed one before each creation. + target_ids = [] + node_operator = stranger + for _ in range(targets_count): + node_operator = _get_fresh_node_operator(node_operator) + target_ids.append(curated_v2_add_node_operator(node_operator, 0)) + for target_id in target_ids: + assert contracts.cm.getNodeOperatorIsActive(target_id) + + meta_registry = contracts.cm_meta_registry + group_manager = _get_role_member_or_grant(meta_registry, meta_registry.MANAGE_OPERATOR_GROUPS_ROLE()) + + # dissolve the singleton groups the fresh operators were auto-assigned to, so they can be regrouped together + for target_id in target_ids: + singleton_group_id = meta_registry.getNodeOperatorGroupId(target_id) + if singleton_group_id != meta_registry.NO_GROUP_ID(): + meta_registry.createOrUpdateOperatorGroup(singleton_group_id, ("", [], []), {"from": group_manager}) + + # one group links the source operator (external NOR entry) with all target operators + external_operator_data = _encode_nor_external_operator_data(CONSOLIDATION_SOURCE_MODULE_ID, source_id) + sub_node_operators = list(zip(target_ids, _split_operator_shares(len(target_ids)))) + meta_registry.createOrUpdateOperatorGroup( + meta_registry.NO_GROUP_ID(), + (CONSOLIDATION_GROUP_NAME, sub_node_operators, [(external_operator_data,)]), + {"from": group_manager}, + ) + + group_id = meta_registry.getNodeOperatorGroupId(target_ids[0]) + assert group_id != meta_registry.NO_GROUP_ID() + for target_id in target_ids: + assert meta_registry.getNodeOperatorGroupId(target_id) == group_id + + return source_id, reward_address, sorted(target_ids) + + +def _assert_create_evm_script_reverts(factory, creator, calldata, reason): + try: + factory.createEVMScript(creator, calldata) + except VirtualMachineError as error: + assert reason in error.message, f"expected {reason}, got: {error.message}" + return + raise AssertionError(f"Expected {reason} revert") + + +def test_allow_consolidation_pair_factory(): + factory = interface.AllowConsolidationPair(EASYTRACK_ALLOW_CONSOLIDATION_PAIR_FACTORY) + migrator = interface.ConsolidationMigrator(CONSOLIDATION_MIGRATOR) + + assert factory.consolidationMigrator() == migrator.address + assert factory.stakingRouter() == STAKING_ROUTER + assert factory.sourceModuleId() == CONSOLIDATION_SOURCE_MODULE_ID + assert factory.targetModuleId() == CONSOLIDATION_TARGET_MODULE_ID + assert _permissions_include(factory.address, migrator.address, migrator.allowPair) + + submitter = "0x0000000000000000000000000000000000001234" + calldata = _encode_calldata(["address", "uint256", "uint256[]"], [submitter, 3, [1, 2, 5]]) + decoded = factory.decodeEVMScriptCallData(calldata) + assert decoded[0] == submitter + assert decoded[1] == 3 + assert list(decoded[2]) == [1, 2, 5] + + +def test_allow_consolidation_pair_factory_input_validation(stranger): + factory = interface.AllowConsolidationPair(EASYTRACK_ALLOW_CONSOLIDATION_PAIR_FACTORY) + nor = contracts.node_operators_registry + + source_id = _find_active_source_operator() + reward_address = nor.getNodeOperator(source_id, False)["rewardAddress"] + source_count = nor.getNodeOperatorsCount() + + # submitter must be non-zero + _assert_create_evm_script_reverts( + factory, + reward_address, + _encode_calldata(["address", "uint256", "uint256[]"], [ZERO_ADDRESS, source_id, [0]]), + "ZERO_SUBMITTER", + ) + + # source operator must exist in the curated module + _assert_create_evm_script_reverts( + factory, + reward_address, + _encode_calldata(["address", "uint256", "uint256[]"], [stranger.address, source_count + 1000, [0]]), + "SOURCE_OPERATOR_ID_DOES_NOT_EXIST", + ) + + # creator must be the source operator reward address (or its manager) + _assert_create_evm_script_reverts( + factory, + stranger, + _encode_calldata(["address", "uint256", "uint256[]"], [stranger.address, source_id, [0]]), + "CALLER_IS_NOT_SOURCE_OPERATOR_OWNER_OR_MANAGER", + ) + + # source operator is not linked to any target group in the MetaRegistry + _assert_create_evm_script_reverts( + factory, + reward_address, + _encode_calldata(["address", "uint256", "uint256[]"], [stranger.address, source_id, [0]]), + "OPERATORS_ARE_NOT_LINKED_BY_META_REGISTRY", + ) + + +def test_allow_consolidation_pair_via_motion(stranger): + factory = interface.AllowConsolidationPair(EASYTRACK_ALLOW_CONSOLIDATION_PAIR_FACTORY) + migrator = interface.ConsolidationMigrator(CONSOLIDATION_MIGRATOR) + + source_id, reward_address, target_ids = _link_consolidation_pair(stranger) + submitter = stranger.address + + for target_id in target_ids: + assert not migrator.isPairAllowed(source_id, target_id) + + calldata = _encode_calldata(["address", "uint256", "uint256[]"], [submitter, source_id, target_ids]) + + create_and_enact_motion( + contracts.easy_track, + set_balance(reward_address, 100000), + factory, + calldata, + stranger, + ) + + allowed_targets = list(migrator.getAllowedTargets(source_id)) + for target_id in target_ids: + assert migrator.isPairAllowed(source_id, target_id) + assert migrator.getSubmitter(source_id, target_id) == submitter + assert target_id in allowed_targets + + +def test_allow_consolidation_pair_via_motion_multiple_targets(stranger): + factory = interface.AllowConsolidationPair(EASYTRACK_ALLOW_CONSOLIDATION_PAIR_FACTORY) + migrator = interface.ConsolidationMigrator(CONSOLIDATION_MIGRATOR) + + source_id, reward_address, target_ids = _link_consolidation_pair(stranger, targets_count=2) + submitter = stranger.address + + # the factory enforces a strictly ascending target list; several targets share one source group + assert len(target_ids) == 2 + assert target_ids == sorted(set(target_ids)) + for target_id in target_ids: + assert not migrator.isPairAllowed(source_id, target_id) + + calldata = _encode_calldata(["address", "uint256", "uint256[]"], [submitter, source_id, target_ids]) + + create_and_enact_motion( + contracts.easy_track, + set_balance(reward_address, 100000), + factory, + calldata, + stranger, + ) + + allowed_targets = list(migrator.getAllowedTargets(source_id)) + for target_id in target_ids: + assert migrator.isPairAllowed(source_id, target_id) + assert migrator.getSubmitter(source_id, target_id) == submitter + assert target_id in allowed_targets From 560d9b8758d440bd904fdad838eaa5535d0b9112 Mon Sep 17 00:00:00 2001 From: Anna Mukharram Date: Fri, 10 Jul 2026 19:50:15 +0400 Subject: [PATCH 29/30] fix: staking module happy path --- configs/config_mainnet.py | 2 +- tests/regression/test_permissions.py | 12 ++++-- .../test_staking_module_happy_path.py | 41 +++++++++++-------- 3 files changed, 32 insertions(+), 23 deletions(-) diff --git a/configs/config_mainnet.py b/configs/config_mainnet.py index e306990a..0d2ade2d 100644 --- a/configs/config_mainnet.py +++ b/configs/config_mainnet.py @@ -379,7 +379,7 @@ TOP_UP_GATEWAY_TARGET_BALANCE_GWEI = 2_046_750_000_000 # 2046.75 ETH (1.25 ETH margin below MaxEB) TOP_UP_GATEWAY_MIN_TOP_UP_GWEI = 2_000_000_000 # 2 ETH # sole TOP_UP_ROLE holder (coreUpgrade.topUpGatewayDepositor, stable deploy input) -TOP_UP_GATEWAY_DEPOSITOR = "0x57Cc953D3d27E7E8bAd04566bfd4Cd416c3B0855" +TOP_UP_GATEWAY_DEPOSITOR = "0xF82aC5937A20dC862F9bc0668779031E06000f17" # CircuitBreaker — TW-upgrade pause hub; the SRv3 vote registers it as pauser for the new gateways CIRCUIT_BREAKER = "0x6019CB557978296BA3C08a7B73225C0975DFB2F7" diff --git a/tests/regression/test_permissions.py b/tests/regression/test_permissions.py index a4c2020f..678a09dc 100644 --- a/tests/regression/test_permissions.py +++ b/tests/regression/test_permissions.py @@ -314,17 +314,21 @@ def protocol_permissions(): "roles": { "DEFAULT_ADMIN_ROLE": [contracts.agent], "ALL_LIMITS_MANAGER_ROLE": [], - "EXITED_VALIDATORS_PER_DAY_LIMIT_MANAGER_ROLE": [], - "APPEARED_VALIDATORS_PER_DAY_LIMIT_MANAGER_ROLE": [], + "EXITED_ETH_AMOUNT_PER_DAY_LIMIT_MANAGER_ROLE": [], + "APPEARED_ETH_AMOUNT_PER_DAY_LIMIT_MANAGER_ROLE": [], + "CONSOLIDATION_ETH_AMOUNT_PER_DAY_LIMIT_MANAGER_ROLE": [], + "EXITED_VALIDATOR_ETH_AMOUNT_LIMIT_MANAGER_ROLE": [], + "EXTERNAL_PENDING_BALANCE_CAP_MANAGER_ROLE": [], + "MAX_BALANCE_EXIT_REQUESTED_PER_REPORT_IN_ETH_ROLE": [], + "MAX_CL_BALANCE_DECREASE_MANAGER_ROLE": [], + "MAX_EFFECTIVE_BALANCE_WEIGHTS_MANAGER_ROLE": [], "ANNUAL_BALANCE_INCREASE_LIMIT_MANAGER_ROLE": [], "SHARE_RATE_DEVIATION_LIMIT_MANAGER_ROLE": [], - "MAX_VALIDATOR_EXIT_REQUESTS_PER_REPORT_ROLE": [], "MAX_ITEMS_PER_EXTRA_DATA_TRANSACTION_ROLE": [], "MAX_NODE_OPERATORS_PER_EXTRA_DATA_ITEM_ROLE": [], "REQUEST_TIMESTAMP_MARGIN_MANAGER_ROLE": [], "MAX_POSITIVE_TOKEN_REBASE_MANAGER_ROLE": [], "SECOND_OPINION_MANAGER_ROLE": [], - "INITIAL_SLASHING_AND_PENALTIES_MANAGER_ROLE": [], }, }, DEPOSIT_SECURITY_MODULE: { diff --git a/tests/regression/test_staking_module_happy_path.py b/tests/regression/test_staking_module_happy_path.py index 9807e488..4fadbd4f 100644 --- a/tests/regression/test_staking_module_happy_path.py +++ b/tests/regression/test_staking_module_happy_path.py @@ -22,6 +22,7 @@ SET_NODE_OPERATOR_LIMIT_ROLE = Web3.keccak(text="SET_NODE_OPERATOR_LIMIT_ROLE") STAKING_CONTROL_ROLE = Web3.keccak(text="STAKING_CONTROL_ROLE") + @pytest.fixture(scope="function") def impersonated_agent(accounts): return accounts.at(contracts.agent.address, force=True) @@ -61,13 +62,15 @@ def deposit_and_check_keys(nor, first_id, second_id, third_id, keys_count, imper deposited_keys_second_before = nor.getNodeOperatorSummary(second_id)["totalDepositedValidators"] deposited_keys_base_before = nor.getNodeOperatorSummary(third_id)["totalDepositedValidators"] validators_before = contracts.lido.getBeaconStat().dict()["depositedValidators"] + (_, _, deposited_since_report_before, _) = contracts.lido.getBalanceStats() module_total_deposited_keys_before = nor.getStakingModuleSummary()["totalDepositedValidators"] print(f"Deposit {keys_count} keys for module {nor.module_id}") - tx = contracts.lido.deposit(keys_count, nor.module_id, "0x", {"from": contracts.deposit_security_module.address}) + tx = contracts.staking_router.deposit(nor.module_id, "0x", {"from": contracts.deposit_security_module.address}) validators_after = contracts.lido.getBeaconStat().dict()["depositedValidators"] + (_, _, deposited_since_report_after, _) = contracts.lido.getBalanceStats() module_total_deposited_keys_after = nor.getStakingModuleSummary()["totalDepositedValidators"] just_deposited = validators_after - validators_before @@ -75,6 +78,7 @@ def deposit_and_check_keys(nor, first_id, second_id, third_id, keys_count, imper if just_deposited: assert tx.events["DepositedValidatorsChanged"]["depositedValidators"] == validators_after assert tx.events["Unbuffered"]["amount"] == just_deposited * ETH(32) + assert deposited_since_report_after - deposited_since_report_before == just_deposited * ETH(32) assert module_total_deposited_keys_before + just_deposited == module_total_deposited_keys_after deposited_keys_first_after = nor.getNodeOperatorSummary(first_id)["totalDepositedValidators"] @@ -107,13 +111,9 @@ def parse_exited_signing_keys_count_changed_logs(logs): return res - - def module_happy_path(staking_module, extra_data_service, impersonated_agent, stranger, helpers): nor_exited_count, _, _ = contracts.staking_router.getStakingModuleSummary(staking_module.module_id) - # all_modules = contracts.staking_router.getStakingModules() - contracts.staking_router.grantRole( STAKING_MODULE_MANAGE_ROLE, impersonated_agent, @@ -135,15 +135,16 @@ def module_happy_path(staking_module, extra_data_service, impersonated_agent, st ) contracts.acl.grantPermission( - impersonated_agent, - contracts.lido, - STAKING_CONTROL_ROLE, - {"from": impersonated_agent} + impersonated_agent, contracts.lido, STAKING_CONTROL_ROLE, {"from": impersonated_agent} ) # pausing csm due to very high amount of keys in the queue csm_module_id = 3 set_staking_module_status(csm_module_id, StakingModuleStatus.Stopped) + # stop Curated Module v2 as well: with depositable keys and zero stake it would + # become the min-first allocation target and steal deposits from the tested module + curated_v2_module_id = 4 + set_staking_module_status(curated_v2_module_id, StakingModuleStatus.Stopped) # fill buffer enough to deposit 310 keys fill_deposit_buffer(310) @@ -259,7 +260,9 @@ def module_happy_path(staking_module, extra_data_service, impersonated_agent, st # Events exited_signing_keys_count_events = parse_exited_signing_keys_count_changed_logs( - filter_transfer_logs(extra_report_tx_list[0].logs, web3.keccak(text="ExitedSigningKeysCountChanged(uint256,uint256)")) + filter_transfer_logs( + extra_report_tx_list[0].logs, web3.keccak(text="ExitedSigningKeysCountChanged(uint256,uint256)") + ) ) assert exited_signing_keys_count_events[0]["nodeOperatorId"] == no1_id assert exited_signing_keys_count_events[0]["exitedValidatorsCount"][0] == no1_exited_before + 5 @@ -276,8 +279,6 @@ def module_happy_path(staking_module, extra_data_service, impersonated_agent, st op_index, no["totalDepositedValidators"] + 10, {"from": impersonated_agent} ) - - # Case 6 # -- SActivate target limit for "1st" NO # -- Check deposits @@ -296,13 +297,15 @@ def module_happy_path(staking_module, extra_data_service, impersonated_agent, st assert first_no_summary_before["depositableValidatorsCount"] > 0 - target_limit_tx = staking_module.updateTargetValidatorsLimits['uint256,uint256,uint256'](no1_id, 1, 0, {"from": STAKING_ROUTER}) + target_limit_tx = staking_module.updateTargetValidatorsLimits["uint256,uint256,uint256"]( + no1_id, 1, 0, {"from": STAKING_ROUTER} + ) helpers.assert_single_event_named( - "TargetValidatorsCountChanged", - target_limit_tx, - {"nodeOperatorId": no1_id, "targetValidatorsCount": 0, "targetLimitMode": 1}, - ) + "TargetValidatorsCountChanged", + target_limit_tx, + {"nodeOperatorId": no1_id, "targetValidatorsCount": 0, "targetLimitMode": 1}, + ) first_no_summary_after = staking_module.getNodeOperatorSummary(no1_id) @@ -326,7 +329,9 @@ def module_happy_path(staking_module, extra_data_service, impersonated_agent, st assert no3_deposited_keys_before != no3_deposited_keys_after # Disable target limit - target_limit_tx = staking_module.updateTargetValidatorsLimits['uint256,uint256,uint256'](no1_id, 0, 0, {"from": STAKING_ROUTER}) + target_limit_tx = staking_module.updateTargetValidatorsLimits["uint256,uint256,uint256"]( + no1_id, 0, 0, {"from": STAKING_ROUTER} + ) helpers.assert_single_event_named( "TargetValidatorsCountChanged", From 476111b135b29e8348ff32b240c58d17ff1f49c0 Mon Sep 17 00:00:00 2001 From: Anna Mukharram Date: Fri, 10 Jul 2026 23:24:35 +0400 Subject: [PATCH 30/30] fix: sdvt tests & vebo --- interfaces/ValidatorsExitBusOracle.json | 1720 ++++++++++++++++- tests/regression/test_permissions.py | 1 - .../test_sdvt_rewards_happy_path.py | 3 +- .../test_validator_exit_bus_happy_path.py | 20 +- 4 files changed, 1733 insertions(+), 11 deletions(-) diff --git a/interfaces/ValidatorsExitBusOracle.json b/interfaces/ValidatorsExitBusOracle.json index ba352a4f..10e0ce30 100644 --- a/interfaces/ValidatorsExitBusOracle.json +++ b/interfaces/ValidatorsExitBusOracle.json @@ -1 +1,1719 @@ -[{"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":[{"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":false,"internalType":"uint256","name":"maxValidatorsPerReport","type":"uint256"}],"name":"SetMaxValidatorsPerReport","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"}] +[ + { + "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": [ + { + "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": "balanceEth", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "remainingLimitEth", + "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": "InvalidMaxEBWeight", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidModuleId", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "InvalidPublicKey", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRequestsDataLength", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRequestsDataSortOrder", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRetrievedKeyLength", + "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": "TooLargeFrameDuration", + "type": "error" + }, + { + "inputs": [], + "name": "TooLargeItemsPerFrame", + "type": "error" + }, + { + "inputs": [], + "name": "TooLargeMaxLimit", + "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": [], + "name": "UnexpectedWCType", + "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": "uint256", + "name": "maxExitBalanceEth", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "balancePerFrameEth", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "frameDurationInSec", + "type": "uint256" + } + ], + "name": "ExitBalanceLimitSet", + "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": "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": false, + "internalType": "uint256", + "name": "maxValidatorsPerReport", + "type": "uint256" + } + ], + "name": "SetMaxValidatorsPerReport", + "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": "DATA_FORMAT_LIST_WITH_KEY_INDEX", + "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": "MAX_EFFECTIVE_BALANCE_WEIGHT_WC_TYPE_01", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_EFFECTIVE_BALANCE_WEIGHT_WC_TYPE_02", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "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": "maxExitBalanceEth", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "balancePerFrameEth", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "frameDurationInSec", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "consensusVersion", + "type": "uint256" + } + ], + "name": "finalizeUpgrade_v3", + "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": "maxExitBalanceEth", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "balancePerFrameEth", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "frameDurationInSec", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "prevExitBalanceEth", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "currentExitBalanceEth", + "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": "maxValidatorsPerReport", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxExitBalanceEth", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "balancePerFrameEth", + "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": "maxExitBalanceEth", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "balancePerFrameEth", + "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" + } +] \ No newline at end of file diff --git a/tests/regression/test_permissions.py b/tests/regression/test_permissions.py index 678a09dc..0ac0a1d2 100644 --- a/tests/regression/test_permissions.py +++ b/tests/regression/test_permissions.py @@ -389,7 +389,6 @@ def protocol_permissions(): "STAKING_CONTROL_ROLE": [], "RESUME_ROLE": [], "STAKING_PAUSE_ROLE": [], - "UNSAFE_CHANGE_DEPOSITED_VALIDATORS_ROLE": [], "BUFFER_RESERVE_MANAGER_ROLE": [contracts.agent], }, }, diff --git a/tests/regression/test_sdvt_rewards_happy_path.py b/tests/regression/test_sdvt_rewards_happy_path.py index 12d47ee0..62144b9a 100644 --- a/tests/regression/test_sdvt_rewards_happy_path.py +++ b/tests/regression/test_sdvt_rewards_happy_path.py @@ -98,7 +98,6 @@ def test_rewards_distribution_happy_path(simple_dvt_module_id, cluster_participa # vet operator keys simple_dvt_vet_keys(operator_id, new_dvt_operator) - # pause deposit to all modules except simple dvt # to be sure that all deposits go to simple dvt modules = staking_router.getStakingModules() @@ -111,7 +110,7 @@ def test_rewards_distribution_happy_path(simple_dvt_module_id, cluster_participa fill_deposit_buffer(deposits_count, heuristic=10000) # deposit to simple dvt module_summary_before = staking_router.getStakingModuleSummary(simple_dvt_module_id) - lido.deposit(deposits_count, simple_dvt_module_id, "0x", {"from": deposit_security_module}) + staking_router.deposit(simple_dvt_module_id, "0x", {"from": deposit_security_module}) module_summary_after = staking_router.getStakingModuleSummary(simple_dvt_module_id) assert ( diff --git a/tests/regression/test_validator_exit_bus_happy_path.py b/tests/regression/test_validator_exit_bus_happy_path.py index 994e9d11..838053db 100644 --- a/tests/regression/test_validator_exit_bus_happy_path.py +++ b/tests/regression/test_validator_exit_bus_happy_path.py @@ -69,7 +69,7 @@ def test_send_zero_validators_to_exit(helpers): assert processing_state_before != processing_state_after assert processing_state_after.data_hash == report_hash_hex assert processing_state_after.data_submitted - assert processing_state_after.data_format == contracts.validators_exit_bus_oracle.DATA_FORMAT_LIST() + assert processing_state_after.data_format == contracts.validators_exit_bus_oracle.DATA_FORMAT_LIST_WITH_KEY_INDEX() assert processing_state_after.requests_count == processing_state_before.requests_count assert processing_state_after.requests_submitted == processing_state_before.requests_submitted @@ -79,7 +79,7 @@ def test_send_validator_to_exit(helpers, web3): no_global_index = (module_id, no_id) = (1, 33) validator_key = contracts.node_operators_registry.getSigningKey(no_id, 1)[0] - validator = LidoValidator(index=unreachable_cl_validator_index, pubkey=validator_key) + validator = LidoValidator(index=unreachable_cl_validator_index, pubkey=validator_key, key_index=1) ref_slot = _wait_for_next_ref_slot() report, report_hash = prepare_exit_bus_report([(no_global_index, validator)], ref_slot) @@ -119,7 +119,7 @@ def test_send_validator_to_exit(helpers, web3): assert processing_state_before != processing_state_after assert processing_state_after.data_hash == report_hash_hex assert processing_state_after.data_submitted - assert processing_state_after.data_format == contracts.validators_exit_bus_oracle.DATA_FORMAT_LIST() + assert processing_state_after.data_format == contracts.validators_exit_bus_oracle.DATA_FORMAT_LIST_WITH_KEY_INDEX() assert processing_state_after.requests_count == processing_state_before.requests_count + 1 assert processing_state_after.requests_submitted == processing_state_before.requests_submitted + 1 @@ -149,9 +149,15 @@ def test_send_multiple_validators_to_exit(helpers, web3, stranger): first_validator_key = contracts.node_operators_registry.getSigningKey(first_no_id, first_validator_id)[0] second_validator_key = contracts.node_operators_registry.getSigningKey(second_no_id, second_validator_id)[0] third_validator_key = contracts.simple_dvt.getSigningKey(third_no_id, third_validator_id)[0] - first_validator = LidoValidator(index=first_validator_index, pubkey=first_validator_key) - second_validator = LidoValidator(index=second_validator_index, pubkey=second_validator_key) - third_validator = LidoValidator(index=third_validator_index, pubkey=third_validator_key) + first_validator = LidoValidator( + index=first_validator_index, pubkey=first_validator_key, key_index=first_validator_id + ) + second_validator = LidoValidator( + index=second_validator_index, pubkey=second_validator_key, key_index=second_validator_id + ) + third_validator = LidoValidator( + index=third_validator_index, pubkey=third_validator_key, key_index=third_validator_id + ) ref_slot = _wait_for_next_ref_slot() report, report_hash = prepare_exit_bus_report( @@ -211,6 +217,6 @@ def test_send_multiple_validators_to_exit(helpers, web3, stranger): assert processing_state_before != processing_state_after assert processing_state_after.data_hash == report_hash_hex assert processing_state_after.data_submitted - assert processing_state_after.data_format == contracts.validators_exit_bus_oracle.DATA_FORMAT_LIST() + assert processing_state_after.data_format == contracts.validators_exit_bus_oracle.DATA_FORMAT_LIST_WITH_KEY_INDEX() assert processing_state_after.requests_count == processing_state_before.requests_count + 3 assert processing_state_after.requests_submitted == processing_state_before.requests_submitted + 3