From 3a8e8e86489aafc38dcc92da749416b49b3094f3 Mon Sep 17 00:00:00 2001 From: Eddort Date: Tue, 14 Apr 2026 17:43:19 +0200 Subject: [PATCH 01/15] feat: devnet srv3 voting prototype --- interfaces/Accounting.json | 328 +-- interfaces/ConsolidationMigrator.json | 1 + interfaces/HashConsensus.json | 2 +- interfaces/IConsolidationMigrator.json | 43 + interfaces/IMetaRegistry.json | 1 + interfaces/StakingRouter.json | 2566 +---------------- interfaces/UpgradeVoteScript.json | 1 + interfaces/WithdrawalsManagerProxy.json | 82 +- ...grade_2026_04_14_hoodi_protocol_upgrade.py | 166 ++ ...2026_04_14_hoodi_protocol_upgrade_no_dg.py | 176 ++ .../test_2026_04_14_hoodi_protocol_upgrade.py | 252 ++ 11 files changed, 644 insertions(+), 2974 deletions(-) create mode 100644 interfaces/ConsolidationMigrator.json create mode 100644 interfaces/IConsolidationMigrator.json create mode 100644 interfaces/IMetaRegistry.json create mode 100644 interfaces/UpgradeVoteScript.json create mode 100644 scripts/upgrade_2026_04_14_hoodi_protocol_upgrade.py create mode 100644 scripts/upgrade_2026_04_14_hoodi_protocol_upgrade_no_dg.py create mode 100644 tests/test_2026_04_14_hoodi_protocol_upgrade.py diff --git a/interfaces/Accounting.json b/interfaces/Accounting.json index 95eb78cc..a6a82d3a 100644 --- a/interfaces/Accounting.json +++ b/interfaces/Accounting.json @@ -1,327 +1 @@ -[ - { - "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"}] diff --git a/interfaces/ConsolidationMigrator.json b/interfaces/ConsolidationMigrator.json new file mode 100644 index 00000000..67f4e11f --- /dev/null +++ b/interfaces/ConsolidationMigrator.json @@ -0,0 +1 @@ +[{"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"}] diff --git a/interfaces/HashConsensus.json b/interfaces/HashConsensus.json index 38512567..f23dd947 100644 --- a/interfaces/HashConsensus.json +++ b/interfaces/HashConsensus.json @@ -1 +1 @@ -[{"inputs":[{"internalType":"uint256","name":"slotsPerEpoch","type":"uint256"},{"internalType":"uint256","name":"secondsPerSlot","type":"uint256"},{"internalType":"uint256","name":"genesisTime","type":"uint256"},{"internalType":"uint256","name":"epochsPerFrame","type":"uint256"},{"internalType":"uint256","name":"fastLaneLengthSlots","type":"uint256"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"address","name":"reportProcessor","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AddressCannotBeZero","type":"error"},{"inputs":[],"name":"AdminCannotBeZero","type":"error"},{"inputs":[],"name":"ConsensusReportAlreadyProcessing","type":"error"},{"inputs":[],"name":"DuplicateMember","type":"error"},{"inputs":[],"name":"DuplicateReport","type":"error"},{"inputs":[],"name":"EmptyReport","type":"error"},{"inputs":[],"name":"EpochsPerFrameCannotBeZero","type":"error"},{"inputs":[],"name":"FastLanePeriodCannotBeLongerThanFrame","type":"error"},{"inputs":[],"name":"InitialEpochAlreadyArrived","type":"error"},{"inputs":[],"name":"InitialEpochIsYetToArrive","type":"error"},{"inputs":[],"name":"InitialEpochRefSlotCannotBeEarlierThanProcessingSlot","type":"error"},{"inputs":[],"name":"InvalidChainConfig","type":"error"},{"inputs":[],"name":"InvalidSlot","type":"error"},{"inputs":[],"name":"NewProcessorCannotBeTheSame","type":"error"},{"inputs":[],"name":"NonFastLaneMemberCannotReportWithinFastLaneInterval","type":"error"},{"inputs":[],"name":"NonMember","type":"error"},{"inputs":[],"name":"NumericOverflow","type":"error"},{"inputs":[{"internalType":"uint256","name":"minQuorum","type":"uint256"},{"internalType":"uint256","name":"receivedQuorum","type":"uint256"}],"name":"QuorumTooSmall","type":"error"},{"inputs":[],"name":"ReportProcessorCannotBeZero","type":"error"},{"inputs":[],"name":"StaleReport","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedConsensusVersion","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"}],"name":"ConsensusLost","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"report","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"support","type":"uint256"}],"name":"ConsensusReached","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"fastLaneLengthSlots","type":"uint256"}],"name":"FastLaneConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newInitialEpoch","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newEpochsPerFrame","type":"uint256"}],"name":"FrameConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"addr","type":"address"},{"indexed":false,"internalType":"uint256","name":"newTotalMembers","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newQuorum","type":"uint256"}],"name":"MemberAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"addr","type":"address"},{"indexed":false,"internalType":"uint256","name":"newTotalMembers","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newQuorum","type":"uint256"}],"name":"MemberRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newQuorum","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalMembers","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"prevQuorum","type":"uint256"}],"name":"QuorumSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"processor","type":"address"},{"indexed":true,"internalType":"address","name":"prevProcessor","type":"address"}],"name":"ReportProcessorSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"},{"indexed":true,"internalType":"address","name":"member","type":"address"},{"indexed":false,"internalType":"bytes32","name":"report","type":"bytes32"}],"name":"ReportReceived","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":"DISABLE_CONSENSUS_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_FAST_LANE_CONFIG_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_FRAME_CONFIG_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_MEMBERS_AND_QUORUM_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_REPORT_PROCESSOR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"quorum","type":"uint256"}],"name":"addMember","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"disableConsensus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getChainConfig","outputs":[{"internalType":"uint256","name":"slotsPerEpoch","type":"uint256"},{"internalType":"uint256","name":"secondsPerSlot","type":"uint256"},{"internalType":"uint256","name":"genesisTime","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConsensusState","outputs":[{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"bytes32","name":"consensusReport","type":"bytes32"},{"internalType":"bool","name":"isReportProcessing","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"getConsensusStateForMember","outputs":[{"components":[{"internalType":"uint256","name":"currentFrameRefSlot","type":"uint256"},{"internalType":"bytes32","name":"currentFrameConsensusReport","type":"bytes32"},{"internalType":"bool","name":"isMember","type":"bool"},{"internalType":"bool","name":"isFastLane","type":"bool"},{"internalType":"bool","name":"canReport","type":"bool"},{"internalType":"uint256","name":"lastMemberReportRefSlot","type":"uint256"},{"internalType":"bytes32","name":"currentFrameMemberReport","type":"bytes32"}],"internalType":"struct HashConsensus.MemberConsensusState","name":"result","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentFrame","outputs":[{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"reportProcessingDeadlineSlot","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFastLaneMembers","outputs":[{"internalType":"address[]","name":"addresses","type":"address[]"},{"internalType":"uint256[]","name":"lastReportedRefSlots","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFrameConfig","outputs":[{"internalType":"uint256","name":"initialEpoch","type":"uint256"},{"internalType":"uint256","name":"epochsPerFrame","type":"uint256"},{"internalType":"uint256","name":"fastLaneLengthSlots","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getInitialRefSlot","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"getIsFastLaneMember","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"getIsMember","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMembers","outputs":[{"internalType":"address[]","name":"addresses","type":"address[]"},{"internalType":"uint256[]","name":"lastReportedRefSlots","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getQuorum","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getReportProcessor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getReportVariants","outputs":[{"internalType":"bytes32[]","name":"variants","type":"bytes32[]"},{"internalType":"uint256[]","name":"support","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":"addr","type":"address"},{"internalType":"uint256","name":"quorum","type":"uint256"}],"name":"removeMember","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":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"fastLaneLengthSlots","type":"uint256"}],"name":"setFastLaneLengthSlots","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"epochsPerFrame","type":"uint256"},{"internalType":"uint256","name":"fastLaneLengthSlots","type":"uint256"}],"name":"setFrameConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"quorum","type":"uint256"}],"name":"setQuorum","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newProcessor","type":"address"}],"name":"setReportProcessor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"slot","type":"uint256"},{"internalType":"bytes32","name":"report","type":"bytes32"},{"internalType":"uint256","name":"consensusVersion","type":"uint256"}],"name":"submitReport","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":"initialEpoch","type":"uint256"}],"name":"updateInitialEpoch","outputs":[],"stateMutability":"nonpayable","type":"function"}] \ No newline at end of file +[{"inputs":[{"internalType":"uint256","name":"slotsPerEpoch","type":"uint256"},{"internalType":"uint256","name":"secondsPerSlot","type":"uint256"},{"internalType":"uint256","name":"genesisTime","type":"uint256"},{"internalType":"uint256","name":"epochsPerFrame","type":"uint256"},{"internalType":"uint256","name":"fastLaneLengthSlots","type":"uint256"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"address","name":"reportProcessor","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AddressCannotBeZero","type":"error"},{"inputs":[],"name":"AdminCannotBeZero","type":"error"},{"inputs":[],"name":"ConsensusReportAlreadyProcessing","type":"error"},{"inputs":[],"name":"DuplicateMember","type":"error"},{"inputs":[],"name":"DuplicateReport","type":"error"},{"inputs":[],"name":"EmptyReport","type":"error"},{"inputs":[],"name":"EpochsPerFrameCannotBeZero","type":"error"},{"inputs":[],"name":"FastLanePeriodCannotBeLongerThanFrame","type":"error"},{"inputs":[],"name":"InitialEpochAlreadyArrived","type":"error"},{"inputs":[],"name":"InitialEpochIsYetToArrive","type":"error"},{"inputs":[],"name":"InitialEpochRefSlotCannotBeEarlierThanProcessingSlot","type":"error"},{"inputs":[],"name":"InvalidChainConfig","type":"error"},{"inputs":[],"name":"InvalidSlot","type":"error"},{"inputs":[],"name":"NewProcessorCannotBeTheSame","type":"error"},{"inputs":[],"name":"NonFastLaneMemberCannotReportWithinFastLaneInterval","type":"error"},{"inputs":[],"name":"NonMember","type":"error"},{"inputs":[],"name":"NumericOverflow","type":"error"},{"inputs":[{"internalType":"uint256","name":"minQuorum","type":"uint256"},{"internalType":"uint256","name":"receivedQuorum","type":"uint256"}],"name":"QuorumTooSmall","type":"error"},{"inputs":[],"name":"ReportProcessorCannotBeZero","type":"error"},{"inputs":[],"name":"StaleReport","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedConsensusVersion","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"}],"name":"ConsensusLost","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"report","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"support","type":"uint256"}],"name":"ConsensusReached","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"fastLaneLengthSlots","type":"uint256"}],"name":"FastLaneConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newInitialEpoch","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newEpochsPerFrame","type":"uint256"}],"name":"FrameConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"addr","type":"address"},{"indexed":false,"internalType":"uint256","name":"newTotalMembers","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newQuorum","type":"uint256"}],"name":"MemberAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"addr","type":"address"},{"indexed":false,"internalType":"uint256","name":"newTotalMembers","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newQuorum","type":"uint256"}],"name":"MemberRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newQuorum","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalMembers","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"prevQuorum","type":"uint256"}],"name":"QuorumSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"processor","type":"address"},{"indexed":true,"internalType":"address","name":"prevProcessor","type":"address"}],"name":"ReportProcessorSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"},{"indexed":true,"internalType":"address","name":"member","type":"address"},{"indexed":false,"internalType":"bytes32","name":"report","type":"bytes32"}],"name":"ReportReceived","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":"DISABLE_CONSENSUS_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_FAST_LANE_CONFIG_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_FRAME_CONFIG_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_MEMBERS_AND_QUORUM_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_REPORT_PROCESSOR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"quorum","type":"uint256"}],"name":"addMember","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"disableConsensus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getChainConfig","outputs":[{"internalType":"uint256","name":"slotsPerEpoch","type":"uint256"},{"internalType":"uint256","name":"secondsPerSlot","type":"uint256"},{"internalType":"uint256","name":"genesisTime","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConsensusState","outputs":[{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"bytes32","name":"consensusReport","type":"bytes32"},{"internalType":"bool","name":"isReportProcessing","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"getConsensusStateForMember","outputs":[{"components":[{"internalType":"uint256","name":"currentFrameRefSlot","type":"uint256"},{"internalType":"bytes32","name":"currentFrameConsensusReport","type":"bytes32"},{"internalType":"bool","name":"isMember","type":"bool"},{"internalType":"bool","name":"isFastLane","type":"bool"},{"internalType":"bool","name":"canReport","type":"bool"},{"internalType":"uint256","name":"lastMemberReportRefSlot","type":"uint256"},{"internalType":"bytes32","name":"currentFrameMemberReport","type":"bytes32"}],"internalType":"struct HashConsensus.MemberConsensusState","name":"result","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentFrame","outputs":[{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"reportProcessingDeadlineSlot","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFastLaneMembers","outputs":[{"internalType":"address[]","name":"addresses","type":"address[]"},{"internalType":"uint256[]","name":"lastReportedRefSlots","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFrameConfig","outputs":[{"internalType":"uint256","name":"initialEpoch","type":"uint256"},{"internalType":"uint256","name":"epochsPerFrame","type":"uint256"},{"internalType":"uint256","name":"fastLaneLengthSlots","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getInitialRefSlot","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"getIsFastLaneMember","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"getIsMember","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMembers","outputs":[{"internalType":"address[]","name":"addresses","type":"address[]"},{"internalType":"uint256[]","name":"lastReportedRefSlots","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getQuorum","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getReportProcessor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getReportVariants","outputs":[{"internalType":"bytes32[]","name":"variants","type":"bytes32[]"},{"internalType":"uint256[]","name":"support","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":"addr","type":"address"},{"internalType":"uint256","name":"quorum","type":"uint256"}],"name":"removeMember","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":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"fastLaneLengthSlots","type":"uint256"}],"name":"setFastLaneLengthSlots","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"epochsPerFrame","type":"uint256"},{"internalType":"uint256","name":"fastLaneLengthSlots","type":"uint256"}],"name":"setFrameConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"quorum","type":"uint256"}],"name":"setQuorum","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newProcessor","type":"address"}],"name":"setReportProcessor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"slot","type":"uint256"},{"internalType":"bytes32","name":"report","type":"bytes32"},{"internalType":"uint256","name":"consensusVersion","type":"uint256"}],"name":"submitReport","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":"initialEpoch","type":"uint256"}],"name":"updateInitialEpoch","outputs":[],"stateMutability":"nonpayable","type":"function"}] diff --git a/interfaces/IConsolidationMigrator.json b/interfaces/IConsolidationMigrator.json new file mode 100644 index 00000000..376e3984 --- /dev/null +++ b/interfaces/IConsolidationMigrator.json @@ -0,0 +1,43 @@ +[ + { + "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" + } +] diff --git a/interfaces/IMetaRegistry.json b/interfaces/IMetaRegistry.json new file mode 100644 index 00000000..d99e774c --- /dev/null +++ b/interfaces/IMetaRegistry.json @@ -0,0 +1 @@ +[{"inputs":[{"internalType":"uint256","name":"groupId","type":"uint256"},{"components":[{"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"}],"name":"createOrUpdateOperatorGroup","outputs":[],"stateMutability":"nonpayable","type":"function"}] diff --git a/interfaces/StakingRouter.json b/interfaces/StakingRouter.json index 63233f2d..7c7ec3d2 100644 --- a/interfaces/StakingRouter.json +++ b/interfaces/StakingRouter.json @@ -1,2565 +1 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "_depositContract", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "AppAuthLidoFailed", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "firstArrayLength", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "secondArrayLength", - "type": "uint256" - } - ], - "name": "ArraysLengthMismatch", - "type": "error" - }, - { - "inputs": [], - "name": "DepositContractZeroAddress", - "type": "error" - }, - { - "inputs": [], - "name": "DirectETHTransfer", - "type": "error" - }, - { - "inputs": [], - "name": "EmptyWithdrawalsCredentials", - "type": "error" - }, - { - "inputs": [], - "name": "ExitedValidatorsCountCannotDecrease", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidContractVersionIncrement", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "etherValue", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "depositsCount", - "type": "uint256" - } - ], - "name": "InvalidDepositsValue", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidFeeSum", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidMaxDepositPerBlockValue", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidMinDepositBlockDistance", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidPriorityExitShareThreshold", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "actual", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "expected", - "type": "uint256" - } - ], - "name": "InvalidPublicKeysBatchLength", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "code", - "type": "uint256" - } - ], - "name": "InvalidReportData", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "actual", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "expected", - "type": "uint256" - } - ], - "name": "InvalidSignaturesBatchLength", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidStakeShareLimit", - "type": "error" - }, - { - "inputs": [], - "name": "NonZeroContractVersionOnInit", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "reportedExitedValidatorsCount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "depositedValidatorsCount", - "type": "uint256" - } - ], - "name": "ReportedExitedValidatorsExceedDeposited", - "type": "error" - }, - { - "inputs": [], - "name": "StakingModuleAddressExists", - "type": "error" - }, - { - "inputs": [], - "name": "StakingModuleNotActive", - "type": "error" - }, - { - "inputs": [], - "name": "StakingModuleStatusTheSame", - "type": "error" - }, - { - "inputs": [], - "name": "StakingModuleUnregistered", - "type": "error" - }, - { - "inputs": [], - "name": "StakingModuleWrongName", - "type": "error" - }, - { - "inputs": [], - "name": "StakingModulesLimitExceeded", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "expected", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "received", - "type": "uint256" - } - ], - "name": "UnexpectedContractVersion", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "currentModuleExitedValidatorsCount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "currentNodeOpExitedValidatorsCount", - "type": "uint256" - } - ], - "name": "UnexpectedCurrentValidatorsCount", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "newModuleTotalExitedValidatorsCount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "newModuleTotalExitedValidatorsCountInStakingRouter", - "type": "uint256" - } - ], - "name": "UnexpectedFinalExitedValidatorsCount", - "type": "error" - }, - { - "inputs": [], - "name": "UnrecoverableModuleError", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAddressAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAddressLido", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAddressStakingModule", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "version", - "type": "uint256" - } - ], - "name": "ContractVersionSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "stakingModuleId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "lowLevelRevertData", - "type": "bytes" - } - ], - "name": "ExitedAndStuckValidatorsCountsUpdateFailed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "stakingModuleId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "lowLevelRevertData", - "type": "bytes" - } - ], - "name": "RewardsMintedReportFailed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "previousAdminRole", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "newAdminRole", - "type": "bytes32" - } - ], - "name": "RoleAdminChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "RoleGranted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "RoleRevoked", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "stakingModuleId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "stakingModule", - "type": "address" - }, - { - "indexed": false, - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "indexed": false, - "internalType": "address", - "name": "createdBy", - "type": "address" - } - ], - "name": "StakingModuleAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "stakingModuleId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "unreportedExitedValidatorsCount", - "type": "uint256" - } - ], - "name": "StakingModuleExitedValidatorsIncompleteReporting", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "stakingModuleId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "stakingModuleFee", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "treasuryFee", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "setBy", - "type": "address" - } - ], - "name": "StakingModuleFeesSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "stakingModuleId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "maxDepositsPerBlock", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "setBy", - "type": "address" - } - ], - "name": "StakingModuleMaxDepositsPerBlockSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "stakingModuleId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "minDepositBlockDistance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "setBy", - "type": "address" - } - ], - "name": "StakingModuleMinDepositBlockDistanceSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "stakingModuleId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "stakeShareLimit", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "priorityExitShareThreshold", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "setBy", - "type": "address" - } - ], - "name": "StakingModuleShareLimitSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "stakingModuleId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "enum StakingRouter.StakingModuleStatus", - "name": "status", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "address", - "name": "setBy", - "type": "address" - } - ], - "name": "StakingModuleStatusSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "stakingModuleId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "StakingRouterETHDeposited", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "withdrawalCredentials", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "address", - "name": "setBy", - "type": "address" - } - ], - "name": "WithdrawalCredentialsSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "stakingModuleId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "lowLevelRevertData", - "type": "bytes" - } - ], - "name": "WithdrawalsCredentialsChangeFailed", - "type": "event" - }, - { - "inputs": [], - "name": "DEFAULT_ADMIN_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "DEPOSIT_CONTRACT", - "outputs": [ - { - "internalType": "contract IDepositContract", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "FEE_PRECISION_POINTS", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MANAGE_WITHDRAWAL_CREDENTIALS_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MAX_STAKING_MODULES_COUNT", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MAX_STAKING_MODULE_NAME_LENGTH", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "REPORT_EXITED_VALIDATORS_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "REPORT_REWARDS_MINTED_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "REPORT_VALIDATOR_EXITING_STATUS_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "STAKING_MODULE_MANAGE_ROLE", - "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": "view", - "type": "function" - }, - { - "inputs": [], - "name": "UNSAFE_SET_EXITED_VALIDATORS_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "_name", - "type": "string" - }, - { - "internalType": "address", - "name": "_stakingModuleAddress", - "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" - } - ], - "name": "addStakingModule", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_nodeOperatorIds", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "_vettedSigningKeysCounts", - "type": "bytes" - } - ], - "name": "decreaseStakingModuleVettedKeysCountByNodeOperator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_depositsCount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_depositCalldata", - "type": "bytes" - } - ], - "name": "deposit", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [], - "name": "finalizeUpgrade_v3", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - } - ], - "name": "getAllNodeOperatorDigests", - "outputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "isActive", - "type": "bool" - }, - { - "components": [ - { - "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" - } - ], - "internalType": "struct StakingRouter.NodeOperatorSummary", - "name": "summary", - "type": "tuple" - } - ], - "internalType": "struct StakingRouter.NodeOperatorDigest[]", - "name": "", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getAllStakingModuleDigests", - "outputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "nodeOperatorsCount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "activeNodeOperatorsCount", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint24", - "name": "id", - "type": "uint24" - }, - { - "internalType": "address", - "name": "stakingModuleAddress", - "type": "address" - }, - { - "internalType": "uint16", - "name": "stakingModuleFee", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "treasuryFee", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "stakeShareLimit", - "type": "uint16" - }, - { - "internalType": "uint8", - "name": "status", - "type": "uint8" - }, - { - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "internalType": "uint64", - "name": "lastDepositAt", - "type": "uint64" - }, - { - "internalType": "uint256", - "name": "lastDepositBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "exitedValidatorsCount", - "type": "uint256" - }, - { - "internalType": "uint16", - "name": "priorityExitShareThreshold", - "type": "uint16" - }, - { - "internalType": "uint64", - "name": "maxDepositsPerBlock", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "minDepositBlockDistance", - "type": "uint64" - } - ], - "internalType": "struct StakingRouter.StakingModule", - "name": "state", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "totalExitedValidators", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "totalDepositedValidators", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "depositableValidatorsCount", - "type": "uint256" - } - ], - "internalType": "struct StakingRouter.StakingModuleSummary", - "name": "summary", - "type": "tuple" - } - ], - "internalType": "struct StakingRouter.StakingModuleDigest[]", - "name": "", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getContractVersion", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_depositsCount", - "type": "uint256" - } - ], - "name": "getDepositsAllocation", - "outputs": [ - { - "internalType": "uint256", - "name": "allocated", - "type": "uint256" - }, - { - "internalType": "uint256[]", - "name": "allocations", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getLido", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - }, - { - "internalType": "uint256[]", - "name": "_nodeOperatorIds", - "type": "uint256[]" - } - ], - "name": "getNodeOperatorDigests", - "outputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "isActive", - "type": "bool" - }, - { - "components": [ - { - "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" - } - ], - "internalType": "struct StakingRouter.NodeOperatorSummary", - "name": "summary", - "type": "tuple" - } - ], - "internalType": "struct StakingRouter.NodeOperatorDigest[]", - "name": "digests", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_offset", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_limit", - "type": "uint256" - } - ], - "name": "getNodeOperatorDigests", - "outputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "isActive", - "type": "bool" - }, - { - "components": [ - { - "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" - } - ], - "internalType": "struct StakingRouter.NodeOperatorSummary", - "name": "summary", - "type": "tuple" - } - ], - "internalType": "struct StakingRouter.NodeOperatorDigest[]", - "name": "", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_nodeOperatorId", - "type": "uint256" - } - ], - "name": "getNodeOperatorSummary", - "outputs": [ - { - "components": [ - { - "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" - } - ], - "internalType": "struct StakingRouter.NodeOperatorSummary", - "name": "summary", - "type": "tuple" - } - ], - "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": "getStakingFeeAggregateDistribution", - "outputs": [ - { - "internalType": "uint96", - "name": "modulesFee", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "treasuryFee", - "type": "uint96" - }, - { - "internalType": "uint256", - "name": "basePrecision", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getStakingFeeAggregateDistributionE4Precision", - "outputs": [ - { - "internalType": "uint16", - "name": "modulesFee", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "treasuryFee", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - } - ], - "name": "getStakingModule", - "outputs": [ - { - "components": [ - { - "internalType": "uint24", - "name": "id", - "type": "uint24" - }, - { - "internalType": "address", - "name": "stakingModuleAddress", - "type": "address" - }, - { - "internalType": "uint16", - "name": "stakingModuleFee", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "treasuryFee", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "stakeShareLimit", - "type": "uint16" - }, - { - "internalType": "uint8", - "name": "status", - "type": "uint8" - }, - { - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "internalType": "uint64", - "name": "lastDepositAt", - "type": "uint64" - }, - { - "internalType": "uint256", - "name": "lastDepositBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "exitedValidatorsCount", - "type": "uint256" - }, - { - "internalType": "uint16", - "name": "priorityExitShareThreshold", - "type": "uint16" - }, - { - "internalType": "uint64", - "name": "maxDepositsPerBlock", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "minDepositBlockDistance", - "type": "uint64" - } - ], - "internalType": "struct StakingRouter.StakingModule", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - } - ], - "name": "getStakingModuleActiveValidatorsCount", - "outputs": [ - { - "internalType": "uint256", - "name": "activeValidatorsCount", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "_stakingModuleIds", - "type": "uint256[]" - } - ], - "name": "getStakingModuleDigests", - "outputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "nodeOperatorsCount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "activeNodeOperatorsCount", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint24", - "name": "id", - "type": "uint24" - }, - { - "internalType": "address", - "name": "stakingModuleAddress", - "type": "address" - }, - { - "internalType": "uint16", - "name": "stakingModuleFee", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "treasuryFee", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "stakeShareLimit", - "type": "uint16" - }, - { - "internalType": "uint8", - "name": "status", - "type": "uint8" - }, - { - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "internalType": "uint64", - "name": "lastDepositAt", - "type": "uint64" - }, - { - "internalType": "uint256", - "name": "lastDepositBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "exitedValidatorsCount", - "type": "uint256" - }, - { - "internalType": "uint16", - "name": "priorityExitShareThreshold", - "type": "uint16" - }, - { - "internalType": "uint64", - "name": "maxDepositsPerBlock", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "minDepositBlockDistance", - "type": "uint64" - } - ], - "internalType": "struct StakingRouter.StakingModule", - "name": "state", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "totalExitedValidators", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "totalDepositedValidators", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "depositableValidatorsCount", - "type": "uint256" - } - ], - "internalType": "struct StakingRouter.StakingModuleSummary", - "name": "summary", - "type": "tuple" - } - ], - "internalType": "struct StakingRouter.StakingModuleDigest[]", - "name": "digests", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getStakingModuleIds", - "outputs": [ - { - "internalType": "uint256[]", - "name": "stakingModuleIds", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - } - ], - "name": "getStakingModuleIsActive", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - } - ], - "name": "getStakingModuleIsDepositsPaused", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - } - ], - "name": "getStakingModuleIsStopped", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - } - ], - "name": "getStakingModuleLastDepositBlock", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_maxDepositsValue", - "type": "uint256" - } - ], - "name": "getStakingModuleMaxDepositsCount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - } - ], - "name": "getStakingModuleMaxDepositsPerBlock", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - } - ], - "name": "getStakingModuleMinDepositBlockDistance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - } - ], - "name": "getStakingModuleNonce", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - } - ], - "name": "getStakingModuleStatus", - "outputs": [ - { - "internalType": "enum StakingRouter.StakingModuleStatus", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - } - ], - "name": "getStakingModuleSummary", - "outputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "totalExitedValidators", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "totalDepositedValidators", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "depositableValidatorsCount", - "type": "uint256" - } - ], - "internalType": "struct StakingRouter.StakingModuleSummary", - "name": "summary", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getStakingModules", - "outputs": [ - { - "components": [ - { - "internalType": "uint24", - "name": "id", - "type": "uint24" - }, - { - "internalType": "address", - "name": "stakingModuleAddress", - "type": "address" - }, - { - "internalType": "uint16", - "name": "stakingModuleFee", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "treasuryFee", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "stakeShareLimit", - "type": "uint16" - }, - { - "internalType": "uint8", - "name": "status", - "type": "uint8" - }, - { - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "internalType": "uint64", - "name": "lastDepositAt", - "type": "uint64" - }, - { - "internalType": "uint256", - "name": "lastDepositBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "exitedValidatorsCount", - "type": "uint256" - }, - { - "internalType": "uint16", - "name": "priorityExitShareThreshold", - "type": "uint16" - }, - { - "internalType": "uint64", - "name": "maxDepositsPerBlock", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "minDepositBlockDistance", - "type": "uint64" - } - ], - "internalType": "struct StakingRouter.StakingModule[]", - "name": "res", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getStakingModulesCount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getStakingRewardsDistribution", - "outputs": [ - { - "internalType": "address[]", - "name": "recipients", - "type": "address[]" - }, - { - "internalType": "uint256[]", - "name": "stakingModuleIds", - "type": "uint256[]" - }, - { - "internalType": "uint96[]", - "name": "stakingModuleFees", - "type": "uint96[]" - }, - { - "internalType": "uint96", - "name": "totalFee", - "type": "uint96" - }, - { - "internalType": "uint256", - "name": "precisionPoints", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getTotalFeeE4Precision", - "outputs": [ - { - "internalType": "uint16", - "name": "totalFee", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getWithdrawalCredentials", - "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": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - } - ], - "name": "hasStakingModule", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_admin", - "type": "address" - }, - { - "internalType": "address", - "name": "_lido", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "_withdrawalCredentials", - "type": "bytes32" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_nodeOperatorId", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_publicKey", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "_withdrawalRequestPaidFee", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_exitType", - "type": "uint256" - } - ], - "name": "onValidatorExitTriggered", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "onValidatorsCountsByNodeOperatorReportingFinished", - "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": [ - { - "internalType": "uint256[]", - "name": "_stakingModuleIds", - "type": "uint256[]" - }, - { - "internalType": "uint256[]", - "name": "_totalShares", - "type": "uint256[]" - } - ], - "name": "reportRewardsMinted", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_nodeOperatorIds", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "_exitedValidatorsCounts", - "type": "bytes" - } - ], - "name": "reportStakingModuleExitedValidatorsCountByNodeOperator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_nodeOperatorId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_proofSlotTimestamp", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_publicKey", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "_eligibleToExitInSec", - "type": "uint256" - } - ], - "name": "reportValidatorExitDelay", - "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": "_stakingModuleId", - "type": "uint256" - }, - { - "internalType": "enum StakingRouter.StakingModuleStatus", - "name": "_status", - "type": "uint8" - } - ], - "name": "setStakingModuleStatus", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_withdrawalCredentials", - "type": "bytes32" - } - ], - "name": "setWithdrawalCredentials", - "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": "_stakingModuleId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_nodeOperatorId", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "_triggerUpdateFinish", - "type": "bool" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "currentModuleExitedValidatorsCount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "currentNodeOperatorExitedValidatorsCount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "newModuleExitedValidatorsCount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "newNodeOperatorExitedValidatorsCount", - "type": "uint256" - } - ], - "internalType": "struct StakingRouter.ValidatorsCountsCorrection", - "name": "_correction", - "type": "tuple" - } - ], - "name": "unsafeSetExitedValidatorsCount", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "_stakingModuleIds", - "type": "uint256[]" - }, - { - "internalType": "uint256[]", - "name": "_exitedValidatorsCounts", - "type": "uint256[]" - } - ], - "name": "updateExitedValidatorsCountByStakingModule", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_nodeOperatorId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_refundedValidatorsCount", - "type": "uint256" - } - ], - "name": "updateRefundedValidatorsCount", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - }, - { - "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" - } - ], - "name": "updateStakingModule", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_stakingModuleId", - "type": "uint256" - }, - { - "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" - }, - { - "stateMutability": "payable", - "type": "receive" - } -] +[{"inputs":[{"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","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":"AllocationExceedsLimit","type":"error"},{"inputs":[],"name":"AmountNotAlignedToGwei","type":"error"},{"inputs":[],"name":"ArraysLengthMismatch","type":"error"},{"inputs":[],"name":"DirectETHTransfer","type":"error"},{"inputs":[],"name":"EmptyKeysList","type":"error"},{"inputs":[],"name":"ExitedValidatorsCountCannotDecrease","type":"error"},{"inputs":[],"name":"InconsistentFeeSum","type":"error"},{"inputs":[],"name":"InvalidAmountGwei","type":"error"},{"inputs":[],"name":"InvalidFeeSum","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"InvalidMaxDepositPerBlockValue","type":"error"},{"inputs":[],"name":"InvalidMinDepositBlockDistance","type":"error"},{"inputs":[],"name":"InvalidPriorityExitShareThreshold","type":"error"},{"inputs":[{"internalType":"uint256","name":"code","type":"uint256"}],"name":"InvalidReportData","type":"error"},{"inputs":[],"name":"InvalidStakeShareLimit","type":"error"},{"inputs":[],"name":"ModuleReturnExceedTarget","type":"error"},{"inputs":[],"name":"NotAuthorized","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[],"name":"OracleExtraDataNotSubmitted","type":"error"},{"inputs":[{"internalType":"uint256","name":"reportedExitedValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"depositedValidatorsCount","type":"uint256"}],"name":"ReportedExitedValidatorsExceedDeposited","type":"error"},{"inputs":[],"name":"StakingModuleAddressExists","type":"error"},{"inputs":[],"name":"StakingModuleNotActive","type":"error"},{"inputs":[],"name":"StakingModuleStatusTheSame","type":"error"},{"inputs":[],"name":"StakingModuleUnregistered","type":"error"},{"inputs":[],"name":"StakingModuleWrongName","type":"error"},{"inputs":[],"name":"StakingModulesLimitExceeded","type":"error"},{"inputs":[{"internalType":"uint256","name":"currentModuleExitedValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"currentNodeOpExitedValidatorsCount","type":"uint256"}],"name":"UnexpectedCurrentValidatorsCount","type":"error"},{"inputs":[{"internalType":"uint256","name":"newModuleTotalExitedValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"newModuleTotalExitedValidatorsCountInStakingRouter","type":"uint256"}],"name":"UnexpectedFinalExitedValidatorsCount","type":"error"},{"inputs":[{"internalType":"uint256","name":"expectedId","type":"uint256"},{"internalType":"uint256","name":"actualId","type":"uint256"}],"name":"UnexpectedModuleId","type":"error"},{"inputs":[],"name":"UnrecoverableModuleError","type":"error"},{"inputs":[],"name":"WrongPubkeyLength","type":"error"},{"inputs":[],"name":"WrongWithdrawalCredentialsType","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"inputs":[],"name":"ZeroArgument","type":"error"},{"inputs":[],"name":"ZeroDeposits","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"DepositableEthReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"lowLevelRevertData","type":"bytes"}],"name":"ExitedAndStuckValidatorsCountsUpdateFailed","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":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"lowLevelRevertData","type":"bytes"}],"name":"RewardsMintedReportFailed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"address","name":"stakingModule","type":"address"},{"indexed":false,"internalType":"string","name":"name","type":"string"},{"indexed":false,"internalType":"address","name":"createdBy","type":"address"}],"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":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"unreportedExitedValidatorsCount","type":"uint256"}],"name":"StakingModuleExitedValidatorsIncompleteReporting","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"stakingModuleFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"treasuryFee","type":"uint256"},{"indexed":false,"internalType":"address","name":"setBy","type":"address"}],"name":"StakingModuleFeesSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"maxDepositsPerBlock","type":"uint256"},{"indexed":false,"internalType":"address","name":"setBy","type":"address"}],"name":"StakingModuleMaxDepositsPerBlockSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"minDepositBlockDistance","type":"uint256"},{"indexed":false,"internalType":"address","name":"setBy","type":"address"}],"name":"StakingModuleMinDepositBlockDistanceSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"stakeShareLimit","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"priorityExitShareThreshold","type":"uint256"},{"indexed":false,"internalType":"address","name":"setBy","type":"address"}],"name":"StakingModuleShareLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"enum StakingModuleStatus","name":"status","type":"uint8"},{"indexed":false,"internalType":"address","name":"setBy","type":"address"}],"name":"StakingModuleStatusSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"StakingRouterETHDeposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"withdrawalCredentials","type":"bytes32"},{"indexed":false,"internalType":"address","name":"setBy","type":"address"}],"name":"WithdrawalCredentialsSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"lowLevelRevertData","type":"bytes"}],"name":"WithdrawalsCredentialsChangeFailed","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEPOSIT_CONTRACT","outputs":[{"internalType":"contract IDepositContract","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FEE_PRECISION_POINTS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_EFFECTIVE_BALANCE_WC_TYPE_01","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_EFFECTIVE_BALANCE_WC_TYPE_02","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_STAKING_MODULES_COUNT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"MAX_STAKING_MODULE_NAME_LENGTH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"REPORT_EXITED_VALIDATORS_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REPORT_REWARDS_MINTED_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REPORT_VALIDATOR_EXITING_STATUS_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STAKING_MODULE_MANAGE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"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","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"address","name":"_stakingModuleAddress","type":"address"},{"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","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"canDeposit","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"bytes","name":"_nodeOperatorIds","type":"bytes"},{"internalType":"bytes","name":"_vettedSigningKeysCounts","type":"bytes"}],"name":"decreaseStakingModuleVettedKeysCountByNodeOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"bytes","name":"_depositCalldata","type":"bytes"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"finalizeUpgrade_v4","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getAllNodeOperatorDigests","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bool","name":"isActive","type":"bool"},{"components":[{"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"}],"internalType":"struct NodeOperatorSummary","name":"summary","type":"tuple"}],"internalType":"struct NodeOperatorDigest[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllStakingModuleDigests","outputs":[{"components":[{"internalType":"uint256","name":"nodeOperatorsCount","type":"uint256"},{"internalType":"uint256","name":"activeNodeOperatorsCount","type":"uint256"},{"components":[{"internalType":"uint24","name":"id","type":"uint24"},{"internalType":"address","name":"stakingModuleAddress","type":"address"},{"internalType":"uint16","name":"stakingModuleFee","type":"uint16"},{"internalType":"uint16","name":"treasuryFee","type":"uint16"},{"internalType":"uint16","name":"stakeShareLimit","type":"uint16"},{"internalType":"uint8","name":"status","type":"uint8"},{"internalType":"string","name":"name","type":"string"},{"internalType":"uint64","name":"lastDepositAt","type":"uint64"},{"internalType":"uint256","name":"lastDepositBlock","type":"uint256"},{"internalType":"uint256","name":"exitedValidatorsCount","type":"uint256"},{"internalType":"uint16","name":"priorityExitShareThreshold","type":"uint16"},{"internalType":"uint64","name":"maxDepositsPerBlock","type":"uint64"},{"internalType":"uint64","name":"minDepositBlockDistance","type":"uint64"},{"internalType":"uint8","name":"withdrawalCredentialsType","type":"uint8"},{"internalType":"uint64","name":"validatorsBalanceGwei","type":"uint64"}],"internalType":"struct StakingModule","name":"state","type":"tuple"},{"components":[{"internalType":"uint256","name":"totalExitedValidators","type":"uint256"},{"internalType":"uint256","name":"totalDepositedValidators","type":"uint256"},{"internalType":"uint256","name":"depositableValidatorsCount","type":"uint256"}],"internalType":"struct StakingModuleSummary","name":"summary","type":"tuple"}],"internalType":"struct StakingModuleDigest[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getContractVersion","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_depositAmount","type":"uint256"},{"internalType":"bool","name":"_isTopUp","type":"bool"}],"name":"getDepositAllocations","outputs":[{"internalType":"uint256","name":"totalAllocated","type":"uint256"},{"internalType":"uint256[]","name":"allocated","type":"uint256[]"},{"internalType":"uint256[]","name":"newAllocations","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"moduleId","type":"uint256"}],"name":"getModuleValidatorsBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"uint256[]","name":"_nodeOperatorIds","type":"uint256[]"}],"name":"getNodeOperatorDigests","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bool","name":"isActive","type":"bool"},{"components":[{"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"}],"internalType":"struct NodeOperatorSummary","name":"summary","type":"tuple"}],"internalType":"struct NodeOperatorDigest[]","name":"digests","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"uint256","name":"_offset","type":"uint256"},{"internalType":"uint256","name":"_limit","type":"uint256"}],"name":"getNodeOperatorDigests","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bool","name":"isActive","type":"bool"},{"components":[{"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"}],"internalType":"struct NodeOperatorSummary","name":"summary","type":"tuple"}],"internalType":"struct NodeOperatorDigest[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"uint256","name":"_nodeOperatorId","type":"uint256"}],"name":"getNodeOperatorSummary","outputs":[{"components":[{"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"}],"internalType":"struct NodeOperatorSummary","name":"summary","type":"tuple"}],"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":"getStakingFeeAggregateDistribution","outputs":[{"internalType":"uint96","name":"modulesFee","type":"uint96"},{"internalType":"uint96","name":"treasuryFee","type":"uint96"},{"internalType":"uint256","name":"basePrecision","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStakingFeeAggregateDistributionE4Precision","outputs":[{"internalType":"uint16","name":"modulesFee","type":"uint16"},{"internalType":"uint16","name":"treasuryFee","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getStakingModule","outputs":[{"components":[{"internalType":"uint24","name":"id","type":"uint24"},{"internalType":"address","name":"stakingModuleAddress","type":"address"},{"internalType":"uint16","name":"stakingModuleFee","type":"uint16"},{"internalType":"uint16","name":"treasuryFee","type":"uint16"},{"internalType":"uint16","name":"stakeShareLimit","type":"uint16"},{"internalType":"uint8","name":"status","type":"uint8"},{"internalType":"string","name":"name","type":"string"},{"internalType":"uint64","name":"lastDepositAt","type":"uint64"},{"internalType":"uint256","name":"lastDepositBlock","type":"uint256"},{"internalType":"uint256","name":"exitedValidatorsCount","type":"uint256"},{"internalType":"uint16","name":"priorityExitShareThreshold","type":"uint16"},{"internalType":"uint64","name":"maxDepositsPerBlock","type":"uint64"},{"internalType":"uint64","name":"minDepositBlockDistance","type":"uint64"},{"internalType":"uint8","name":"withdrawalCredentialsType","type":"uint8"},{"internalType":"uint64","name":"validatorsBalanceGwei","type":"uint64"}],"internalType":"struct StakingModule","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getStakingModuleActiveValidatorsCount","outputs":[{"internalType":"uint256","name":"activeValidatorsCount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_stakingModuleIds","type":"uint256[]"}],"name":"getStakingModuleDigests","outputs":[{"components":[{"internalType":"uint256","name":"nodeOperatorsCount","type":"uint256"},{"internalType":"uint256","name":"activeNodeOperatorsCount","type":"uint256"},{"components":[{"internalType":"uint24","name":"id","type":"uint24"},{"internalType":"address","name":"stakingModuleAddress","type":"address"},{"internalType":"uint16","name":"stakingModuleFee","type":"uint16"},{"internalType":"uint16","name":"treasuryFee","type":"uint16"},{"internalType":"uint16","name":"stakeShareLimit","type":"uint16"},{"internalType":"uint8","name":"status","type":"uint8"},{"internalType":"string","name":"name","type":"string"},{"internalType":"uint64","name":"lastDepositAt","type":"uint64"},{"internalType":"uint256","name":"lastDepositBlock","type":"uint256"},{"internalType":"uint256","name":"exitedValidatorsCount","type":"uint256"},{"internalType":"uint16","name":"priorityExitShareThreshold","type":"uint16"},{"internalType":"uint64","name":"maxDepositsPerBlock","type":"uint64"},{"internalType":"uint64","name":"minDepositBlockDistance","type":"uint64"},{"internalType":"uint8","name":"withdrawalCredentialsType","type":"uint8"},{"internalType":"uint64","name":"validatorsBalanceGwei","type":"uint64"}],"internalType":"struct StakingModule","name":"state","type":"tuple"},{"components":[{"internalType":"uint256","name":"totalExitedValidators","type":"uint256"},{"internalType":"uint256","name":"totalDepositedValidators","type":"uint256"},{"internalType":"uint256","name":"depositableValidatorsCount","type":"uint256"}],"internalType":"struct StakingModuleSummary","name":"summary","type":"tuple"}],"internalType":"struct StakingModuleDigest[]","name":"digests","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStakingModuleIds","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getStakingModuleIsActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getStakingModuleIsDepositsPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getStakingModuleIsStopped","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getStakingModuleLastDepositBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"uint256","name":"_maxDepositsValue","type":"uint256"}],"name":"getStakingModuleMaxDepositsCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getStakingModuleMaxDepositsPerBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getStakingModuleMinDepositBlockDistance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getStakingModuleNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getStakingModuleStatus","outputs":[{"internalType":"enum StakingModuleStatus","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getStakingModuleSummary","outputs":[{"components":[{"internalType":"uint256","name":"totalExitedValidators","type":"uint256"},{"internalType":"uint256","name":"totalDepositedValidators","type":"uint256"},{"internalType":"uint256","name":"depositableValidatorsCount","type":"uint256"}],"internalType":"struct StakingModuleSummary","name":"summary","type":"tuple"}],"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","outputs":[{"components":[{"internalType":"uint24","name":"id","type":"uint24"},{"internalType":"address","name":"stakingModuleAddress","type":"address"},{"internalType":"uint16","name":"stakingModuleFee","type":"uint16"},{"internalType":"uint16","name":"treasuryFee","type":"uint16"},{"internalType":"uint16","name":"stakeShareLimit","type":"uint16"},{"internalType":"uint8","name":"status","type":"uint8"},{"internalType":"string","name":"name","type":"string"},{"internalType":"uint64","name":"lastDepositAt","type":"uint64"},{"internalType":"uint256","name":"lastDepositBlock","type":"uint256"},{"internalType":"uint256","name":"exitedValidatorsCount","type":"uint256"},{"internalType":"uint16","name":"priorityExitShareThreshold","type":"uint16"},{"internalType":"uint64","name":"maxDepositsPerBlock","type":"uint64"},{"internalType":"uint64","name":"minDepositBlockDistance","type":"uint64"},{"internalType":"uint8","name":"withdrawalCredentialsType","type":"uint8"},{"internalType":"uint64","name":"validatorsBalanceGwei","type":"uint64"}],"internalType":"struct StakingModule[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStakingModulesCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStakingRewardsDistribution","outputs":[{"internalType":"address[]","name":"recipients","type":"address[]"},{"internalType":"uint256[]","name":"stakingModuleIds","type":"uint256[]"},{"internalType":"uint96[]","name":"stakingModuleFees","type":"uint96[]"},{"internalType":"uint96","name":"totalFee","type":"uint96"},{"internalType":"uint256","name":"precisionPoints","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalFeeE4Precision","outputs":[{"internalType":"uint16","name":"totalFee","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalModulesValidatorsBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWithdrawalCredentials","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":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"hasStakingModule","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_admin","type":"address"},{"internalType":"bytes32","name":"_withdrawalCredentials","type":"bytes32"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"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","name":"_withdrawalRequestPaidFee","type":"uint256"},{"internalType":"uint256","name":"_exitType","type":"uint256"}],"name":"onValidatorExitTriggered","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"onValidatorsCountsByNodeOperatorReportingFinished","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"receiveDepositableEther","outputs":[],"stateMutability":"payable","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":"_stakingModuleIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_totalShares","type":"uint256[]"}],"name":"reportRewardsMinted","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"bytes","name":"_nodeOperatorIds","type":"bytes"},{"internalType":"bytes","name":"_exitedValidatorsCounts","type":"bytes"}],"name":"reportStakingModuleExitedValidatorsCountByNodeOperator","outputs":[],"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":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"uint256","name":"_nodeOperatorId","type":"uint256"},{"internalType":"uint256","name":"_proofSlotTimestamp","type":"uint256"},{"internalType":"bytes","name":"_publicKey","type":"bytes"},{"internalType":"uint256","name":"_eligibleToExitInSec","type":"uint256"}],"name":"reportValidatorExitDelay","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":"_stakingModuleId","type":"uint256"},{"internalType":"enum StakingModuleStatus","name":"_status","type":"uint8"}],"name":"setStakingModuleStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_withdrawalCredentials","type":"bytes32"}],"name":"setWithdrawalCredentials","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":"_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":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"uint256","name":"_nodeOperatorId","type":"uint256"},{"internalType":"bool","name":"_triggerUpdateFinish","type":"bool"},{"components":[{"internalType":"uint256","name":"currentModuleExitedValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"currentNodeOperatorExitedValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"newModuleExitedValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"newNodeOperatorExitedValidatorsCount","type":"uint256"}],"internalType":"struct ValidatorsCountsCorrection","name":"_correction","type":"tuple"}],"name":"unsafeSetExitedValidatorsCount","outputs":[],"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":[{"internalType":"uint256[]","name":"_stakingModuleIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_exitedValidatorsCounts","type":"uint256[]"}],"name":"updateExitedValidatorsCountByStakingModule","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"uint16","name":"_stakeShareLimit","type":"uint16"},{"internalType":"uint16","name":"_priorityExitShareThreshold","type":"uint16"}],"name":"updateModuleShares","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"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"}],"name":"updateStakingModule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"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"},{"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/UpgradeVoteScript.json b/interfaces/UpgradeVoteScript.json new file mode 100644 index 00000000..8e05371f --- /dev/null +++ b/interfaces/UpgradeVoteScript.json @@ -0,0 +1 @@ +[{"inputs":[{"components":[{"internalType":"address","name":"upgradeTemplate","type":"address"},{"internalType":"address","name":"timeConstraints","type":"address"}],"internalType":"struct UpgradeVoteScript.ScriptParams","name":"_params","type":"tuple"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"DG_ITEMS_COUNT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ENABLED_DAY_SPAN_END","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ENABLED_DAY_SPAN_START","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TEMPLATE","outputs":[{"internalType":"contract UpgradeTemplate","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":"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"},{"inputs":[],"name":"params","outputs":[{"internalType":"address","name":"upgradeTemplate","type":"address"},{"internalType":"address","name":"timeConstraints","type":"address"}],"stateMutability":"view","type":"function"}] diff --git a/interfaces/WithdrawalsManagerProxy.json b/interfaces/WithdrawalsManagerProxy.json index 92f4356b..29a0e78d 100644 --- a/interfaces/WithdrawalsManagerProxy.json +++ b/interfaces/WithdrawalsManagerProxy.json @@ -1,81 +1 @@ -[ - { "inputs": [], "stateMutability": "nonpayable", "type": "constructor" }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "previousAdmin", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "newAdmin", - "type": "address" - } - ], - "name": "AdminChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "implementation", - "type": "address" - } - ], - "name": "Upgraded", - "type": "event" - }, - { "stateMutability": "payable", "type": "fallback" }, - { - "inputs": [], - "name": "implementation", - "outputs": [{ "internalType": "address", "name": "", "type": "address" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { "internalType": "address", "name": "newAdmin", "type": "address" } - ], - "name": "proxy_changeAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "proxy_getAdmin", - "outputs": [{ "internalType": "address", "name": "", "type": "address" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "proxy_getIsOssified", - "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newImplementation", - "type": "address" - }, - { "internalType": "bytes", "name": "setupCalldata", "type": "bytes" } - ], - "name": "proxy_upgradeTo", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { "stateMutability": "payable", "type": "receive" } -] +[{"inputs":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"address","name":"impl","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"implementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newAdmin","type":"address"}],"name":"proxy_changeAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"proxy_getAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxy_getIsOssified","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"setupCalldata","type":"bytes"}],"name":"proxy_upgradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}] diff --git a/scripts/upgrade_2026_04_14_hoodi_protocol_upgrade.py b/scripts/upgrade_2026_04_14_hoodi_protocol_upgrade.py new file mode 100644 index 00000000..4bea3a8d --- /dev/null +++ b/scripts/upgrade_2026_04_14_hoodi_protocol_upgrade.py @@ -0,0 +1,166 @@ +""" +TODO Vote 2026_04_14 + +Uses deployed `UpgradeVoteScript` as the source of truth for both: +1. DG items returned by `getVoteItems()` +2. Immediate voting items returned by `getVotingVoteItems()` + +Replace the TODO values below after the Hoodi deployment. +""" + +from typing import Dict, List, Tuple + +from brownie import interface + +from utils.config import 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 + + +# ============================== Addresses =================================== +UPGRADE_VOTE_SCRIPT = "0x0000000000000000000000000000000000000000" + + +# ============================= Description ================================== +DG_PROPOSAL_METADATA = "Upgrade Lido protocol contracts on Ethereum Hoodi testnet" +DG_SUBMISSION_DESCRIPTION = "1. Submit a Dual Governance proposal for the Lido protocol upgrade on Ethereum Hoodi testnet" +IPFS_DESCRIPTION = """ +**Lido protocol upgrade on Ethereum Hoodi testnet** + +**Dual Governance proposal** +1. Submit a Dual Governance proposal for the Lido protocol upgrade on Ethereum Hoodi testnet. +1.1. Call UpgradeTemplate.startUpgrade +1.2. Upgrade LidoLocator implementation +1.3. Grant Aragon APP_MANAGER_ROLE to the AGENT +1.4. Set Lido implementation in Kernel +1.5. Revoke Aragon APP_MANAGER_ROLE from the AGENT +1.6. Upgrade StakingRouter implementation and finalize v4 migration +1.7. Grant STAKING_MODULE_SHARE_MANAGE_ROLE to EasyTrack executor +1.8. Upgrade AccountingOracle implementation +1.9. Upgrade Accounting implementation +1.10. Upgrade WithdrawalVault implementation +1.11. Upgrade and finalize CSM v3 +1.12. Upgrade and finalize ParametersRegistry v3 +1.13. Upgrade and finalize FeeOracle v3 +1.14. Upgrade VettedGate implementation +1.15. Upgrade and finalize Accounting v3 +1.16. Upgrade and finalize FeeDistributor v3 +1.17. Upgrade ExitPenalties implementation +1.18. Upgrade ValidatorStrikes implementation +1.19. Point ValidatorStrikes to the new Ejector +1.20. Grant REPORT_GENERAL_DELAYED_PENALTY_ROLE +1.21. Grant SETTLE_GENERAL_DELAYED_PENALTY_ROLE +1.22. Revoke REPORT_EL_REWARDS_STEALING_PENALTY_ROLE +1.23. Revoke SETTLE_EL_REWARDS_STEALING_PENALTY_ROLE +1.24. Revoke VERIFIER_ROLE from old verifier +1.25. Grant VERIFIER_ROLE to VerifierV3 +1.26. Grant REPORT_REGULAR_WITHDRAWN_VALIDATORS_ROLE to VerifierV3 +1.27. Grant REPORT_SLASHED_WITHDRAWN_VALIDATORS_ROLE to Easy Track +1.28. Revoke CREATE_NODE_OPERATOR_ROLE from old PermissionlessGate +1.29. Grant CREATE_NODE_OPERATOR_ROLE to new PermissionlessGate +1.30. Revoke PAUSE_ROLE from old gate seal on CSModule +1.31. Revoke PAUSE_ROLE from old gate seal on Accounting +1.32. Revoke PAUSE_ROLE from old gate seal on FeeOracle +1.33. Revoke PAUSE_ROLE from old gate seal on VettedGate +1.34. Revoke PAUSE_ROLE from old gate seal on old Verifier +1.35. Revoke PAUSE_ROLE from old gate seal on old Ejector +1.36. Revoke PAUSE_ROLE from reseal manager on old Verifier +1.37. Revoke RESUME_ROLE from reseal manager on old Verifier +1.38. Revoke PAUSE_ROLE from reseal manager on old Ejector +1.39. Revoke RESUME_ROLE from reseal manager on old Ejector +1.40. Revoke START_REFERRAL_SEASON_ROLE +1.41. Revoke END_REFERRAL_SEASON_ROLE +1.42. Grant PAUSE_ROLE to GateSealV3 on CSModule +1.43. Grant PAUSE_ROLE to GateSealV3 on Accounting +1.44. Grant PAUSE_ROLE to GateSealV3 on FeeOracle +1.45. Grant PAUSE_ROLE to GateSealV3 on VettedGate +1.46. Grant MANAGE_GENERAL_PENALTIES_AND_CHARGES_ROLE to penaltiesManager +1.47. Revoke REQUEST_BURN_SHARES_ROLE from CSM Accounting +1.48. Grant REQUEST_BURN_MY_STETH_ROLE to CSM Accounting +1.49. Revoke TWG full-withdrawal role from old Ejector +1.50. Grant TWG full-withdrawal role to new Ejector +1.51. Add Curated module to StakingRouter +1.52. Grant REQUEST_BURN_MY_STETH_ROLE to Curated Accounting +1.53. Grant TWG full-withdrawal role to Curated Ejector +1.54. Grant RESUME_ROLE to agent on Curated module +1.55. Resume Curated module +1.56. Revoke RESUME_ROLE from agent on Curated module +1.57. Update Curated HashConsensus initial epoch +1.58. Call UpgradeTemplate.finishUpgrade + +**Immediate voting items** +2. Add UpdateStakingModuleShareLimits ET factory +3. Add AllowConsolidationPair ET factory +4. Add CreateOrUpdateOperatorGroup ET factory +""" + + +# ================================ Main ====================================== +def get_dg_items() -> List[Tuple[str, str]]: + omnibus = interface.UpgradeVoteScript(UPGRADE_VOTE_SCRIPT) + 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() -> Tuple[List[str], List[Tuple[str, str]]]: + omnibus = interface.UpgradeVoteScript(UPGRADE_VOTE_SCRIPT) + + vote_desc_items: List[str] = [] + call_script_items: List[Tuple[str, str]] = [] + + dg_items = get_dg_items() + + 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): + vote_desc_items, call_script_items = get_vote_items() + vote_items = bake_vote_items(list(vote_desc_items), list(call_script_items)) + + desc_ipfs = ( + calculate_vote_ipfs_description(IPFS_DESCRIPTION) + if silent + else upload_vote_ipfs_description(IPFS_DESCRIPTION) + ) + + vote_id, tx = confirm_vote_script(vote_items, silent, desc_ipfs) and list( + create_vote(vote_items, tx_params, desc_ipfs=desc_ipfs) + ) + + assert interface.UpgradeVoteScript(UPGRADE_VOTE_SCRIPT).isValidVoteScript(vote_id, DG_PROPOSAL_METADATA) + + return vote_id, tx + + +def main(): + tx_params: Dict[str, str] = {"from": get_deployer_account().address} + if get_is_live(): + tx_params["priority_fee"] = get_priority_fee() + + vote_id, _ = start_vote(tx_params=tx_params, silent=False) + vote_id >= 0 and print(f"Vote created: {vote_id}.") + + +def start_and_execute_vote_on_fork_manual(): + if get_is_live(): + raise Exception("This script is for local testing only.") + + tx_params = {"from": get_deployer_account()} + vote_id, _ = start_vote(tx_params=tx_params, silent=True) + print(f"Vote created: {vote_id}.") + pass_and_exec_dao_vote(int(vote_id), step_by_step=True) diff --git a/scripts/upgrade_2026_04_14_hoodi_protocol_upgrade_no_dg.py b/scripts/upgrade_2026_04_14_hoodi_protocol_upgrade_no_dg.py new file mode 100644 index 00000000..89cc5f4a --- /dev/null +++ b/scripts/upgrade_2026_04_14_hoodi_protocol_upgrade_no_dg.py @@ -0,0 +1,176 @@ +""" +TODO Vote 2026_04_14 (no DG) + +Uses deployed `UpgradeVoteScript` as the source of truth for both: +1. Former DG items returned by `getVoteItems()` +2. Immediate voting items returned by `getVotingVoteItems()` + +Unlike the DG-enabled version, this script flattens both sets of items into a +single Aragon vote and executes them directly. + +Replace the TODO values below after the Hoodi deployment. +""" + +from typing import Dict, List, Tuple + +from brownie import interface + +from utils.config import get_deployer_account, get_is_live, get_priority_fee +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 + + +# ============================== Addresses =================================== +UPGRADE_VOTE_SCRIPT = "0x0000000000000000000000000000000000000000" + + +# ============================= Description ================================== +IPFS_DESCRIPTION = """ +**Lido protocol upgrade on Ethereum Hoodi testnet (direct vote, no Dual Governance)** + +This variant executes all upgrade items returned by the deployed `UpgradeVoteScript` +directly as part of the Aragon vote, without wrapping the former DG items into +`DualGovernance.submitProposal`. + +**Directly executed upgrade items** +1. Call UpgradeTemplate.startUpgrade +2. Upgrade LidoLocator implementation +3. Grant Aragon APP_MANAGER_ROLE to the AGENT +4. Set Lido implementation in Kernel +5. Revoke Aragon APP_MANAGER_ROLE from the AGENT +6. Upgrade StakingRouter implementation and finalize v4 migration +7. Grant STAKING_MODULE_SHARE_MANAGE_ROLE to EasyTrack executor +8. Upgrade AccountingOracle implementation +9. Upgrade Accounting implementation +10. Upgrade WithdrawalVault implementation +11. Upgrade and finalize CSM v3 +12. Upgrade and finalize ParametersRegistry v3 +13. Upgrade and finalize FeeOracle v3 +14. Upgrade VettedGate implementation +15. Upgrade and finalize Accounting v3 +16. Upgrade and finalize FeeDistributor v3 +17. Upgrade ExitPenalties implementation +18. Upgrade ValidatorStrikes implementation +19. Point ValidatorStrikes to the new Ejector +20. Grant REPORT_GENERAL_DELAYED_PENALTY_ROLE +21. Grant SETTLE_GENERAL_DELAYED_PENALTY_ROLE +22. Revoke REPORT_EL_REWARDS_STEALING_PENALTY_ROLE +23. Revoke SETTLE_EL_REWARDS_STEALING_PENALTY_ROLE +24. Revoke VERIFIER_ROLE from old verifier +25. Grant VERIFIER_ROLE to VerifierV3 +26. Grant REPORT_REGULAR_WITHDRAWN_VALIDATORS_ROLE to VerifierV3 +27. Grant REPORT_SLASHED_WITHDRAWN_VALIDATORS_ROLE to Easy Track +28. Revoke CREATE_NODE_OPERATOR_ROLE from old PermissionlessGate +29. Grant CREATE_NODE_OPERATOR_ROLE to new PermissionlessGate +30. Revoke PAUSE_ROLE from old gate seal on CSModule +31. Revoke PAUSE_ROLE from old gate seal on Accounting +32. Revoke PAUSE_ROLE from old gate seal on FeeOracle +33. Revoke PAUSE_ROLE from old gate seal on VettedGate +34. Revoke PAUSE_ROLE from old gate seal on old Verifier +35. Revoke PAUSE_ROLE from old gate seal on old Ejector +36. Revoke PAUSE_ROLE from reseal manager on old Verifier +37. Revoke RESUME_ROLE from reseal manager on old Verifier +38. Revoke PAUSE_ROLE from reseal manager on old Ejector +39. Revoke RESUME_ROLE from reseal manager on old Ejector +40. Revoke START_REFERRAL_SEASON_ROLE +41. Revoke END_REFERRAL_SEASON_ROLE +42. Grant PAUSE_ROLE to GateSealV3 on CSModule +43. Grant PAUSE_ROLE to GateSealV3 on Accounting +44. Grant PAUSE_ROLE to GateSealV3 on FeeOracle +45. Grant PAUSE_ROLE to GateSealV3 on VettedGate +46. Grant MANAGE_GENERAL_PENALTIES_AND_CHARGES_ROLE to penaltiesManager +47. Revoke REQUEST_BURN_SHARES_ROLE from CSM Accounting +48. Grant REQUEST_BURN_MY_STETH_ROLE to CSM Accounting +49. Revoke TWG full-withdrawal role from old Ejector +50. Grant TWG full-withdrawal role to new Ejector +51. Add Curated module to StakingRouter +52. Grant REQUEST_BURN_MY_STETH_ROLE to Curated Accounting +53. Grant TWG full-withdrawal role to Curated Ejector +54. Grant RESUME_ROLE to agent on Curated module +55. Resume Curated module +56. Revoke RESUME_ROLE from agent on Curated module +57. Update Curated HashConsensus initial epoch +58. Call UpgradeTemplate.finishUpgrade + +**Immediate voting items** +59. Add UpdateStakingModuleShareLimits ET factory +60. Add AllowConsolidationPair ET factory +61. Add CreateOrUpdateOperatorGroup ET factory +""" + + +def _extract_vote_items(vote_items) -> Tuple[List[str], List[Tuple[str, str]]]: + vote_desc_items: List[str] = [] + call_script_items: List[Tuple[str, str]] = [] + + for desc, call_script in vote_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 get_direct_upgrade_items() -> Tuple[List[str], List[Tuple[str, str]]]: + omnibus = interface.UpgradeVoteScript(UPGRADE_VOTE_SCRIPT) + direct_items = omnibus.getVoteItems() + + assert len(direct_items) == omnibus.DG_ITEMS_COUNT(), "Unexpected number of former DG items" + + return _extract_vote_items(direct_items) + + +def get_immediate_vote_items() -> Tuple[List[str], List[Tuple[str, str]]]: + omnibus = interface.UpgradeVoteScript(UPGRADE_VOTE_SCRIPT) + voting_items = omnibus.getVotingVoteItems() + + assert len(voting_items) == omnibus.VOTING_ITEMS_COUNT(), "Unexpected number of immediate voting items" + + return _extract_vote_items(voting_items) + + +# ================================ Main ====================================== +def get_vote_items() -> Tuple[List[str], List[Tuple[str, str]]]: + direct_vote_desc_items, direct_call_script_items = get_direct_upgrade_items() + voting_vote_desc_items, voting_call_script_items = get_immediate_vote_items() + + return ( + direct_vote_desc_items + voting_vote_desc_items, + direct_call_script_items + voting_call_script_items, + ) + + +def start_vote(tx_params: Dict[str, str], silent: bool = False): + vote_desc_items, call_script_items = get_vote_items() + vote_items = bake_vote_items(list(vote_desc_items), list(call_script_items)) + + desc_ipfs = ( + calculate_vote_ipfs_description(IPFS_DESCRIPTION) + if silent + else upload_vote_ipfs_description(IPFS_DESCRIPTION) + ) + + vote_id, tx = confirm_vote_script(vote_items, silent, desc_ipfs) and list( + create_vote(vote_items, tx_params, desc_ipfs=desc_ipfs) + ) + + return vote_id, tx + + +def main(): + tx_params: Dict[str, str] = {"from": get_deployer_account().address} + if get_is_live(): + tx_params["priority_fee"] = get_priority_fee() + + vote_id, _ = start_vote(tx_params=tx_params, silent=False) + vote_id >= 0 and print(f"Vote created: {vote_id}.") + + +def start_and_execute_vote_on_fork_manual(): + if get_is_live(): + raise Exception("This script is for local testing only.") + + tx_params = {"from": get_deployer_account()} + vote_id, _ = start_vote(tx_params=tx_params, silent=True) + print(f"Vote created: {vote_id}.") + pass_and_exec_dao_vote(int(vote_id), step_by_step=True) diff --git a/tests/test_2026_04_14_hoodi_protocol_upgrade.py b/tests/test_2026_04_14_hoodi_protocol_upgrade.py new file mode 100644 index 00000000..cd80631e --- /dev/null +++ b/tests/test_2026_04_14_hoodi_protocol_upgrade.py @@ -0,0 +1,252 @@ +import pytest + +from brownie import chain, interface +from brownie.network.transaction import TransactionReceipt + +from utils.easy_track import create_permissions +from utils.test.tx_tracing_helpers import ( + count_vote_items_by_events, + display_dg_events, + display_voting_events, + group_dg_events_from_receipt, + group_voting_events_from_receipt, +) +from utils.evm_script import encode_call_script +from utils.dual_governance import PROPOSAL_STATUS +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 +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_04_14_hoodi_protocol_upgrade import ( + start_vote, + get_vote_items, + get_dg_items, + UPGRADE_VOTE_SCRIPT, + DG_PROPOSAL_METADATA, + IPFS_DESCRIPTION, +) + + +# ============================================================================ +# ============================== Constants =================================== +# ============================================================================ +VOTING = "0x49B3512c44891bef83F8967d075121Bd1b07a01B" +AGENT = "0x0534aA41907c9631fae990960bCC72d75fA7cfeD" +EMERGENCY_PROTECTED_TIMELOCK = "0x0A5E22782C0Bd4AddF10D771f0bF0406B038282d" +DUAL_GOVERNANCE = "0x9CAaCCc62c66d817CC59c44780D1b722359795bF" +DUAL_GOVERNANCE_ADMIN_EXECUTOR = "0x0eCc17597D292271836691358B22340b78F3035B" +EASYTRACK = "0x284D91a7D47850d21A6DEaaC6E538AC7E5E6fc2a" +STAKING_ROUTER = "0xCc820558B39ee15C7C45B59390B503b83fb499A8" + +UPDATE_STAKING_MODULE_SHARE_LIMITS_FACTORY = "0x0000000000000000000000000000000000000000" # TODO +ALLOW_CONSOLIDATION_PAIR_FACTORY = "0x0000000000000000000000000000000000000000" # TODO +CREATE_OR_UPDATE_OPERATOR_GROUP_FACTORY = "0x0000000000000000000000000000000000000000" # TODO +CONSOLIDATION_MIGRATOR = "0x0000000000000000000000000000000000000000" # TODO +META_REGISTRY = "0x0000000000000000000000000000000000000000" # TODO + + +# ============================================================================ +# ============================= Test params ================================== +# ============================================================================ +EXPECTED_VOTE_ID = None +EXPECTED_DG_PROPOSAL_ID = None +EXPECTED_VOTE_EVENTS_COUNT = None +EXPECTED_DG_EVENTS_FROM_AGENT = None +EXPECTED_DG_EVENTS_COUNT = None +IPFS_DESCRIPTION_HASH = None + + +def _is_placeholder_address(value: str) -> bool: + return value in ("", "0x0000000000000000000000000000000000000000") + + +def _is_placeholder_text(value: str) -> bool: + return "TODO:" in value + + +pytestmark = pytest.mark.skipif( + _is_placeholder_address(UPGRADE_VOTE_SCRIPT) + or _is_placeholder_address(UPDATE_STAKING_MODULE_SHARE_LIMITS_FACTORY) + or _is_placeholder_address(ALLOW_CONSOLIDATION_PAIR_FACTORY) + or _is_placeholder_address(CREATE_OR_UPDATE_OPERATOR_GROUP_FACTORY) + or _is_placeholder_address(CONSOLIDATION_MIGRATOR) + or _is_placeholder_address(META_REGISTRY) + or _is_placeholder_text(DG_PROPOSAL_METADATA) + or _is_placeholder_text(IPFS_DESCRIPTION), + reason="Fill TODO values in the active Hoodi upgrade vote script before running the dedicated test.", +) + + +@pytest.fixture(scope="module") +def dual_governance_proposal_calls(): + dg_items = get_dg_items() + + proposal_calls = [] + for target, data in dg_items: + proposal_calls.append( + { + "target": target, + "value": 0, + "data": data, + } + ) + + return proposal_calls + + +def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_governance_proposal_calls): + voting = interface.Voting(VOTING) + agent = interface.Agent(AGENT) + timelock = interface.EmergencyProtectedTimelock(EMERGENCY_PROTECTED_TIMELOCK) + dual_governance = interface.DualGovernance(DUAL_GOVERNANCE) + easy_track = interface.EasyTrack(EASYTRACK) + staking_router = interface.StakingRouter(STAKING_ROUTER) + consolidation_migrator = interface.ConsolidationMigrator(CONSOLIDATION_MIGRATOR) + meta_registry = interface.IMetaRegistry(META_REGISTRY) + + vote_desc_items, call_script_items = get_vote_items() + dg_items = get_dg_items() + + expected_vote_events_count = EXPECTED_VOTE_EVENTS_COUNT or len(call_script_items) + expected_dg_events_from_agent = EXPECTED_DG_EVENTS_FROM_AGENT or len(dg_items) + expected_dg_events_count = EXPECTED_DG_EVENTS_COUNT or len(dg_items) + expected_ipfs_description_hash = IPFS_DESCRIPTION_HASH or calculate_vote_ipfs_description(IPFS_DESCRIPTION)["cid"] + + # ========================================================================= + # ======================== 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) + + 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() + assert UPDATE_STAKING_MODULE_SHARE_LIMITS_FACTORY not in initial_factories + assert ALLOW_CONSOLIDATION_PAIR_FACTORY not in initial_factories + assert CREATE_OR_UPDATE_OPERATOR_GROUP_FACTORY not in initial_factories + + 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() + assert UPDATE_STAKING_MODULE_SHARE_LIMITS_FACTORY in new_factories + assert ALLOW_CONSOLIDATION_PAIR_FACTORY in new_factories + assert CREATE_OR_UPDATE_OPERATOR_GROUP_FACTORY in new_factories + + 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() + + validate_dual_governance_submit_event( + vote_events[0], + proposal_id=expected_dg_proposal_id, + proposer=VOTING, + executor=DUAL_GOVERNANCE_ADMIN_EXECUTOR, + metadata=DG_PROPOSAL_METADATA, + proposal_calls=dual_governance_proposal_calls, + ) + + validate_evmscript_factory_added_event( + event=vote_events[1], + p=EVMScriptFactoryAdded( + factory_addr=UPDATE_STAKING_MODULE_SHARE_LIMITS_FACTORY, + permissions=create_permissions(staking_router, "updateModuleShares"), + ), + emitted_by=easy_track, + ) + + validate_evmscript_factory_added_event( + event=vote_events[2], + p=EVMScriptFactoryAdded( + factory_addr=ALLOW_CONSOLIDATION_PAIR_FACTORY, + permissions=create_permissions(consolidation_migrator, "allowPair"), + ), + emitted_by=easy_track, + ) + + validate_evmscript_factory_added_event( + event=vote_events[3], + p=EVMScriptFactoryAdded( + factory_addr=CREATE_OR_UPDATE_OPERATOR_GROUP_FACTORY, + permissions=create_permissions(meta_registry, "createOrUpdateOperatorGroup"), + ), + 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 live Hoodi vote.") + + # ========================================================================= + # ======================= Execute DG Proposal ============================= + # ========================================================================= + if expected_dg_proposal_id is not None: + details = timelock.getProposalDetails(expected_dg_proposal_id) + if details["status"] != PROPOSAL_STATUS["executed"]: + # ========================================================================= + # ================== DG before proposal executed checks =================== + # ========================================================================= + + # TODO Acceptance tests (before DG state) + + # TODO Scenario tests (before DG state) + + if details["status"] == PROPOSAL_STATUS["submitted"]: + chain.sleep(timelock.getAfterSubmitDelay() + 1) + dual_governance.scheduleProposal(expected_dg_proposal_id, {"from": stranger}) + + if timelock.getProposalDetails(expected_dg_proposal_id)["status"] == PROPOSAL_STATUS["scheduled"]: + chain.sleep(timelock.getAfterScheduleDelay() + 1) + + dg_tx: TransactionReceipt = timelock.execute(expected_dg_proposal_id, {"from": stranger}) + display_dg_events(dg_tx) + dg_events = group_dg_events_from_receipt( + dg_tx, + timelock=EMERGENCY_PROTECTED_TIMELOCK, + admin_executor=DUAL_GOVERNANCE_ADMIN_EXECUTOR, + ) + assert count_vote_items_by_events(dg_tx, agent.address) == expected_dg_events_from_agent + assert len(dg_events) == expected_dg_events_count + + # TODO validate all DG events + + # ========================================================================= + # ==================== After DG proposal executed checks ================== + # ========================================================================= + + # TODO Acceptance tests (after DG state) + + # TODO Scenario tests (after DG state) From e7745dae793b1741fea999650b3e086f152581fe Mon Sep 17 00:00:00 2001 From: Eddort Date: Thu, 23 Apr 2026 21:47:43 +0200 Subject: [PATCH 02/15] wip: srv3 + cm hoodi --- ...grade_2026_04_14_hoodi_protocol_upgrade.py | 115 +- ...2026_04_14_hoodi_protocol_upgrade_no_dg.py | 176 --- .../test_2026_04_14_hoodi_protocol_upgrade.py | 1146 ++++++++++++++++- 3 files changed, 1178 insertions(+), 259 deletions(-) delete mode 100644 scripts/upgrade_2026_04_14_hoodi_protocol_upgrade_no_dg.py diff --git a/scripts/upgrade_2026_04_14_hoodi_protocol_upgrade.py b/scripts/upgrade_2026_04_14_hoodi_protocol_upgrade.py index 4bea3a8d..c4c04088 100644 --- a/scripts/upgrade_2026_04_14_hoodi_protocol_upgrade.py +++ b/scripts/upgrade_2026_04_14_hoodi_protocol_upgrade.py @@ -8,11 +8,14 @@ Replace the TODO values below after the Hoodi deployment. """ -from typing import Dict, List, Tuple +import os + +from typing import Dict, List, Optional, Tuple from brownie import interface from utils.config import get_deployer_account, get_is_live, get_priority_fee +from utils.hoodi_upgrade import get_optional_upgrade_vote_script_address, get_upgrade_vote_script_address 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 @@ -20,7 +23,8 @@ # ============================== Addresses =================================== -UPGRADE_VOTE_SCRIPT = "0x0000000000000000000000000000000000000000" +UPGRADE_VOTE_SCRIPT = get_optional_upgrade_vote_script_address() +HOODI_DG_ONLY_ENV = "HOODI_DG_ONLY" # ============================= Description ================================== @@ -96,10 +100,88 @@ 4. Add CreateOrUpdateOperatorGroup ET factory """ +DG_ONLY_IPFS_DESCRIPTION = """ +**Lido protocol upgrade on Ethereum Hoodi testnet** + +**Dual Governance proposal** +1. Submit a Dual Governance proposal for the Lido protocol upgrade on Ethereum Hoodi testnet. +1.1. Call UpgradeTemplate.startUpgrade +1.2. Upgrade LidoLocator implementation +1.3. Grant Aragon APP_MANAGER_ROLE to the AGENT +1.4. Set Lido implementation in Kernel +1.5. Revoke Aragon APP_MANAGER_ROLE from the AGENT +1.6. Upgrade StakingRouter implementation and finalize v4 migration +1.7. Grant STAKING_MODULE_SHARE_MANAGE_ROLE to EasyTrack executor +1.8. Upgrade AccountingOracle implementation +1.9. Upgrade Accounting implementation +1.10. Upgrade WithdrawalVault implementation +1.11. Upgrade and finalize CSM v3 +1.12. Upgrade and finalize ParametersRegistry v3 +1.13. Upgrade and finalize FeeOracle v3 +1.14. Upgrade VettedGate implementation +1.15. Upgrade and finalize Accounting v3 +1.16. Upgrade and finalize FeeDistributor v3 +1.17. Upgrade ExitPenalties implementation +1.18. Upgrade ValidatorStrikes implementation +1.19. Point ValidatorStrikes to the new Ejector +1.20. Grant REPORT_GENERAL_DELAYED_PENALTY_ROLE +1.21. Grant SETTLE_GENERAL_DELAYED_PENALTY_ROLE +1.22. Revoke REPORT_EL_REWARDS_STEALING_PENALTY_ROLE +1.23. Revoke SETTLE_EL_REWARDS_STEALING_PENALTY_ROLE +1.24. Revoke VERIFIER_ROLE from old verifier +1.25. Grant VERIFIER_ROLE to VerifierV3 +1.26. Grant REPORT_REGULAR_WITHDRAWN_VALIDATORS_ROLE to VerifierV3 +1.27. Grant REPORT_SLASHED_WITHDRAWN_VALIDATORS_ROLE to Easy Track +1.28. Revoke CREATE_NODE_OPERATOR_ROLE from old PermissionlessGate +1.29. Grant CREATE_NODE_OPERATOR_ROLE to new PermissionlessGate +1.30. Revoke PAUSE_ROLE from old gate seal on CSModule +1.31. Revoke PAUSE_ROLE from old gate seal on Accounting +1.32. Revoke PAUSE_ROLE from old gate seal on FeeOracle +1.33. Revoke PAUSE_ROLE from old gate seal on VettedGate +1.34. Revoke PAUSE_ROLE from old gate seal on old Verifier +1.35. Revoke PAUSE_ROLE from old gate seal on old Ejector +1.36. Revoke PAUSE_ROLE from reseal manager on old Verifier +1.37. Revoke RESUME_ROLE from reseal manager on old Verifier +1.38. Revoke PAUSE_ROLE from reseal manager on old Ejector +1.39. Revoke RESUME_ROLE from reseal manager on old Ejector +1.40. Revoke START_REFERRAL_SEASON_ROLE +1.41. Revoke END_REFERRAL_SEASON_ROLE +1.42. Grant PAUSE_ROLE to GateSealV3 on CSModule +1.43. Grant PAUSE_ROLE to GateSealV3 on Accounting +1.44. Grant PAUSE_ROLE to GateSealV3 on FeeOracle +1.45. Grant PAUSE_ROLE to GateSealV3 on VettedGate +1.46. Grant MANAGE_GENERAL_PENALTIES_AND_CHARGES_ROLE to penaltiesManager +1.47. Revoke REQUEST_BURN_SHARES_ROLE from CSM Accounting +1.48. Grant REQUEST_BURN_MY_STETH_ROLE to CSM Accounting +1.49. Revoke TWG full-withdrawal role from old Ejector +1.50. Grant TWG full-withdrawal role to new Ejector +1.51. Add Curated module to StakingRouter +1.52. Grant REQUEST_BURN_MY_STETH_ROLE to Curated Accounting +1.53. Grant TWG full-withdrawal role to Curated Ejector +1.54. Grant RESUME_ROLE to agent on Curated module +1.55. Resume Curated module +1.56. Revoke RESUME_ROLE from agent on Curated module +1.57. Update Curated HashConsensus initial epoch +1.58. Call UpgradeTemplate.finishUpgrade +""" + # ================================ Main ====================================== +def _get_upgrade_vote_script(): + return interface.UpgradeVoteScript(get_upgrade_vote_script_address()) + + +def is_dg_only_mode() -> bool: + return os.getenv(HOODI_DG_ONLY_ENV, "").lower() in ("1", "true", "yes", "on") + + +def get_ipfs_description(dg_only: Optional[bool] = None) -> str: + dg_only = is_dg_only_mode() if dg_only is None else dg_only + return DG_ONLY_IPFS_DESCRIPTION if dg_only else IPFS_DESCRIPTION + + def get_dg_items() -> List[Tuple[str, str]]: - omnibus = interface.UpgradeVoteScript(UPGRADE_VOTE_SCRIPT) + omnibus = _get_upgrade_vote_script() dg_items: List[Tuple[str, str]] = [] for _, call_script in omnibus.getVoteItems(): @@ -108,8 +190,9 @@ def get_dg_items() -> List[Tuple[str, str]]: return dg_items -def get_vote_items() -> Tuple[List[str], List[Tuple[str, str]]]: - omnibus = interface.UpgradeVoteScript(UPGRADE_VOTE_SCRIPT) +def get_vote_items(dg_only: Optional[bool] = None) -> Tuple[List[str], List[Tuple[str, str]]]: + dg_only = is_dg_only_mode() if dg_only is None else dg_only + omnibus = _get_upgrade_vote_script() vote_desc_items: List[str] = [] call_script_items: List[Tuple[str, str]] = [] @@ -120,29 +203,33 @@ def get_vote_items() -> Tuple[List[str], List[Tuple[str, str]]]: 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())) + if not dg_only: + 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): - vote_desc_items, call_script_items = get_vote_items() +def start_vote(tx_params: Dict[str, str], silent: bool = False, dg_only: Optional[bool] = None): + dg_only = is_dg_only_mode() if dg_only is None else dg_only + vote_desc_items, call_script_items = get_vote_items(dg_only=dg_only) vote_items = bake_vote_items(list(vote_desc_items), list(call_script_items)) + ipfs_description = get_ipfs_description(dg_only=dg_only) desc_ipfs = ( - calculate_vote_ipfs_description(IPFS_DESCRIPTION) + calculate_vote_ipfs_description(ipfs_description) if silent - else upload_vote_ipfs_description(IPFS_DESCRIPTION) + 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) ) - assert interface.UpgradeVoteScript(UPGRADE_VOTE_SCRIPT).isValidVoteScript(vote_id, DG_PROPOSAL_METADATA) + if not dg_only: + assert _get_upgrade_vote_script().isValidVoteScript(vote_id, DG_PROPOSAL_METADATA) return vote_id, tx diff --git a/scripts/upgrade_2026_04_14_hoodi_protocol_upgrade_no_dg.py b/scripts/upgrade_2026_04_14_hoodi_protocol_upgrade_no_dg.py deleted file mode 100644 index 89cc5f4a..00000000 --- a/scripts/upgrade_2026_04_14_hoodi_protocol_upgrade_no_dg.py +++ /dev/null @@ -1,176 +0,0 @@ -""" -TODO Vote 2026_04_14 (no DG) - -Uses deployed `UpgradeVoteScript` as the source of truth for both: -1. Former DG items returned by `getVoteItems()` -2. Immediate voting items returned by `getVotingVoteItems()` - -Unlike the DG-enabled version, this script flattens both sets of items into a -single Aragon vote and executes them directly. - -Replace the TODO values below after the Hoodi deployment. -""" - -from typing import Dict, List, Tuple - -from brownie import interface - -from utils.config import get_deployer_account, get_is_live, get_priority_fee -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 - - -# ============================== Addresses =================================== -UPGRADE_VOTE_SCRIPT = "0x0000000000000000000000000000000000000000" - - -# ============================= Description ================================== -IPFS_DESCRIPTION = """ -**Lido protocol upgrade on Ethereum Hoodi testnet (direct vote, no Dual Governance)** - -This variant executes all upgrade items returned by the deployed `UpgradeVoteScript` -directly as part of the Aragon vote, without wrapping the former DG items into -`DualGovernance.submitProposal`. - -**Directly executed upgrade items** -1. Call UpgradeTemplate.startUpgrade -2. Upgrade LidoLocator implementation -3. Grant Aragon APP_MANAGER_ROLE to the AGENT -4. Set Lido implementation in Kernel -5. Revoke Aragon APP_MANAGER_ROLE from the AGENT -6. Upgrade StakingRouter implementation and finalize v4 migration -7. Grant STAKING_MODULE_SHARE_MANAGE_ROLE to EasyTrack executor -8. Upgrade AccountingOracle implementation -9. Upgrade Accounting implementation -10. Upgrade WithdrawalVault implementation -11. Upgrade and finalize CSM v3 -12. Upgrade and finalize ParametersRegistry v3 -13. Upgrade and finalize FeeOracle v3 -14. Upgrade VettedGate implementation -15. Upgrade and finalize Accounting v3 -16. Upgrade and finalize FeeDistributor v3 -17. Upgrade ExitPenalties implementation -18. Upgrade ValidatorStrikes implementation -19. Point ValidatorStrikes to the new Ejector -20. Grant REPORT_GENERAL_DELAYED_PENALTY_ROLE -21. Grant SETTLE_GENERAL_DELAYED_PENALTY_ROLE -22. Revoke REPORT_EL_REWARDS_STEALING_PENALTY_ROLE -23. Revoke SETTLE_EL_REWARDS_STEALING_PENALTY_ROLE -24. Revoke VERIFIER_ROLE from old verifier -25. Grant VERIFIER_ROLE to VerifierV3 -26. Grant REPORT_REGULAR_WITHDRAWN_VALIDATORS_ROLE to VerifierV3 -27. Grant REPORT_SLASHED_WITHDRAWN_VALIDATORS_ROLE to Easy Track -28. Revoke CREATE_NODE_OPERATOR_ROLE from old PermissionlessGate -29. Grant CREATE_NODE_OPERATOR_ROLE to new PermissionlessGate -30. Revoke PAUSE_ROLE from old gate seal on CSModule -31. Revoke PAUSE_ROLE from old gate seal on Accounting -32. Revoke PAUSE_ROLE from old gate seal on FeeOracle -33. Revoke PAUSE_ROLE from old gate seal on VettedGate -34. Revoke PAUSE_ROLE from old gate seal on old Verifier -35. Revoke PAUSE_ROLE from old gate seal on old Ejector -36. Revoke PAUSE_ROLE from reseal manager on old Verifier -37. Revoke RESUME_ROLE from reseal manager on old Verifier -38. Revoke PAUSE_ROLE from reseal manager on old Ejector -39. Revoke RESUME_ROLE from reseal manager on old Ejector -40. Revoke START_REFERRAL_SEASON_ROLE -41. Revoke END_REFERRAL_SEASON_ROLE -42. Grant PAUSE_ROLE to GateSealV3 on CSModule -43. Grant PAUSE_ROLE to GateSealV3 on Accounting -44. Grant PAUSE_ROLE to GateSealV3 on FeeOracle -45. Grant PAUSE_ROLE to GateSealV3 on VettedGate -46. Grant MANAGE_GENERAL_PENALTIES_AND_CHARGES_ROLE to penaltiesManager -47. Revoke REQUEST_BURN_SHARES_ROLE from CSM Accounting -48. Grant REQUEST_BURN_MY_STETH_ROLE to CSM Accounting -49. Revoke TWG full-withdrawal role from old Ejector -50. Grant TWG full-withdrawal role to new Ejector -51. Add Curated module to StakingRouter -52. Grant REQUEST_BURN_MY_STETH_ROLE to Curated Accounting -53. Grant TWG full-withdrawal role to Curated Ejector -54. Grant RESUME_ROLE to agent on Curated module -55. Resume Curated module -56. Revoke RESUME_ROLE from agent on Curated module -57. Update Curated HashConsensus initial epoch -58. Call UpgradeTemplate.finishUpgrade - -**Immediate voting items** -59. Add UpdateStakingModuleShareLimits ET factory -60. Add AllowConsolidationPair ET factory -61. Add CreateOrUpdateOperatorGroup ET factory -""" - - -def _extract_vote_items(vote_items) -> Tuple[List[str], List[Tuple[str, str]]]: - vote_desc_items: List[str] = [] - call_script_items: List[Tuple[str, str]] = [] - - for desc, call_script in vote_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 get_direct_upgrade_items() -> Tuple[List[str], List[Tuple[str, str]]]: - omnibus = interface.UpgradeVoteScript(UPGRADE_VOTE_SCRIPT) - direct_items = omnibus.getVoteItems() - - assert len(direct_items) == omnibus.DG_ITEMS_COUNT(), "Unexpected number of former DG items" - - return _extract_vote_items(direct_items) - - -def get_immediate_vote_items() -> Tuple[List[str], List[Tuple[str, str]]]: - omnibus = interface.UpgradeVoteScript(UPGRADE_VOTE_SCRIPT) - voting_items = omnibus.getVotingVoteItems() - - assert len(voting_items) == omnibus.VOTING_ITEMS_COUNT(), "Unexpected number of immediate voting items" - - return _extract_vote_items(voting_items) - - -# ================================ Main ====================================== -def get_vote_items() -> Tuple[List[str], List[Tuple[str, str]]]: - direct_vote_desc_items, direct_call_script_items = get_direct_upgrade_items() - voting_vote_desc_items, voting_call_script_items = get_immediate_vote_items() - - return ( - direct_vote_desc_items + voting_vote_desc_items, - direct_call_script_items + voting_call_script_items, - ) - - -def start_vote(tx_params: Dict[str, str], silent: bool = False): - vote_desc_items, call_script_items = get_vote_items() - vote_items = bake_vote_items(list(vote_desc_items), list(call_script_items)) - - desc_ipfs = ( - calculate_vote_ipfs_description(IPFS_DESCRIPTION) - if silent - else upload_vote_ipfs_description(IPFS_DESCRIPTION) - ) - - vote_id, tx = confirm_vote_script(vote_items, silent, desc_ipfs) and list( - create_vote(vote_items, tx_params, desc_ipfs=desc_ipfs) - ) - - return vote_id, tx - - -def main(): - tx_params: Dict[str, str] = {"from": get_deployer_account().address} - if get_is_live(): - tx_params["priority_fee"] = get_priority_fee() - - vote_id, _ = start_vote(tx_params=tx_params, silent=False) - vote_id >= 0 and print(f"Vote created: {vote_id}.") - - -def start_and_execute_vote_on_fork_manual(): - if get_is_live(): - raise Exception("This script is for local testing only.") - - tx_params = {"from": get_deployer_account()} - vote_id, _ = start_vote(tx_params=tx_params, silent=True) - print(f"Vote created: {vote_id}.") - pass_and_exec_dao_vote(int(vote_id), step_by_step=True) diff --git a/tests/test_2026_04_14_hoodi_protocol_upgrade.py b/tests/test_2026_04_14_hoodi_protocol_upgrade.py index cd80631e..f6ad1b3b 100644 --- a/tests/test_2026_04_14_hoodi_protocol_upgrade.py +++ b/tests/test_2026_04_14_hoodi_protocol_upgrade.py @@ -1,9 +1,19 @@ +from typing import NamedTuple, Optional + import pytest -from brownie import chain, interface +from brownie import chain, convert, interface +from brownie.network.event import EventDict from brownie.network.transaction import TransactionReceipt -from utils.easy_track import create_permissions +from utils.config import network_name +from utils.hoodi_upgrade import ( + get_consolidation_migrator_address, + get_easy_track_new_factories, + get_meta_registry_address, + get_state_address, + get_upgrade_vote_script_address, +) from utils.test.tx_tracing_helpers import ( count_vote_items_by_events, display_dg_events, @@ -11,10 +21,16 @@ 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 +from utils.test.event_validators.aragon import ( + validate_aragon_grant_permission_event, + validate_aragon_revoke_permission_event, + validate_aragon_set_app_event, +) +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 from utils.voting import find_metadata_by_vote_id from utils.ipfs import calculate_vote_ipfs_description, get_lido_vote_cid_from_str @@ -23,12 +39,11 @@ # ============================== Import vote ================================= # ============================================================================ from scripts.upgrade_2026_04_14_hoodi_protocol_upgrade import ( + get_ipfs_description, start_vote, get_vote_items, get_dg_items, - UPGRADE_VOTE_SCRIPT, DG_PROPOSAL_METADATA, - IPFS_DESCRIPTION, ) @@ -40,14 +55,124 @@ EMERGENCY_PROTECTED_TIMELOCK = "0x0A5E22782C0Bd4AddF10D771f0bF0406B038282d" DUAL_GOVERNANCE = "0x9CAaCCc62c66d817CC59c44780D1b722359795bF" DUAL_GOVERNANCE_ADMIN_EXECUTOR = "0x0eCc17597D292271836691358B22340b78F3035B" -EASYTRACK = "0x284D91a7D47850d21A6DEaaC6E538AC7E5E6fc2a" +ACL = "0x78780e70Eae33e2935814a327f7dB6c01136cc62" +ARAGON_KERNEL = "0xA48DF029Fd2e5FCECB3886c5c2F60e3625A1E87d" +LIDO = "0x3508A952176b3c15387C97BE809eaffB1982176a" +LIDO_LOCATOR = "0xe2EF9536DAAAEBFf5b1c130957AB3E80056b06D8" STAKING_ROUTER = "0xCc820558B39ee15C7C45B59390B503b83fb499A8" - -UPDATE_STAKING_MODULE_SHARE_LIMITS_FACTORY = "0x0000000000000000000000000000000000000000" # TODO -ALLOW_CONSOLIDATION_PAIR_FACTORY = "0x0000000000000000000000000000000000000000" # TODO -CREATE_OR_UPDATE_OPERATOR_GROUP_FACTORY = "0x0000000000000000000000000000000000000000" # TODO -CONSOLIDATION_MIGRATOR = "0x0000000000000000000000000000000000000000" # TODO -META_REGISTRY = "0x0000000000000000000000000000000000000000" # TODO +ACCOUNTING_ORACLE = "0xcb883B1bD0a41512b42D2dB267F2A2cd919FB216" +VALIDATORS_EXIT_BUS_ORACLE = "0x8664d394C2B3278F26A1B44B967aEf99707eeAB2" +ACCOUNTING = "0x9b5b78D1C9A3238bF24662067e34c57c83E8c354" +WITHDRAWAL_VAULT = "0x4473dCDDbf77679A643BdB654dbd86D67F8d32f2" +TRIGGERABLE_WITHDRAWALS_GATEWAY = "0x6679090D92b08a2a686eF8614feECD8cDFE209db" +VALIDATOR_EXIT_DELAY_VERIFIER = "0xa5F5A9360275390fF9728262a29384399f38d2f0" +EASYTRACK_EVMSCRIPT_EXECUTOR = "0x79a20FD0FA36453B2F45eAbab19bfef43575Ba9E" +LIDO_IMPL = "0x6147270470A9Ee5b55c33EA71e32000E5d6D8E6B" +LIDO_APP_ID = "0x3ca7c3e38968823ccb4c78ea688df41356f182ae1d159e4ee608d30d68cef320" +CIRCUIT_BREAKER = "0x44a5789dFeDa59cD176Ab5709ec2F4829dE4d555" +CONSOLIDATION_GATEWAY = "0xce93710b849e0dC202AaC513837e05bEA9D7DdFD" +CURATED_MODULE_COMMITTEE = "0x84DffcfB232594975C608DE92544Ff239a24c9E9" +CSM = "0x79CEf36D84743222f37765204Bec41E92a93E59d" +CS_PARAMETERS_REGISTRY = "0xA4aD5236963f9Fe4229864712269D8d79B65C5Ad" +CS_FEE_ORACLE = "0xe7314f561B2e72f9543F1004e741bab6Fc51028B" +CS_VETTED_GATE = "0x10a254E724fe2b7f305F76f3F116a3969c53845f" +CS_ACCOUNTING = "0xA54b90BA34C5f326BC1485054080994e38FB4C60" +CS_FEE_DISTRIBUTOR = "0xaCd9820b0A2229a82dc1A0770307ce5522FF3582" +CS_EXIT_PENALTIES = "0xD259b31083Be841E5C85b2D481Cfc17C14276800" +CS_VALIDATOR_STRIKES = "0x8fBA385C3c334D251eE413e79d4D3890db98693c" +VERIFIER_V3 = "0xC96406b0eADdAC5708aFCa04DcCA67BAdC9642Fd" +OLD_VERIFIER = "0x1773b2Ff99A030F6000554Cb8A5Ec93145650cbA" +OLD_PERMISSIONLESS_GATE = "0x5553077102322689876A6AdFd48D75014c28acfb" +NEW_PERMISSIONLESS_GATE = "0xd7bD8D2A9888D1414c770B35ACF55890B15de26a" +OLD_DEPOSIT_SECURITY_MODULE = "0x2F0303F20E0795E6CCd17BD5efE791A586f28E03" +NEW_DEPOSIT_SECURITY_MODULE = "0x1a629bB7C0563650e46406Eb6764A2ba207a0eFE" +HOODI_LEGACY_STAKING_MODULE_MANAGER = "0xE28f573b732632fdE03BD5507A7d475383e8512E" +ICS_MANAGER = "0x4AF43Ee34a6fcD1fEcA1e1F832124C763561dA53" +CSM_GENERAL_DELAYED_PENALTY_REPORTER = ICS_MANAGER +CSM_PENALTIES_MANAGER = ICS_MANAGER +BURNER = "0xb2c99cd38a2636a6281a849C8de938B3eF4A7C3D" +OLD_CSM_EJECTOR = "0x777bd76326E4aDcD353b03AD45b33BAF41048476" +CSM_EJECTOR = "0xCAe028378d69D54dc8bF809e6C44CF751F997b80" +CURATED_MODULE = "0x87EB69Ae51317405FD285efD2326a4a11f6173b9" +CURATED_ACCOUNTING = "0x7f7356D29aCd915F1934220956c3305808ceB235" +CURATED_EJECTOR = "0xfDbde2B3554B69C84e0f8d7daB68D390Ff0f4394" +CURATED_HASH_CONSENSUS = "0x920883908A78c1554f682006a8aB32E62Be09F33" +LIDO_LOCATOR_IMPL = "0x9b110E022a13583679536B303d0C22467d1b567A" +STAKING_ROUTER_IMPL = "0x44d0b2B95d2C2bDF73FE4f5cD7E3A930494E5B1f" +ACCOUNTING_ORACLE_IMPL = "0x41bF10F28A1312f2241f86A2537A04b08e343C0a" +VALIDATORS_EXIT_BUS_ORACLE_IMPL = "0x86aeA211B30174b3ee5d294ECeaDbD7f1C575eF3" +ACCOUNTING_IMPL = "0xDB47544d5813f15116bf95c1cF2ff4dEdb2226fD" +WITHDRAWAL_VAULT_IMPL = "0xB97e67CC20bd2970E30341c0ECc7497d8A5b7342" +CSM_IMPL = "0x161b1DAa658fD0D78a4603860edd8Ed06f98F4cA" +CS_PARAMETERS_REGISTRY_IMPL = "0x58376D8B192813E85532b25685D948EB49c2A8B5" +CS_FEE_ORACLE_IMPL = "0x27d1Ff0353AF6b7480CBc902169d0F89b49334B5" +CS_VETTED_GATE_IMPL = "0x3b834c6d043F4CE5C61d84723bA737D405B2e276" +CS_ACCOUNTING_IMPL = "0x3a18675fFB2C37A4296dD794A7Ed94644225F881" +CS_FEE_DISTRIBUTOR_IMPL = "0x74c5be19CcD1a264899FbCf8dB1a64C1e3fb73Ac" +CS_EXIT_PENALTIES_IMPL = "0xf38A3DA25B417D83182EEDD30d00557d78c35C96" +CS_VALIDATOR_STRIKES_IMPL = "0x47F96DCD5cf3e94492CD050c00C9F6e33b3ca677" +DEFAULT_ADMIN_ROLE = "0x0000000000000000000000000000000000000000000000000000000000000000" +APP_MANAGER_ROLE = "0xb6d92708f3d4817afc106147d969e229ced5c46e65e0a5002a0d391287762bd0" +BUFFER_RESERVE_MANAGER_ROLE = "0x33969636f1fbf3d7d062d4de4a08e7bd3c46606ec28b3a4398d2665be559b921" +STAKING_MODULE_MANAGE_ROLE = "0x3105bcbf19d4417b73ae0e58d508a65ecf75665e46c2622d8521732de6080c48" +STAKING_MODULE_UNVETTING_ROLE = "0x240525496a9dc32284b17ce03b43e539e4bd81414634ee54395030d793463b57" +STAKING_MODULE_SHARE_MANAGE_ROLE = "0x43bf0e13900cfaa1b03ed5681dc143266597e29a1d6f9cbd84114f0ac21cd208" +REPORT_EXITED_VALIDATORS_ROLE = "0xc23292b191d95d2a7dd94fc6436eb44338fda9e1307d9394fd27c28157c1b33c" +REPORT_VALIDATOR_EXITING_STATUS_ROLE = "0xbe1bd143a0dde8a867d58aab054bfdb25250951665c4570e39abc3b3de3c2d6c" +REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE = "0x0766e72e5c008b3df8129fb356d9176eef8544f6241e078b7d61aff604f8812b" +REPORT_REWARDS_MINTED_ROLE = "0x779e5c23cb7a5bcb9bfe1e9a5165a00057f12bcdfd13e374540fdf1a1cd91137" +TW_EXIT_LIMIT_MANAGER_ROLE = "0x03c30da9b9e4d4789ac88a294d39a63058ca4a498804c2aa823e381df59d0cf4" +REPORT_GENERAL_DELAYED_PENALTY_ROLE = "0xa2c92d51d5647473735e9dfd5e2edf65bcf2fc2c139c95cbed53c19dc227c0b5" +SETTLE_GENERAL_DELAYED_PENALTY_ROLE = "0xe4c6f42648e5067520394b287613558d8b8a48bc7a320523da96c04d46253bda" +REPORT_EL_REWARDS_STEALING_PENALTY_ROLE = "0x59911a6aa08a72fe3824aec4500dc42335c6d0702b6d5c5c72ceb265a0de9302" +SETTLE_EL_REWARDS_STEALING_PENALTY_ROLE = "0xe85fdec10fe0f93d0792364051df7c3d73e37c17b3a954bffe593960e3cd3012" +VERIFIER_ROLE = "0x0ce23c3e399818cfee81a7ab0880f714e53d7672b08df0fa62f2843416e1ea09" +REPORT_REGULAR_WITHDRAWN_VALIDATORS_ROLE = "0xb169cb0459e6d91326174ff566a2fcc3c7bb31ef3d4d83bec1d5679c611ab094" +REPORT_SLASHED_WITHDRAWN_VALIDATORS_ROLE = "0x2dba60a7b2c6bc437f1868d48dc8e53a95d71e78cef88de0aff6d952ecff8daa" +CREATE_NODE_OPERATOR_ROLE = "0xc72a21b38830f4d6418a239e17db78b945cc7cfee674bac97fd596eaf0438478" +RESUME_ROLE = "0x2fc10cc8ae19568712f7a176fb4978616a610650813c9d05326c34abb62749c7" +START_REFERRAL_SEASON_ROLE = "0xc0bd4bb446c4ce6fd2289aa78c8ea233de3ad2b870bc787b2ba154e19c271f12" +END_REFERRAL_SEASON_ROLE = "0x4a1304957825c6a76938ccf907b92b9b872c8348083e23dae57e7e6111105d0c" +MANAGE_GENERAL_PENALTIES_AND_CHARGES_ROLE = "0x00b6097bf7ad894f88f786cd383df3190b971af96510047737d0cb2e9bd25558" +REQUEST_BURN_SHARES_ROLE = "0x4be29e0e4eb91f98f709d98803cba271592782e293b84a625e025cbb40197ba8" +REQUEST_BURN_MY_STETH_ROLE = "0x28186f938b759084eea36948ef1cd8b40ec8790a98d5f1a09b70879fe054e5cc" +ADD_FULL_WITHDRAWAL_REQUEST_ROLE = "0x15fac8ba7fe8dd5344b88c1915452ce66976f270d1cd793c3b0ab579cecd33c0" +EXIT_BALANCE_LIMIT_SET_TOPIC = "0x28a59cb43d86267095565f85c40c9110eb77192a738ef87891ba3696c423a531" +CIRCUIT_BREAKER_BLOCKER_ADDED_TOPIC = "0xd92c3c28ed17463268f864776463c4c2154f89b18156d3edf77c0e37d0476913" +CIRCUIT_BREAKER_COMMITTEE_ACTIVATED_TOPIC = "0x4ea9e94baeeb3668b47d8d9b4cc8f5a1784d783dd263d7d76f8c10d6a10aed44" +AO_CONTRACT_VERSION = 5 +AO_CONSENSUS_VERSION = 6 +AO_PREV_CONSENSUS_VERSION = 5 +VEBO_CONTRACT_VERSION = 3 +VEBO_CONSENSUS_VERSION = 5 +VEBO_PREV_CONSENSUS_VERSION = 4 +VEBO_MAX_VALIDATORS_PER_REPORT = 600 +VALIDATORS_EXIT_BUS_MAX_EXIT_BALANCE_ETH = 416000 +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 +TW_MAX_EXIT_REQUESTS = 250 +TW_EXITS_PER_FRAME = 1 +TW_FRAME_DURATION_IN_SEC = 240 +CURATED_MODULE_ID = 5 +CURATED_MODULE_NAME = "curated-onchain-v2" +CURATED_STAKE_SHARE_LIMIT = 2000 +CURATED_PRIORITY_EXIT_SHARE_THRESHOLD = 2500 +CURATED_STAKING_MODULE_FEE = 800 +CURATED_TREASURY_FEE = 200 +CURATED_MAX_DEPOSITS_PER_BLOCK = 30 +CURATED_MIN_DEPOSIT_BLOCK_DISTANCE = 25 +CURATED_INITIAL_EPOCH = 47480 +CURATED_EPOCHS_PER_FRAME = 1575 +# TODO: restore Easy Track checks when full ET flow is enabled again. +# EASYTRACK = "0x284D91a7D47850d21A6DEaaC6E538AC7E5E6fc2a" +# STAKING_ROUTER = "0xCc820558B39ee15C7C45B59390B503b83fb499A8" +# UPDATE_STAKING_MODULE_SHARE_LIMITS_FACTORY = "0x0000000000000000000000000000000000000000" +# ALLOW_CONSOLIDATION_PAIR_FACTORY = "0x0000000000000000000000000000000000000000" +# CREATE_OR_UPDATE_OPERATOR_GROUP_FACTORY = "0x0000000000000000000000000000000000000000" +# CONSOLIDATION_MIGRATOR = "0x0000000000000000000000000000000000000000" +# META_REGISTRY = "0x0000000000000000000000000000000000000000" # ============================================================================ @@ -56,34 +181,361 @@ EXPECTED_VOTE_ID = None EXPECTED_DG_PROPOSAL_ID = None EXPECTED_VOTE_EVENTS_COUNT = None -EXPECTED_DG_EVENTS_FROM_AGENT = None -EXPECTED_DG_EVENTS_COUNT = None +EXPECTED_DG_EVENTS_FROM_AGENT = 60 +EXPECTED_DG_EVENTS_COUNT = 60 IPFS_DESCRIPTION_HASH = None +DG_ONLY_MODE = True + + +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 + + +CURATED_MODULE_V2 = StakingModuleItem( + id=CURATED_MODULE_ID, + staking_module_address=CURATED_MODULE, + name=CURATED_MODULE_NAME, + staking_module_fee=CURATED_STAKING_MODULE_FEE, + stake_share_limit=CURATED_STAKE_SHARE_LIMIT, + treasury_fee=CURATED_TREASURY_FEE, + priority_exit_share_threshold=CURATED_PRIORITY_EXIT_SHARE_THRESHOLD, + max_deposits_per_block=CURATED_MAX_DEPOSITS_PER_BLOCK, + min_deposit_block_distance=CURATED_MIN_DEPOSIT_BLOCK_DISTANCE, +) def _is_placeholder_address(value: str) -> bool: - return value in ("", "0x0000000000000000000000000000000000000000") + normalized = str(value).lower() + return normalized in ("", "0x0000000000000000000000000000000000000000") def _is_placeholder_text(value: str) -> bool: return "TODO:" in value -pytestmark = pytest.mark.skipif( - _is_placeholder_address(UPGRADE_VOTE_SCRIPT) - or _is_placeholder_address(UPDATE_STAKING_MODULE_SHARE_LIMITS_FACTORY) - or _is_placeholder_address(ALLOW_CONSOLIDATION_PAIR_FACTORY) - or _is_placeholder_address(CREATE_OR_UPDATE_OPERATOR_GROUP_FACTORY) - or _is_placeholder_address(CONSOLIDATION_MIGRATOR) - or _is_placeholder_address(META_REGISTRY) - or _is_placeholder_text(DG_PROPOSAL_METADATA) - or _is_placeholder_text(IPFS_DESCRIPTION), - reason="Fill TODO values in the active Hoodi upgrade vote script before running the dedicated test.", -) +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 _address_to_topic(address: str) -> str: + return "0x" + "0" * 24 + address.lower().replace("0x", "") + + +def _raw_event_values(raw_event: dict) -> dict: + return {item["name"]: item["value"] for item in raw_event["data"]} + + +def _decode_uint256_words(data_hex) -> list[int]: + normalized = _normalize_hex_data(data_hex) + return [int(normalized[i : i + 64], 16) for i in range(0, len(normalized), 64) if normalized[i : i + 64]] + + +def _normalize_hex_data(data_hex) -> str: + if isinstance(data_hex, bytes): + normalized = data_hex.hex() + elif hasattr(data_hex, "hex") and callable(data_hex.hex): + normalized = data_hex.hex() + else: + normalized = str(data_hex) + + return normalized.replace("0x", "") + + +def _group_raw_dg_events_from_receipt(receipt: TransactionReceipt) -> list[list[dict]]: + events = tx_events_from_receipt(receipt) + + assert len(events) >= 1, "Unexpected raw DG events count" + assert ( + convert.to_address(events[-1]["address"]) == convert.to_address(EMERGENCY_PROTECTED_TIMELOCK) + and events[-1]["name"] == "ProposalExecuted" + ), "Unexpected raw DG service event" + + groups = [] + current_group = [] + + for event in events[:-1]: + current_group.append(event) + + is_end_of_group = event["name"] == "Executed" and convert.to_address(event["address"]) == convert.to_address( + DUAL_GOVERNANCE_ADMIN_EXECUTOR + ) + if is_end_of_group: + groups.append(current_group) + current_group = [] + + return groups + + +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", "ScriptResult", "Executed"] + 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", "ScriptResult", "Executed"] + 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", "ScriptResult", "Executed"] + 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, + emitted_by: Optional[str] = None, +) -> None: + validate_events_chain([e.name for e in event], ["LogScriptCall", "RoleGranted", "ScriptResult", "Executed"]) + + 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(AGENT), "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, + emitted_by: Optional[str] = None, +) -> None: + validate_events_chain([e.name for e in event], ["LogScriptCall", "RoleRevoked", "ScriptResult", "Executed"]) + + 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(AGENT), "Wrong role revoke sender" + + if emitted_by is not None: + _assert_emitted_by(role_revoked_event, emitted_by) + +def validate_dg_noop_event(event: EventDict) -> None: + validate_events_chain([e.name for e in event], ["LogScriptCall", "ScriptResult", "Executed"]) + assert event.count("LogScriptCall") == 1 + assert event.count("ScriptResult") == 1 + assert event.count("Executed") == 1 + +def validate_module_add(event: EventDict, module: StakingModuleItem, emitted_by: str) -> None: + validate_events_chain( + [e.name for e in event], + [ + "LogScriptCall", + "StakingModuleAdded", + "StakingModuleShareLimitSet", + "StakingModuleFeesSet", + "StakingModuleMaxDepositsPerBlockSet", + "StakingModuleMinDepositBlockDistanceSet", + "StakingRouterETHDeposited", + "ScriptResult", + "Executed", + ], + ) + + 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(AGENT) + _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(AGENT) + _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(AGENT) + _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(AGENT) + _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(AGENT) + _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_exit_balance_limit_set_raw_group(raw_group: list[dict]) -> None: + validate_events_chain( + [event["name"] for event in raw_group], + [ + "LogScriptCall", + "Upgraded", + "ContractVersionSet", + "ConsensusVersionSet", + "SetMaxValidatorsPerReport", + "(unknown)", + "ScriptResult", + "Executed", + ], + ) + + unknown_event = raw_group[5] + unknown_event_values = _raw_event_values(unknown_event) + assert convert.to_address(unknown_event["address"]) == convert.to_address(VALIDATORS_EXIT_BUS_ORACLE) + assert unknown_event_values["topic1"] == EXIT_BALANCE_LIMIT_SET_TOPIC + + decoded_words = _decode_uint256_words(unknown_event_values["data"]) + assert decoded_words == [ + VALIDATORS_EXIT_BUS_MAX_EXIT_BALANCE_ETH, + VALIDATORS_EXIT_BUS_BALANCE_PER_FRAME_ETH, + VALIDATORS_EXIT_BUS_FRAME_DURATION_IN_SEC, + ] + + +def validate_circuit_breaker_registration_raw_group(raw_group: list[dict]) -> None: + validate_events_chain( + [event["name"] for event in raw_group], + ["LogScriptCall", "(unknown)", "(unknown)", "ScriptResult", "Executed"], + ) + + first_unknown_event = raw_group[1] + second_unknown_event = raw_group[2] + + assert convert.to_address(first_unknown_event["address"]) == convert.to_address(CIRCUIT_BREAKER) + first_unknown_event_values = _raw_event_values(first_unknown_event) + assert first_unknown_event_values["topic1"] == CIRCUIT_BREAKER_BLOCKER_ADDED_TOPIC + assert first_unknown_event_values["topic2"] == _address_to_topic(CONSOLIDATION_GATEWAY) + assert first_unknown_event_values["topic3"] == _address_to_topic("0x0000000000000000000000000000000000000000") + assert first_unknown_event_values["topic4"] == _address_to_topic(CURATED_MODULE_COMMITTEE) + assert _normalize_hex_data(first_unknown_event_values["data"]) == "00" + + assert convert.to_address(second_unknown_event["address"]) == convert.to_address(CIRCUIT_BREAKER) + second_unknown_event_values = _raw_event_values(second_unknown_event) + assert second_unknown_event_values["topic1"] == CIRCUIT_BREAKER_COMMITTEE_ACTIVATED_TOPIC + assert second_unknown_event_values["topic2"] == _address_to_topic(CURATED_MODULE_COMMITTEE) + assert int(_normalize_hex_data(second_unknown_event_values["data"]), 16) > 0 + + +@pytest.fixture(scope="module") +def runtime_upgrade_addresses(): + if network_name() != "hoodi-fork": + pytest.skip("Run the dedicated Hoodi upgrade test on --network hoodi-fork.") + + upgrade_vote_script = get_upgrade_vote_script_address() + factories = get_easy_track_new_factories() + update_staking_module_share_limits_factory = factories["UpdateStakingModuleShareLimits"] + allow_consolidation_pair_factory = factories["AllowConsolidationPair"] + create_or_update_operator_group_factory = factories["CreateOrUpdateOperatorGroup"] + consolidation_migrator = get_consolidation_migrator_address() + meta_registry = get_meta_registry_address() + + if ( + _is_placeholder_address(upgrade_vote_script) + or _is_placeholder_address(update_staking_module_share_limits_factory) + or _is_placeholder_address(allow_consolidation_pair_factory) + or _is_placeholder_address(create_or_update_operator_group_factory) + or _is_placeholder_address(consolidation_migrator) + or _is_placeholder_address(meta_registry) + or _is_placeholder_text(DG_PROPOSAL_METADATA) + or _is_placeholder_text(get_ipfs_description(dg_only=DG_ONLY_MODE)) + ): + pytest.skip("Local Hoodi upgrade artifacts are missing. Run the lido-core deploy flow first.") + + return { + "upgrade_vote_script": upgrade_vote_script, + "update_staking_module_share_limits_factory": update_staking_module_share_limits_factory, + "allow_consolidation_pair_factory": allow_consolidation_pair_factory, + "create_or_update_operator_group_factory": create_or_update_operator_group_factory, + "consolidation_migrator": consolidation_migrator, + "meta_registry": meta_registry, + } @pytest.fixture(scope="module") -def dual_governance_proposal_calls(): +def dual_governance_proposal_calls(runtime_upgrade_addresses): dg_items = get_dg_items() proposal_calls = [] @@ -104,18 +556,22 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g agent = interface.Agent(AGENT) timelock = interface.EmergencyProtectedTimelock(EMERGENCY_PROTECTED_TIMELOCK) dual_governance = interface.DualGovernance(DUAL_GOVERNANCE) - easy_track = interface.EasyTrack(EASYTRACK) - staking_router = interface.StakingRouter(STAKING_ROUTER) - consolidation_migrator = interface.ConsolidationMigrator(CONSOLIDATION_MIGRATOR) - meta_registry = interface.IMetaRegistry(META_REGISTRY) + # TODO: restore once Easy Track items are enabled in the vote again. + # easy_track = interface.EasyTrack(EASYTRACK) + # staking_router = interface.StakingRouter(STAKING_ROUTER) + # consolidation_migrator = interface.ConsolidationMigrator(CONSOLIDATION_MIGRATOR) + # meta_registry = interface.IMetaRegistry(META_REGISTRY) - vote_desc_items, call_script_items = get_vote_items() + vote_desc_items, call_script_items = get_vote_items(dg_only=DG_ONLY_MODE) dg_items = get_dg_items() + upgrade_template = get_state_address("upgradeTemplate") expected_vote_events_count = EXPECTED_VOTE_EVENTS_COUNT or len(call_script_items) expected_dg_events_from_agent = EXPECTED_DG_EVENTS_FROM_AGENT or len(dg_items) expected_dg_events_count = EXPECTED_DG_EVENTS_COUNT or len(dg_items) - expected_ipfs_description_hash = IPFS_DESCRIPTION_HASH or calculate_vote_ipfs_description(IPFS_DESCRIPTION)["cid"] + expected_ipfs_description_hash = IPFS_DESCRIPTION_HASH or calculate_vote_ipfs_description( + get_ipfs_description(dg_only=DG_ONLY_MODE) + )["cid"] # ========================================================================= # ======================== Identify or Create vote ======================== @@ -127,7 +583,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g 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) + vote_id, _ = start_vote({"from": ldo_holder}, silent=True, dg_only=DG_ONLY_MODE) onchain_script = voting.getVote(vote_id)["script"] assert str(onchain_script).lower() == encode_call_script(call_script_items).lower() @@ -144,10 +600,11 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g # ========================= Before voting checks ======================== # ======================================================================= - initial_factories = easy_track.getEVMScriptFactories() - assert UPDATE_STAKING_MODULE_SHARE_LIMITS_FACTORY not in initial_factories - assert ALLOW_CONSOLIDATION_PAIR_FACTORY not in initial_factories - assert CREATE_OR_UPDATE_OPERATOR_GROUP_FACTORY not in initial_factories + # TODO: restore Easy Track pre-vote checks together with full ET flow. + # initial_factories = easy_track.getEVMScriptFactories() + # assert UPDATE_STAKING_MODULE_SHARE_LIMITS_FACTORY not in initial_factories + # assert ALLOW_CONSOLIDATION_PAIR_FACTORY not in initial_factories + # assert CREATE_OR_UPDATE_OPERATOR_GROUP_FACTORY not in initial_factories assert get_lido_vote_cid_from_str(find_metadata_by_vote_id(vote_id)) == expected_ipfs_description_hash @@ -159,10 +616,11 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g # ========================= After voting checks ========================= # ======================================================================= - new_factories = easy_track.getEVMScriptFactories() - assert UPDATE_STAKING_MODULE_SHARE_LIMITS_FACTORY in new_factories - assert ALLOW_CONSOLIDATION_PAIR_FACTORY in new_factories - assert CREATE_OR_UPDATE_OPERATOR_GROUP_FACTORY in new_factories + # TODO: restore Easy Track post-vote checks together with full ET flow. + # new_factories = easy_track.getEVMScriptFactories() + # assert UPDATE_STAKING_MODULE_SHARE_LIMITS_FACTORY in new_factories + # assert ALLOW_CONSOLIDATION_PAIR_FACTORY in new_factories + # assert CREATE_OR_UPDATE_OPERATOR_GROUP_FACTORY in new_factories assert len(vote_events) == expected_vote_events_count assert count_vote_items_by_events(vote_tx, voting.address) == expected_vote_events_count @@ -181,32 +639,33 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g proposal_calls=dual_governance_proposal_calls, ) - validate_evmscript_factory_added_event( - event=vote_events[1], - p=EVMScriptFactoryAdded( - factory_addr=UPDATE_STAKING_MODULE_SHARE_LIMITS_FACTORY, - permissions=create_permissions(staking_router, "updateModuleShares"), - ), - emitted_by=easy_track, - ) - - validate_evmscript_factory_added_event( - event=vote_events[2], - p=EVMScriptFactoryAdded( - factory_addr=ALLOW_CONSOLIDATION_PAIR_FACTORY, - permissions=create_permissions(consolidation_migrator, "allowPair"), - ), - emitted_by=easy_track, - ) - - validate_evmscript_factory_added_event( - event=vote_events[3], - p=EVMScriptFactoryAdded( - factory_addr=CREATE_OR_UPDATE_OPERATOR_GROUP_FACTORY, - permissions=create_permissions(meta_registry, "createOrUpdateOperatorGroup"), - ), - emitted_by=easy_track, - ) + # TODO: restore ET event validation when full ET flow is enabled again. + # validate_evmscript_factory_added_event( + # event=vote_events[1], + # p=EVMScriptFactoryAdded( + # factory_addr=UPDATE_STAKING_MODULE_SHARE_LIMITS_FACTORY, + # permissions=create_permissions(staking_router, "updateModuleShares"), + # ), + # emitted_by=easy_track, + # ) + # + # validate_evmscript_factory_added_event( + # event=vote_events[2], + # p=EVMScriptFactoryAdded( + # factory_addr=ALLOW_CONSOLIDATION_PAIR_FACTORY, + # permissions=create_permissions(consolidation_migrator, "allowPair"), + # ), + # emitted_by=easy_track, + # ) + # + # validate_evmscript_factory_added_event( + # event=vote_events[3], + # p=EVMScriptFactoryAdded( + # factory_addr=CREATE_OR_UPDATE_OPERATOR_GROUP_FACTORY, + # permissions=create_permissions(meta_registry, "createOrUpdateOperatorGroup"), + # ), + # 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 live Hoodi vote.") @@ -238,10 +697,559 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g timelock=EMERGENCY_PROTECTED_TIMELOCK, admin_executor=DUAL_GOVERNANCE_ADMIN_EXECUTOR, ) + raw_dg_events = _group_raw_dg_events_from_receipt(dg_tx) assert count_vote_items_by_events(dg_tx, agent.address) == expected_dg_events_from_agent assert len(dg_events) == expected_dg_events_count + assert len(raw_dg_events) == expected_dg_events_count + + # === DG EXECUTION EVENTS VALIDATION === + + # 1. Call UpgradeTemplate.startUpgrade + validate_events_chain([e.name for e in dg_events[0]], ["LogScriptCall", "UpgradeStarted", "ScriptResult", "Executed"]) + upgrade_started_event = _single_event(dg_events[0], "UpgradeStarted") + _assert_emitted_by(upgrade_started_event, upgrade_template) + + # 2. Upgrade LidoLocator proxy + validate_proxy_upgrade_event(dg_events[1], LIDO_LOCATOR_IMPL, emitted_by=LIDO_LOCATOR) + + # 3. Upgrade and finalize StakingRouter + validate_proxy_upgrade_event( + dg_events[2], + STAKING_ROUTER_IMPL, + emitted_by=STAKING_ROUTER, + events_chain=[ + "LogScriptCall", + "Upgraded", + "RoleGranted", + "RoleGranted", + "RoleGranted", + "RoleGranted", + "RoleGranted", + "RoleGranted", + "RoleGranted", + "RoleGranted", + "Initialized", + "ScriptResult", + "Executed", + ], + ) + role_grants = _event_list(dg_events[2], "RoleGranted") + assert len(role_grants) == 8 + for role_granted_event, (role_hash, account) in zip( + role_grants, + [ + (DEFAULT_ADMIN_ROLE, AGENT), + (STAKING_MODULE_MANAGE_ROLE, AGENT), + (STAKING_MODULE_MANAGE_ROLE, HOODI_LEGACY_STAKING_MODULE_MANAGER), + (STAKING_MODULE_UNVETTING_ROLE, OLD_DEPOSIT_SECURITY_MODULE), + (REPORT_EXITED_VALIDATORS_ROLE, ACCOUNTING_ORACLE), + (REPORT_VALIDATOR_EXITING_STATUS_ROLE, VALIDATOR_EXIT_DELAY_VERIFIER), + (REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE, TRIGGERABLE_WITHDRAWALS_GATEWAY), + (REPORT_REWARDS_MINTED_ROLE, ACCOUNTING), + ], + ): + assert _normalize_role(role_granted_event["role"]) == role_hash.replace("0x", "") + assert convert.to_address(role_granted_event["account"]) == convert.to_address(account) + assert convert.to_address(role_granted_event["sender"]) == convert.to_address(AGENT) + _assert_emitted_by(role_granted_event, STAKING_ROUTER) + initialized_event = _single_event(dg_events[2], "Initialized") + assert initialized_event["version"] == 4 + _assert_emitted_by(initialized_event, STAKING_ROUTER) + + # 4. Upgrade and finalize AccountingOracle + validate_proxy_upgrade_event( + dg_events[3], + ACCOUNTING_ORACLE_IMPL, + emitted_by=ACCOUNTING_ORACLE, + events_chain=[ + "LogScriptCall", + "Upgraded", + "ContractVersionSet", + "ConsensusVersionSet", + "ScriptResult", + "Executed", + ], + ) + validate_contract_version_set_event( + dg_events[3], + AO_CONTRACT_VERSION, + emitted_by=ACCOUNTING_ORACLE, + events_chain=[ + "LogScriptCall", + "Upgraded", + "ContractVersionSet", + "ConsensusVersionSet", + "ScriptResult", + "Executed", + ], + ) + validate_consensus_version_set_event( + dg_events[3], + AO_CONSENSUS_VERSION, + AO_PREV_CONSENSUS_VERSION, + emitted_by=ACCOUNTING_ORACLE, + events_chain=[ + "LogScriptCall", + "Upgraded", + "ContractVersionSet", + "ConsensusVersionSet", + "ScriptResult", + "Executed", + ], + ) + + # 5. Upgrade and finalize ValidatorsExitBusOracle + validate_proxy_upgrade_event( + dg_events[4], + VALIDATORS_EXIT_BUS_ORACLE_IMPL, + emitted_by=VALIDATORS_EXIT_BUS_ORACLE, + events_chain=[ + "LogScriptCall", + "Upgraded", + "ContractVersionSet", + "ConsensusVersionSet", + "SetMaxValidatorsPerReport", + "(unknown)", + "ScriptResult", + "Executed", + ], + ) + validate_contract_version_set_event( + dg_events[4], + VEBO_CONTRACT_VERSION, + emitted_by=VALIDATORS_EXIT_BUS_ORACLE, + events_chain=[ + "LogScriptCall", + "Upgraded", + "ContractVersionSet", + "ConsensusVersionSet", + "SetMaxValidatorsPerReport", + "(unknown)", + "ScriptResult", + "Executed", + ], + ) + validate_consensus_version_set_event( + dg_events[4], + VEBO_CONSENSUS_VERSION, + VEBO_PREV_CONSENSUS_VERSION, + emitted_by=VALIDATORS_EXIT_BUS_ORACLE, + events_chain=[ + "LogScriptCall", + "Upgraded", + "ContractVersionSet", + "ConsensusVersionSet", + "SetMaxValidatorsPerReport", + "(unknown)", + "ScriptResult", + "Executed", + ], + ) + 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, VALIDATORS_EXIT_BUS_ORACLE) + validate_exit_balance_limit_set_raw_group(raw_dg_events[4]) + + # 6. Upgrade Accounting implementation + validate_proxy_upgrade_event(dg_events[5], ACCOUNTING_IMPL, emitted_by=ACCOUNTING) + + # 7. Upgrade and finalize WithdrawalVault + validate_proxy_upgrade_event( + dg_events[6], + WITHDRAWAL_VAULT_IMPL, + emitted_by=WITHDRAWAL_VAULT, + events_chain=["LogScriptCall", "Upgraded", "ContractVersionSet", "ScriptResult", "Executed"], + ) + validate_contract_version_set_event( + dg_events[6], + WITHDRAWAL_VAULT_CONTRACT_VERSION, + emitted_by=WITHDRAWAL_VAULT, + events_chain=["LogScriptCall", "Upgraded", "ContractVersionSet", "ScriptResult", "Executed"], + ) + + # 8. Grant APP_MANAGER_ROLE on Kernel to Agent + validate_aragon_grant_permission_event( + dg_events[7], + entity=AGENT, + app=ARAGON_KERNEL, + role=APP_MANAGER_ROLE, + emitted_by=ACL, + ) + + # 9. Set new Lido implementation in Kernel + validate_aragon_set_app_event( + dg_events[8], + app_id=LIDO_APP_ID, + app=LIDO_IMPL, + emitted_by=ARAGON_KERNEL, + ) + + # 10. Revoke APP_MANAGER_ROLE on Kernel from Agent + validate_aragon_revoke_permission_event( + dg_events[9], + entity=AGENT, + app=ARAGON_KERNEL, + role=APP_MANAGER_ROLE, + emitted_by=ACL, + ) + + # 11. Grant BUFFER_RESERVE_MANAGER_ROLE on Lido and transfer permission manager to Agent + validate_events_chain( + [e.name for e in dg_events[10]], + ["LogScriptCall", "SetPermission", "ChangePermissionManager", "ScriptResult", "Executed"], + ) + set_permission_event = _single_event(dg_events[10], "SetPermission") + assert convert.to_address(set_permission_event["entity"]) == convert.to_address(AGENT) + assert convert.to_address(set_permission_event["app"]) == convert.to_address(LIDO) + assert set_permission_event["role"] == BUFFER_RESERVE_MANAGER_ROLE + assert set_permission_event["allowed"] is True + _assert_emitted_by(set_permission_event, ACL) + change_permission_manager_event = _single_event(dg_events[10], "ChangePermissionManager") + assert convert.to_address(change_permission_manager_event["app"]) == convert.to_address(LIDO) + assert change_permission_manager_event["role"] == BUFFER_RESERVE_MANAGER_ROLE + assert convert.to_address(change_permission_manager_event["manager"]) == convert.to_address(AGENT) + _assert_emitted_by(change_permission_manager_event, ACL) + + # 12. Finalize Lido contract version + validate_contract_version_set_event(dg_events[11], LIDO_CONTRACT_VERSION, emitted_by=LIDO) + + # 13. Grant STAKING_MODULE_SHARE_MANAGE_ROLE to EasyTrack executor + validate_role_grant_event( + dg_events[12], + STAKING_MODULE_SHARE_MANAGE_ROLE, + EASYTRACK_EVMSCRIPT_EXECUTOR, + emitted_by=STAKING_ROUTER, + ) + + # 14. Revoke STAKING_MODULE_UNVETTING_ROLE from old DSM + validate_role_revoke_event( + dg_events[13], + STAKING_MODULE_UNVETTING_ROLE, + OLD_DEPOSIT_SECURITY_MODULE, + emitted_by=STAKING_ROUTER, + ) + + # 15. Grant STAKING_MODULE_UNVETTING_ROLE to new DSM + validate_role_grant_event( + dg_events[14], + STAKING_MODULE_UNVETTING_ROLE, + NEW_DEPOSIT_SECURITY_MODULE, + emitted_by=STAKING_ROUTER, + ) + + # 16. Grant TW_EXIT_LIMIT_MANAGER_ROLE to Agent + validate_role_grant_event( + dg_events[15], + TW_EXIT_LIMIT_MANAGER_ROLE, + AGENT, + emitted_by=TRIGGERABLE_WITHDRAWALS_GATEWAY, + ) + + # 17. Set TWG exit limits + validate_events_chain( + [e.name for e in dg_events[16]], + ["LogScriptCall", "ExitRequestsLimitSet", "ScriptResult", "Executed"], + ) + 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, TRIGGERABLE_WITHDRAWALS_GATEWAY) + + # 18. Register CircuitBreaker integration + validate_circuit_breaker_registration_raw_group(raw_dg_events[17]) + + # 19. Upgrade and initialize CSM + validate_proxy_upgrade_event( + dg_events[18], + CSM_IMPL, + emitted_by=CSM, + events_chain=["LogScriptCall", "Upgraded", "Initialized", "ScriptResult", "Executed"], + ) + initialized_event = _single_event(dg_events[18], "Initialized") + assert initialized_event["version"] == 3 + _assert_emitted_by(initialized_event, CSM) + + # 20. Upgrade and initialize CSParametersRegistry + validate_proxy_upgrade_event( + dg_events[19], + CS_PARAMETERS_REGISTRY_IMPL, + emitted_by=CS_PARAMETERS_REGISTRY, + events_chain=["LogScriptCall", "Upgraded", "Initialized", "ScriptResult", "Executed"], + ) + initialized_event = _single_event(dg_events[19], "Initialized") + assert initialized_event["version"] == 3 + _assert_emitted_by(initialized_event, CS_PARAMETERS_REGISTRY) + + # 21. Upgrade and finalize CSFeeOracle + validate_proxy_upgrade_event( + dg_events[20], + CS_FEE_ORACLE_IMPL, + emitted_by=CS_FEE_ORACLE, + events_chain=["LogScriptCall", "Upgraded", "ConsensusVersionSet", "ContractVersionSet", "ScriptResult", "Executed"], + ) + validate_consensus_version_set_event( + dg_events[20], + 4, + 3, + emitted_by=CS_FEE_ORACLE, + events_chain=["LogScriptCall", "Upgraded", "ConsensusVersionSet", "ContractVersionSet", "ScriptResult", "Executed"], + ) + validate_contract_version_set_event( + dg_events[20], + 3, + emitted_by=CS_FEE_ORACLE, + events_chain=["LogScriptCall", "Upgraded", "ConsensusVersionSet", "ContractVersionSet", "ScriptResult", "Executed"], + ) + + # 22. Upgrade CSVettedGate + validate_proxy_upgrade_event(dg_events[21], CS_VETTED_GATE_IMPL, emitted_by=CS_VETTED_GATE) + + # 23. Upgrade and initialize CSAccounting + validate_proxy_upgrade_event( + dg_events[22], + CS_ACCOUNTING_IMPL, + emitted_by=CS_ACCOUNTING, + events_chain=["LogScriptCall", "Upgraded", "Initialized", "ScriptResult", "Executed"], + ) + initialized_event = _single_event(dg_events[22], "Initialized") + assert initialized_event["version"] == 3 + _assert_emitted_by(initialized_event, CS_ACCOUNTING) + + # 24. Upgrade and initialize CSFeeDistributor + validate_proxy_upgrade_event( + dg_events[23], + CS_FEE_DISTRIBUTOR_IMPL, + emitted_by=CS_FEE_DISTRIBUTOR, + events_chain=["LogScriptCall", "Upgraded", "Initialized", "ScriptResult", "Executed"], + ) + initialized_event = _single_event(dg_events[23], "Initialized") + assert initialized_event["version"] == 3 + _assert_emitted_by(initialized_event, CS_FEE_DISTRIBUTOR) + + # 25. Upgrade CSExitPenalties + validate_proxy_upgrade_event(dg_events[24], CS_EXIT_PENALTIES_IMPL, emitted_by=CS_EXIT_PENALTIES) + + # 26. Upgrade CSValidatorStrikes + validate_proxy_upgrade_event(dg_events[25], CS_VALIDATOR_STRIKES_IMPL, emitted_by=CS_VALIDATOR_STRIKES) + + # 27. Set CSM ejector + validate_events_chain([e.name for e in dg_events[26]], ["LogScriptCall", "EjectorSet", "ScriptResult", "Executed"]) + ejector_set_event = _single_event(dg_events[26], "EjectorSet") + assert convert.to_address(ejector_set_event["ejector"]) == convert.to_address(CSM_EJECTOR) + _assert_emitted_by(ejector_set_event, CS_VALIDATOR_STRIKES) + + # 28. Grant REPORT_GENERAL_DELAYED_PENALTY_ROLE + validate_role_grant_event( + dg_events[27], + REPORT_GENERAL_DELAYED_PENALTY_ROLE, + CSM_GENERAL_DELAYED_PENALTY_REPORTER, + emitted_by=CSM, + ) + + # 29. Grant SETTLE_GENERAL_DELAYED_PENALTY_ROLE + validate_role_grant_event( + dg_events[28], + SETTLE_GENERAL_DELAYED_PENALTY_ROLE, + EASYTRACK_EVMSCRIPT_EXECUTOR, + emitted_by=CSM, + ) + + # 30. Revoke REPORT_EL_REWARDS_STEALING_PENALTY_ROLE + validate_role_revoke_event( + dg_events[29], + REPORT_EL_REWARDS_STEALING_PENALTY_ROLE, + CSM_GENERAL_DELAYED_PENALTY_REPORTER, + emitted_by=CSM, + ) + + # 31. Revoke SETTLE_EL_REWARDS_STEALING_PENALTY_ROLE + validate_role_revoke_event( + dg_events[30], + SETTLE_EL_REWARDS_STEALING_PENALTY_ROLE, + EASYTRACK_EVMSCRIPT_EXECUTOR, + emitted_by=CSM, + ) + + # 32. Revoke VERIFIER_ROLE from old verifier + validate_role_revoke_event( + dg_events[31], + VERIFIER_ROLE, + OLD_VERIFIER, + emitted_by=CSM, + ) + + # 33. Grant VERIFIER_ROLE to verifier v3 + validate_role_grant_event( + dg_events[32], + VERIFIER_ROLE, + VERIFIER_V3, + emitted_by=CSM, + ) + + # 34. Grant REPORT_REGULAR_WITHDRAWN_VALIDATORS_ROLE + validate_role_grant_event( + dg_events[33], + REPORT_REGULAR_WITHDRAWN_VALIDATORS_ROLE, + VERIFIER_V3, + emitted_by=CSM, + ) + + # 35. Grant REPORT_SLASHED_WITHDRAWN_VALIDATORS_ROLE + validate_role_grant_event( + dg_events[34], + REPORT_SLASHED_WITHDRAWN_VALIDATORS_ROLE, + EASYTRACK_EVMSCRIPT_EXECUTOR, + emitted_by=CSM, + ) + + # 36. Revoke CREATE_NODE_OPERATOR_ROLE from old permissionless gate + validate_role_revoke_event( + dg_events[35], + CREATE_NODE_OPERATOR_ROLE, + OLD_PERMISSIONLESS_GATE, + emitted_by=CSM, + ) + + # 37. Grant CREATE_NODE_OPERATOR_ROLE to new permissionless gate + validate_role_grant_event( + dg_events[36], + CREATE_NODE_OPERATOR_ROLE, + NEW_PERMISSIONLESS_GATE, + emitted_by=CSM, + ) + + # 38. No-op DG item + validate_dg_noop_event(dg_events[37]) + + # 39. No-op DG item + validate_dg_noop_event(dg_events[38]) + + # 40. No-op DG item + validate_dg_noop_event(dg_events[39]) + + # 41. No-op DG item + validate_dg_noop_event(dg_events[40]) + + # 42. Revoke START_REFERRAL_SEASON_ROLE from Agent + validate_role_revoke_event( + dg_events[41], + START_REFERRAL_SEASON_ROLE, + AGENT, + emitted_by=CS_VETTED_GATE, + ) + + # 43. Revoke END_REFERRAL_SEASON_ROLE from ICS manager + validate_role_revoke_event( + dg_events[42], + END_REFERRAL_SEASON_ROLE, + ICS_MANAGER, + emitted_by=CS_VETTED_GATE, + ) + + # 44. No-op DG item + validate_dg_noop_event(dg_events[43]) + + # 45. No-op DG item + validate_dg_noop_event(dg_events[44]) + + # 46. No-op DG item + validate_dg_noop_event(dg_events[45]) + + # 47. No-op DG item + validate_dg_noop_event(dg_events[46]) + + # 48. Grant MANAGE_GENERAL_PENALTIES_AND_CHARGES_ROLE + validate_role_grant_event( + dg_events[47], + MANAGE_GENERAL_PENALTIES_AND_CHARGES_ROLE, + CSM_PENALTIES_MANAGER, + emitted_by=CS_PARAMETERS_REGISTRY, + ) + + # 49. Revoke REQUEST_BURN_SHARES_ROLE from CSAccounting + validate_role_revoke_event( + dg_events[48], + REQUEST_BURN_SHARES_ROLE, + CS_ACCOUNTING, + emitted_by=BURNER, + ) + + # 50. Grant REQUEST_BURN_MY_STETH_ROLE to CSAccounting + validate_role_grant_event( + dg_events[49], + REQUEST_BURN_MY_STETH_ROLE, + CS_ACCOUNTING, + emitted_by=BURNER, + ) + + # 51. Revoke ADD_FULL_WITHDRAWAL_REQUEST_ROLE from old CSM ejector + validate_role_revoke_event( + dg_events[50], + ADD_FULL_WITHDRAWAL_REQUEST_ROLE, + OLD_CSM_EJECTOR, + emitted_by=TRIGGERABLE_WITHDRAWALS_GATEWAY, + ) + + # 52. Grant ADD_FULL_WITHDRAWAL_REQUEST_ROLE to CSM ejector + validate_role_grant_event( + dg_events[51], + ADD_FULL_WITHDRAWAL_REQUEST_ROLE, + CSM_EJECTOR, + emitted_by=TRIGGERABLE_WITHDRAWALS_GATEWAY, + ) + + # 53. Add curated-onchain-v2 module + validate_module_add(dg_events[52], CURATED_MODULE_V2, emitted_by=STAKING_ROUTER) + + # 54. Grant REQUEST_BURN_MY_STETH_ROLE to curated accounting + validate_role_grant_event( + dg_events[53], + REQUEST_BURN_MY_STETH_ROLE, + CURATED_ACCOUNTING, + emitted_by=BURNER, + ) + + # 55. Grant ADD_FULL_WITHDRAWAL_REQUEST_ROLE to curated ejector + validate_role_grant_event( + dg_events[54], + ADD_FULL_WITHDRAWAL_REQUEST_ROLE, + CURATED_EJECTOR, + emitted_by=TRIGGERABLE_WITHDRAWALS_GATEWAY, + ) + + # 56. Grant RESUME_ROLE on curated module to Agent + validate_role_grant_event( + dg_events[55], + RESUME_ROLE, + AGENT, + emitted_by=CURATED_MODULE, + ) + + # 57. Resume curated module + validate_events_chain([e.name for e in dg_events[56]], ["LogScriptCall", "Resumed", "ScriptResult", "Executed"]) + resumed_event = _single_event(dg_events[56], "Resumed") + _assert_emitted_by(resumed_event, CURATED_MODULE) + + # 58. Revoke RESUME_ROLE from Agent + validate_role_revoke_event( + dg_events[57], + RESUME_ROLE, + AGENT, + emitted_by=CURATED_MODULE, + ) + + # 59. Set curated HashConsensus frame config + validate_events_chain([e.name for e in dg_events[58]], ["LogScriptCall", "FrameConfigSet", "ScriptResult", "Executed"]) + frame_config_set_event = _single_event(dg_events[58], "FrameConfigSet") + assert frame_config_set_event["newInitialEpoch"] == CURATED_INITIAL_EPOCH + assert frame_config_set_event["newEpochsPerFrame"] == CURATED_EPOCHS_PER_FRAME + _assert_emitted_by(frame_config_set_event, CURATED_HASH_CONSENSUS) - # TODO validate all DG events + # 60. Call UpgradeTemplate.finishUpgrade + validate_events_chain([e.name for e in dg_events[59]], ["LogScriptCall", "UpgradeFinished", "ScriptResult", "Executed"]) + upgrade_finished_event = _single_event(dg_events[59], "UpgradeFinished") + _assert_emitted_by(upgrade_finished_event, upgrade_template) # ========================================================================= # ==================== After DG proposal executed checks ================== From c64874a6f3a7216df5195e569556c42c1857600e Mon Sep 17 00:00:00 2001 From: Eddort Date: Thu, 23 Apr 2026 22:18:49 +0200 Subject: [PATCH 03/15] wip: hoodi update voting contract source of true --- interfaces/IValidatorStrikesV3.json | 28 + interfaces/UpgradeConfig.json | 1183 +++++++++++++++++ interfaces/UpgradeVoteScript.json | 358 ++++- tests/conftest.py | 5 +- .../test_2026_04_14_hoodi_protocol_upgrade.py | 613 +++++---- utils/hoodi_upgrade.py | 139 ++ .../test/event_validators/dual_governance.py | 21 +- 7 files changed, 2063 insertions(+), 284 deletions(-) create mode 100644 interfaces/IValidatorStrikesV3.json create mode 100644 interfaces/UpgradeConfig.json create mode 100644 utils/hoodi_upgrade.py 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/UpgradeConfig.json b/interfaces/UpgradeConfig.json new file mode 100644 index 00000000..5268dc77 --- /dev/null +++ b/interfaces/UpgradeConfig.json @@ -0,0 +1,1183 @@ +[ + { + "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": "resealManager", + "type": "address" + }, + { + "internalType": "address", + "name": "circuitBreaker", + "type": "address" + }, + { + "internalType": "address", + "name": "easyTrack", + "type": "address" + }, + { + "components": [ + { + "internalType": "address", + "name": "UpdateStakingModuleShareLimits", + "type": "address" + }, + { + "internalType": "address", + "name": "AllowConsolidationPair", + "type": "address" + }, + { + "internalType": "address", + "name": "AllowedMerkleGatesRegistryForCSM", + "type": "address" + }, + { + "internalType": "address", + "name": "SetMerkleGateTreeForCSM", + "type": "address" + }, + { + "internalType": "address", + "name": "ReportWithdrawalsForSlashedValidatorsForCSM", + "type": "address" + }, + { + "internalType": "address", + "name": "SettleGeneralDelayedPenaltyForCSM", + "type": "address" + }, + { + "internalType": "address", + "name": "AllowedMerkleGatesRegistryForCM", + "type": "address" + }, + { + "internalType": "address", + "name": "SetMerkleGateTreeForCM", + "type": "address" + }, + { + "internalType": "address", + "name": "ReportWithdrawalsForSlashedValidatorsForCM", + "type": "address" + }, + { + "internalType": "address", + "name": "SettleGeneralDelayedPenaltyForCM", + "type": "address" + }, + { + "internalType": "address", + "name": "CreateOrUpdateOperatorGroup", + "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": "oldLocatorImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "oldLidoImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "oldAccountingImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "oldAccountingOracleImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "oldStakingRouterImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "oldWithdrawalVaultImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "oldValidatorsExitBusOracleImpl", + "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": "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": "address", + "name": "topUpGateway", + "type": "address" + }, + { + "internalType": "uint256", + "name": "lidoDepositsReserveTarget", + "type": "uint256" + }, + { + "internalType": "address", + "name": "curatedModuleCommittee", + "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": "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": "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": "permissionlessGate", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "address", + "name": "verifierV3", + "type": "address" + }, + { + "internalType": "address", + "name": "ejector", + "type": "address" + }, + { + "internalType": "address", + "name": "identifiedCommunityStakersGateManager", + "type": "address" + }, + { + "internalType": "address", + "name": "gateSeal", + "type": "address" + }, + { + "internalType": "address", + "name": "generalDelayedPenaltyReporter", + "type": "address" + }, + { + "internalType": "address", + "name": "penaltiesManager", + "type": "address" + } + ], + "internalType": "struct CSMUpgradeParams", + "name": "csmUpgrade", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "address", + "name": "module", + "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": "hashConsensusInitialEpoch", + "type": "uint256" + } + ], + "internalType": "struct CuratedModuleParams", + "name": "curatedModule", + "type": "tuple" + } + ], + "internalType": "struct UpgradeParameters", + "name": "params", + "type": "tuple" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "NewAndOldLocatorImplementationsMustBeDifferent", + "type": "error" + }, + { + "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": "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": "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": "verifier", + "type": "address" + }, + { + "internalType": "address", + "name": "verifierV3", + "type": "address" + }, + { + "internalType": "address", + "name": "permissionlessGate", + "type": "address" + }, + { + "internalType": "address", + "name": "ejector", + "type": "address" + }, + { + "internalType": "address", + "name": "identifiedCommunityStakersGateManager", + "type": "address" + }, + { + "internalType": "address", + "name": "gateSeal", + "type": "address" + }, + { + "internalType": "address", + "name": "generalDelayedPenaltyReporter", + "type": "address" + }, + { + "internalType": "address", + "name": "penaltiesManager", + "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": "oldLocatorImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "oldLidoImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "oldAccountingImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "oldAccountingOracleImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "oldStakingRouterImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "oldWithdrawalVaultImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "oldValidatorsExitBusOracleImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "oldOracleReportSanityChecker", + "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": "curatedModuleCommittee", + "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": "struct CoreUpgradeConfig", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCuratedModuleConfig", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "module", + "type": "address" + }, + { + "internalType": "address", + "name": "accounting", + "type": "address" + }, + { + "internalType": "address", + "name": "ejector", + "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": "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": "AllowedMerkleGatesRegistryForCSM", + "type": "address" + }, + { + "internalType": "address", + "name": "SetMerkleGateTreeForCSM", + "type": "address" + }, + { + "internalType": "address", + "name": "ReportWithdrawalsForSlashedValidatorsForCSM", + "type": "address" + }, + { + "internalType": "address", + "name": "SettleGeneralDelayedPenaltyForCSM", + "type": "address" + }, + { + "internalType": "address", + "name": "AllowedMerkleGatesRegistryForCM", + "type": "address" + }, + { + "internalType": "address", + "name": "SetMerkleGateTreeForCM", + "type": "address" + }, + { + "internalType": "address", + "name": "ReportWithdrawalsForSlashedValidatorsForCM", + "type": "address" + }, + { + "internalType": "address", + "name": "SettleGeneralDelayedPenaltyForCM", + "type": "address" + }, + { + "internalType": "address", + "name": "CreateOrUpdateOperatorGroup", + "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": "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/UpgradeVoteScript.json b/interfaces/UpgradeVoteScript.json index 8e05371f..d4e3acd1 100644 --- a/interfaces/UpgradeVoteScript.json +++ b/interfaces/UpgradeVoteScript.json @@ -1 +1,357 @@ -[{"inputs":[{"components":[{"internalType":"address","name":"upgradeTemplate","type":"address"},{"internalType":"address","name":"timeConstraints","type":"address"}],"internalType":"struct UpgradeVoteScript.ScriptParams","name":"_params","type":"tuple"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"DG_ITEMS_COUNT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ENABLED_DAY_SPAN_END","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ENABLED_DAY_SPAN_START","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TEMPLATE","outputs":[{"internalType":"contract UpgradeTemplate","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":"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"},{"inputs":[],"name":"params","outputs":[{"internalType":"address","name":"upgradeTemplate","type":"address"},{"internalType":"address","name":"timeConstraints","type":"address"}],"stateMutability":"view","type":"function"}] +[ + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "upgradeTemplate", + "type": "address" + }, + { + "internalType": "address", + "name": "timeConstraints", + "type": "address" + }, + { + "internalType": "uint32", + "name": "enabledDaySpanStart", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "enabledDaySpanEnd", + "type": "uint32" + } + ], + "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": "ENABLED_DAY_SPAN_END", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ENABLED_DAY_SPAN_START", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TEMPLATE", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TIME_CONSTRAINTS", + "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": "getVoteItemsPacked", + "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/tests/conftest.py b/tests/conftest.py index f14b9cb0..e209869a 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -169,7 +169,10 @@ def prefetch_contracts_from_etherscan(): # add contracts here to fetch the abis from etherscan # Use next format to fetch the abi: # Contract.from_explorer() - Contract.from_explorer(contracts.cs_exit_penalties.address) + try: + Contract.from_explorer(contracts.cs_exit_penalties.address) + except Exception as exc: + print(f"warning: unable to prefetch ABI from Etherscan, continuing with local ABIs: {exc}") Helpers._etherscan_is_fetched = True diff --git a/tests/test_2026_04_14_hoodi_protocol_upgrade.py b/tests/test_2026_04_14_hoodi_protocol_upgrade.py index f6ad1b3b..5ef17760 100644 --- a/tests/test_2026_04_14_hoodi_protocol_upgrade.py +++ b/tests/test_2026_04_14_hoodi_protocol_upgrade.py @@ -2,16 +2,12 @@ import pytest -from brownie import chain, convert, interface +from brownie import chain, convert, interface, web3 from brownie.network.event import EventDict from brownie.network.transaction import TransactionReceipt from utils.config import network_name from utils.hoodi_upgrade import ( - get_consolidation_migrator_address, - get_easy_track_new_factories, - get_meta_registry_address, - get_state_address, get_upgrade_vote_script_address, ) from utils.test.tx_tracing_helpers import ( @@ -50,96 +46,37 @@ # ============================================================================ # ============================== Constants =================================== # ============================================================================ -VOTING = "0x49B3512c44891bef83F8967d075121Bd1b07a01B" -AGENT = "0x0534aA41907c9631fae990960bCC72d75fA7cfeD" EMERGENCY_PROTECTED_TIMELOCK = "0x0A5E22782C0Bd4AddF10D771f0bF0406B038282d" -DUAL_GOVERNANCE = "0x9CAaCCc62c66d817CC59c44780D1b722359795bF" -DUAL_GOVERNANCE_ADMIN_EXECUTOR = "0x0eCc17597D292271836691358B22340b78F3035B" -ACL = "0x78780e70Eae33e2935814a327f7dB6c01136cc62" -ARAGON_KERNEL = "0xA48DF029Fd2e5FCECB3886c5c2F60e3625A1E87d" -LIDO = "0x3508A952176b3c15387C97BE809eaffB1982176a" -LIDO_LOCATOR = "0xe2EF9536DAAAEBFf5b1c130957AB3E80056b06D8" -STAKING_ROUTER = "0xCc820558B39ee15C7C45B59390B503b83fb499A8" -ACCOUNTING_ORACLE = "0xcb883B1bD0a41512b42D2dB267F2A2cd919FB216" -VALIDATORS_EXIT_BUS_ORACLE = "0x8664d394C2B3278F26A1B44B967aEf99707eeAB2" -ACCOUNTING = "0x9b5b78D1C9A3238bF24662067e34c57c83E8c354" -WITHDRAWAL_VAULT = "0x4473dCDDbf77679A643BdB654dbd86D67F8d32f2" -TRIGGERABLE_WITHDRAWALS_GATEWAY = "0x6679090D92b08a2a686eF8614feECD8cDFE209db" -VALIDATOR_EXIT_DELAY_VERIFIER = "0xa5F5A9360275390fF9728262a29384399f38d2f0" -EASYTRACK_EVMSCRIPT_EXECUTOR = "0x79a20FD0FA36453B2F45eAbab19bfef43575Ba9E" -LIDO_IMPL = "0x6147270470A9Ee5b55c33EA71e32000E5d6D8E6B" -LIDO_APP_ID = "0x3ca7c3e38968823ccb4c78ea688df41356f182ae1d159e4ee608d30d68cef320" -CIRCUIT_BREAKER = "0x44a5789dFeDa59cD176Ab5709ec2F4829dE4d555" -CONSOLIDATION_GATEWAY = "0xce93710b849e0dC202AaC513837e05bEA9D7DdFD" -CURATED_MODULE_COMMITTEE = "0x84DffcfB232594975C608DE92544Ff239a24c9E9" -CSM = "0x79CEf36D84743222f37765204Bec41E92a93E59d" -CS_PARAMETERS_REGISTRY = "0xA4aD5236963f9Fe4229864712269D8d79B65C5Ad" -CS_FEE_ORACLE = "0xe7314f561B2e72f9543F1004e741bab6Fc51028B" -CS_VETTED_GATE = "0x10a254E724fe2b7f305F76f3F116a3969c53845f" -CS_ACCOUNTING = "0xA54b90BA34C5f326BC1485054080994e38FB4C60" -CS_FEE_DISTRIBUTOR = "0xaCd9820b0A2229a82dc1A0770307ce5522FF3582" -CS_EXIT_PENALTIES = "0xD259b31083Be841E5C85b2D481Cfc17C14276800" -CS_VALIDATOR_STRIKES = "0x8fBA385C3c334D251eE413e79d4D3890db98693c" -VERIFIER_V3 = "0xC96406b0eADdAC5708aFCa04DcCA67BAdC9642Fd" -OLD_VERIFIER = "0x1773b2Ff99A030F6000554Cb8A5Ec93145650cbA" -OLD_PERMISSIONLESS_GATE = "0x5553077102322689876A6AdFd48D75014c28acfb" -NEW_PERMISSIONLESS_GATE = "0xd7bD8D2A9888D1414c770B35ACF55890B15de26a" -OLD_DEPOSIT_SECURITY_MODULE = "0x2F0303F20E0795E6CCd17BD5efE791A586f28E03" -NEW_DEPOSIT_SECURITY_MODULE = "0x1a629bB7C0563650e46406Eb6764A2ba207a0eFE" HOODI_LEGACY_STAKING_MODULE_MANAGER = "0xE28f573b732632fdE03BD5507A7d475383e8512E" -ICS_MANAGER = "0x4AF43Ee34a6fcD1fEcA1e1F832124C763561dA53" -CSM_GENERAL_DELAYED_PENALTY_REPORTER = ICS_MANAGER -CSM_PENALTIES_MANAGER = ICS_MANAGER -BURNER = "0xb2c99cd38a2636a6281a849C8de938B3eF4A7C3D" -OLD_CSM_EJECTOR = "0x777bd76326E4aDcD353b03AD45b33BAF41048476" -CSM_EJECTOR = "0xCAe028378d69D54dc8bF809e6C44CF751F997b80" -CURATED_MODULE = "0x87EB69Ae51317405FD285efD2326a4a11f6173b9" -CURATED_ACCOUNTING = "0x7f7356D29aCd915F1934220956c3305808ceB235" -CURATED_EJECTOR = "0xfDbde2B3554B69C84e0f8d7daB68D390Ff0f4394" -CURATED_HASH_CONSENSUS = "0x920883908A78c1554f682006a8aB32E62Be09F33" -LIDO_LOCATOR_IMPL = "0x9b110E022a13583679536B303d0C22467d1b567A" -STAKING_ROUTER_IMPL = "0x44d0b2B95d2C2bDF73FE4f5cD7E3A930494E5B1f" -ACCOUNTING_ORACLE_IMPL = "0x41bF10F28A1312f2241f86A2537A04b08e343C0a" -VALIDATORS_EXIT_BUS_ORACLE_IMPL = "0x86aeA211B30174b3ee5d294ECeaDbD7f1C575eF3" -ACCOUNTING_IMPL = "0xDB47544d5813f15116bf95c1cF2ff4dEdb2226fD" -WITHDRAWAL_VAULT_IMPL = "0xB97e67CC20bd2970E30341c0ECc7497d8A5b7342" -CSM_IMPL = "0x161b1DAa658fD0D78a4603860edd8Ed06f98F4cA" -CS_PARAMETERS_REGISTRY_IMPL = "0x58376D8B192813E85532b25685D948EB49c2A8B5" -CS_FEE_ORACLE_IMPL = "0x27d1Ff0353AF6b7480CBc902169d0F89b49334B5" -CS_VETTED_GATE_IMPL = "0x3b834c6d043F4CE5C61d84723bA737D405B2e276" -CS_ACCOUNTING_IMPL = "0x3a18675fFB2C37A4296dD794A7Ed94644225F881" -CS_FEE_DISTRIBUTOR_IMPL = "0x74c5be19CcD1a264899FbCf8dB1a64C1e3fb73Ac" -CS_EXIT_PENALTIES_IMPL = "0xf38A3DA25B417D83182EEDD30d00557d78c35C96" -CS_VALIDATOR_STRIKES_IMPL = "0x47F96DCD5cf3e94492CD050c00C9F6e33b3ca677" DEFAULT_ADMIN_ROLE = "0x0000000000000000000000000000000000000000000000000000000000000000" -APP_MANAGER_ROLE = "0xb6d92708f3d4817afc106147d969e229ced5c46e65e0a5002a0d391287762bd0" -BUFFER_RESERVE_MANAGER_ROLE = "0x33969636f1fbf3d7d062d4de4a08e7bd3c46606ec28b3a4398d2665be559b921" -STAKING_MODULE_MANAGE_ROLE = "0x3105bcbf19d4417b73ae0e58d508a65ecf75665e46c2622d8521732de6080c48" -STAKING_MODULE_UNVETTING_ROLE = "0x240525496a9dc32284b17ce03b43e539e4bd81414634ee54395030d793463b57" -STAKING_MODULE_SHARE_MANAGE_ROLE = "0x43bf0e13900cfaa1b03ed5681dc143266597e29a1d6f9cbd84114f0ac21cd208" -REPORT_EXITED_VALIDATORS_ROLE = "0xc23292b191d95d2a7dd94fc6436eb44338fda9e1307d9394fd27c28157c1b33c" -REPORT_VALIDATOR_EXITING_STATUS_ROLE = "0xbe1bd143a0dde8a867d58aab054bfdb25250951665c4570e39abc3b3de3c2d6c" -REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE = "0x0766e72e5c008b3df8129fb356d9176eef8544f6241e078b7d61aff604f8812b" -REPORT_REWARDS_MINTED_ROLE = "0x779e5c23cb7a5bcb9bfe1e9a5165a00057f12bcdfd13e374540fdf1a1cd91137" -TW_EXIT_LIMIT_MANAGER_ROLE = "0x03c30da9b9e4d4789ac88a294d39a63058ca4a498804c2aa823e381df59d0cf4" -REPORT_GENERAL_DELAYED_PENALTY_ROLE = "0xa2c92d51d5647473735e9dfd5e2edf65bcf2fc2c139c95cbed53c19dc227c0b5" -SETTLE_GENERAL_DELAYED_PENALTY_ROLE = "0xe4c6f42648e5067520394b287613558d8b8a48bc7a320523da96c04d46253bda" -REPORT_EL_REWARDS_STEALING_PENALTY_ROLE = "0x59911a6aa08a72fe3824aec4500dc42335c6d0702b6d5c5c72ceb265a0de9302" -SETTLE_EL_REWARDS_STEALING_PENALTY_ROLE = "0xe85fdec10fe0f93d0792364051df7c3d73e37c17b3a954bffe593960e3cd3012" -VERIFIER_ROLE = "0x0ce23c3e399818cfee81a7ab0880f714e53d7672b08df0fa62f2843416e1ea09" -REPORT_REGULAR_WITHDRAWN_VALIDATORS_ROLE = "0xb169cb0459e6d91326174ff566a2fcc3c7bb31ef3d4d83bec1d5679c611ab094" -REPORT_SLASHED_WITHDRAWN_VALIDATORS_ROLE = "0x2dba60a7b2c6bc437f1868d48dc8e53a95d71e78cef88de0aff6d952ecff8daa" -CREATE_NODE_OPERATOR_ROLE = "0xc72a21b38830f4d6418a239e17db78b945cc7cfee674bac97fd596eaf0438478" -RESUME_ROLE = "0x2fc10cc8ae19568712f7a176fb4978616a610650813c9d05326c34abb62749c7" -START_REFERRAL_SEASON_ROLE = "0xc0bd4bb446c4ce6fd2289aa78c8ea233de3ad2b870bc787b2ba154e19c271f12" -END_REFERRAL_SEASON_ROLE = "0x4a1304957825c6a76938ccf907b92b9b872c8348083e23dae57e7e6111105d0c" -MANAGE_GENERAL_PENALTIES_AND_CHARGES_ROLE = "0x00b6097bf7ad894f88f786cd383df3190b971af96510047737d0cb2e9bd25558" -REQUEST_BURN_SHARES_ROLE = "0x4be29e0e4eb91f98f709d98803cba271592782e293b84a625e025cbb40197ba8" -REQUEST_BURN_MY_STETH_ROLE = "0x28186f938b759084eea36948ef1cd8b40ec8790a98d5f1a09b70879fe054e5cc" -ADD_FULL_WITHDRAWAL_REQUEST_ROLE = "0x15fac8ba7fe8dd5344b88c1915452ce66976f270d1cd793c3b0ab579cecd33c0" -EXIT_BALANCE_LIMIT_SET_TOPIC = "0x28a59cb43d86267095565f85c40c9110eb77192a738ef87891ba3696c423a531" -CIRCUIT_BREAKER_BLOCKER_ADDED_TOPIC = "0xd92c3c28ed17463268f864776463c4c2154f89b18156d3edf77c0e37d0476913" -CIRCUIT_BREAKER_COMMITTEE_ACTIVATED_TOPIC = "0x4ea9e94baeeb3668b47d8d9b4cc8f5a1784d783dd263d7d76f8c10d6a10aed44" +APP_MANAGER_ROLE = web3.keccak(text="APP_MANAGER_ROLE").hex() +BUFFER_RESERVE_MANAGER_ROLE = web3.keccak(text="BUFFER_RESERVE_MANAGER_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() +REPORT_REWARDS_MINTED_ROLE = web3.keccak(text="REPORT_REWARDS_MINTED_ROLE").hex() +TW_EXIT_LIMIT_MANAGER_ROLE = web3.keccak(text="TW_EXIT_LIMIT_MANAGER_ROLE").hex() +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() +RESUME_ROLE = web3.keccak(text="RESUME_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() +MANAGE_GENERAL_PENALTIES_AND_CHARGES_ROLE = web3.keccak(text="MANAGE_GENERAL_PENALTIES_AND_CHARGES_ROLE").hex() +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() +ADD_FULL_WITHDRAWAL_REQUEST_ROLE = web3.keccak(text="ADD_FULL_WITHDRAWAL_REQUEST_ROLE").hex() +EXIT_BALANCE_LIMIT_SET_TOPIC = web3.keccak(text="ExitBalanceLimitSet(uint256,uint256,uint256)").hex() +CIRCUIT_BREAKER_PAUSER_SET_TOPIC = web3.keccak(text="PauserSet(address,address,address)").hex() +CIRCUIT_BREAKER_HEARTBEAT_UPDATED_TOPIC = web3.keccak(text="HeartbeatUpdated(address,uint256)").hex() AO_CONTRACT_VERSION = 5 AO_CONSENSUS_VERSION = 6 AO_PREV_CONSENSUS_VERSION = 5 @@ -156,13 +93,6 @@ TW_EXITS_PER_FRAME = 1 TW_FRAME_DURATION_IN_SEC = 240 CURATED_MODULE_ID = 5 -CURATED_MODULE_NAME = "curated-onchain-v2" -CURATED_STAKE_SHARE_LIMIT = 2000 -CURATED_PRIORITY_EXIT_SHARE_THRESHOLD = 2500 -CURATED_STAKING_MODULE_FEE = 800 -CURATED_TREASURY_FEE = 200 -CURATED_MAX_DEPOSITS_PER_BLOCK = 30 -CURATED_MIN_DEPOSIT_BLOCK_DISTANCE = 25 CURATED_INITIAL_EPOCH = 47480 CURATED_EPOCHS_PER_FRAME = 1575 # TODO: restore Easy Track checks when full ET flow is enabled again. @@ -199,19 +129,6 @@ class StakingModuleItem(NamedTuple): min_deposit_block_distance: int -CURATED_MODULE_V2 = StakingModuleItem( - id=CURATED_MODULE_ID, - staking_module_address=CURATED_MODULE, - name=CURATED_MODULE_NAME, - staking_module_fee=CURATED_STAKING_MODULE_FEE, - stake_share_limit=CURATED_STAKE_SHARE_LIMIT, - treasury_fee=CURATED_TREASURY_FEE, - priority_exit_share_threshold=CURATED_PRIORITY_EXIT_SHARE_THRESHOLD, - max_deposits_per_block=CURATED_MAX_DEPOSITS_PER_BLOCK, - min_deposit_block_distance=CURATED_MIN_DEPOSIT_BLOCK_DISTANCE, -) - - def _is_placeholder_address(value: str) -> bool: normalized = str(value).lower() return normalized in ("", "0x0000000000000000000000000000000000000000") @@ -271,12 +188,16 @@ def _normalize_hex_data(data_hex) -> str: return normalized.replace("0x", "") -def _group_raw_dg_events_from_receipt(receipt: TransactionReceipt) -> list[list[dict]]: +def _group_raw_dg_events_from_receipt( + receipt: TransactionReceipt, + timelock: str, + admin_executor: str, +) -> list[list[dict]]: events = tx_events_from_receipt(receipt) assert len(events) >= 1, "Unexpected raw DG events count" assert ( - convert.to_address(events[-1]["address"]) == convert.to_address(EMERGENCY_PROTECTED_TIMELOCK) + convert.to_address(events[-1]["address"]) == convert.to_address(timelock) and events[-1]["name"] == "ProposalExecuted" ), "Unexpected raw DG service event" @@ -287,7 +208,7 @@ def _group_raw_dg_events_from_receipt(receipt: TransactionReceipt) -> list[list[ current_group.append(event) is_end_of_group = event["name"] == "Executed" and convert.to_address(event["address"]) == convert.to_address( - DUAL_GOVERNANCE_ADMIN_EXECUTOR + admin_executor ) if is_end_of_group: groups.append(current_group) @@ -355,6 +276,7 @@ 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", "ScriptResult", "Executed"]) @@ -363,7 +285,7 @@ def validate_role_grant_event( 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(AGENT), "Wrong role grant sender" + 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) @@ -373,6 +295,7 @@ 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", "ScriptResult", "Executed"]) @@ -381,7 +304,7 @@ def validate_role_revoke_event( 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(AGENT), "Wrong role revoke sender" + 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) @@ -392,7 +315,7 @@ def validate_dg_noop_event(event: EventDict) -> None: assert event.count("ScriptResult") == 1 assert event.count("Executed") == 1 -def validate_module_add(event: EventDict, module: StakingModuleItem, emitted_by: str) -> None: +def validate_module_add(event: EventDict, module: StakingModuleItem, emitted_by: str, sender: str) -> None: validate_events_chain( [e.name for e in event], [ @@ -412,33 +335,33 @@ def validate_module_add(event: EventDict, module: StakingModuleItem, emitted_by: 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(AGENT) + 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(AGENT) + 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(AGENT) + 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(AGENT) + 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(AGENT) + 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") @@ -447,7 +370,7 @@ def validate_module_add(event: EventDict, module: StakingModuleItem, emitted_by: _assert_emitted_by(deposited_event, emitted_by) -def validate_exit_balance_limit_set_raw_group(raw_group: list[dict]) -> None: +def validate_exit_balance_limit_set_raw_group(raw_group: list[dict], validators_exit_bus_oracle: str) -> None: validate_events_chain( [event["name"] for event in raw_group], [ @@ -464,7 +387,7 @@ def validate_exit_balance_limit_set_raw_group(raw_group: list[dict]) -> None: unknown_event = raw_group[5] unknown_event_values = _raw_event_values(unknown_event) - assert convert.to_address(unknown_event["address"]) == convert.to_address(VALIDATORS_EXIT_BUS_ORACLE) + assert convert.to_address(unknown_event["address"]) == convert.to_address(validators_exit_bus_oracle) assert unknown_event_values["topic1"] == EXIT_BALANCE_LIMIT_SET_TOPIC decoded_words = _decode_uint256_words(unknown_event_values["data"]) @@ -475,7 +398,12 @@ def validate_exit_balance_limit_set_raw_group(raw_group: list[dict]) -> None: ] -def validate_circuit_breaker_registration_raw_group(raw_group: list[dict]) -> None: +def validate_circuit_breaker_registration_raw_group( + raw_group: list[dict], + circuit_breaker: str, + consolidation_gateway: str, + curated_module_committee: str, +) -> None: validate_events_chain( [event["name"] for event in raw_group], ["LogScriptCall", "(unknown)", "(unknown)", "ScriptResult", "Executed"], @@ -484,58 +412,147 @@ def validate_circuit_breaker_registration_raw_group(raw_group: list[dict]) -> No first_unknown_event = raw_group[1] second_unknown_event = raw_group[2] - assert convert.to_address(first_unknown_event["address"]) == convert.to_address(CIRCUIT_BREAKER) + assert convert.to_address(first_unknown_event["address"]) == convert.to_address(circuit_breaker) first_unknown_event_values = _raw_event_values(first_unknown_event) - assert first_unknown_event_values["topic1"] == CIRCUIT_BREAKER_BLOCKER_ADDED_TOPIC - assert first_unknown_event_values["topic2"] == _address_to_topic(CONSOLIDATION_GATEWAY) + assert first_unknown_event_values["topic1"] == CIRCUIT_BREAKER_PAUSER_SET_TOPIC + assert first_unknown_event_values["topic2"] == _address_to_topic(consolidation_gateway) assert first_unknown_event_values["topic3"] == _address_to_topic("0x0000000000000000000000000000000000000000") - assert first_unknown_event_values["topic4"] == _address_to_topic(CURATED_MODULE_COMMITTEE) + assert first_unknown_event_values["topic4"] == _address_to_topic(curated_module_committee) assert _normalize_hex_data(first_unknown_event_values["data"]) == "00" - assert convert.to_address(second_unknown_event["address"]) == convert.to_address(CIRCUIT_BREAKER) + assert convert.to_address(second_unknown_event["address"]) == convert.to_address(circuit_breaker) second_unknown_event_values = _raw_event_values(second_unknown_event) - assert second_unknown_event_values["topic1"] == CIRCUIT_BREAKER_COMMITTEE_ACTIVATED_TOPIC - assert second_unknown_event_values["topic2"] == _address_to_topic(CURATED_MODULE_COMMITTEE) + assert second_unknown_event_values["topic1"] == CIRCUIT_BREAKER_HEARTBEAT_UPDATED_TOPIC + assert second_unknown_event_values["topic2"] == _address_to_topic(curated_module_committee) assert int(_normalize_hex_data(second_unknown_event_values["data"]), 16) > 0 @pytest.fixture(scope="module") -def runtime_upgrade_addresses(): +def runtime_upgrade_context(): if network_name() != "hoodi-fork": pytest.skip("Run the dedicated Hoodi upgrade test on --network hoodi-fork.") upgrade_vote_script = get_upgrade_vote_script_address() - factories = get_easy_track_new_factories() - update_staking_module_share_limits_factory = factories["UpdateStakingModuleShareLimits"] - allow_consolidation_pair_factory = factories["AllowConsolidationPair"] - create_or_update_operator_group_factory = factories["CreateOrUpdateOperatorGroup"] - consolidation_migrator = get_consolidation_migrator_address() - meta_registry = get_meta_registry_address() - if ( _is_placeholder_address(upgrade_vote_script) - or _is_placeholder_address(update_staking_module_share_limits_factory) - or _is_placeholder_address(allow_consolidation_pair_factory) - or _is_placeholder_address(create_or_update_operator_group_factory) - or _is_placeholder_address(consolidation_migrator) - or _is_placeholder_address(meta_registry) or _is_placeholder_text(DG_PROPOSAL_METADATA) or _is_placeholder_text(get_ipfs_description(dg_only=DG_ONLY_MODE)) ): pytest.skip("Local Hoodi upgrade artifacts are missing. Run the lido-core deploy flow 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, _ = upgrade_config.getEasyTrackConfig() + + 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() + return { "upgrade_vote_script": upgrade_vote_script, - "update_staking_module_share_limits_factory": update_staking_module_share_limits_factory, - "allow_consolidation_pair_factory": allow_consolidation_pair_factory, - "create_or_update_operator_group_factory": create_or_update_operator_group_factory, - "consolidation_migrator": consolidation_migrator, - "meta_registry": meta_registry, + "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_app_id": core_config["lidoAppId"], + "lido_impl": core_config["newLidoImpl"], + "lido_locator": core_config["locator"], + "lido_locator_impl": core_config["newLocatorImpl"], + "staking_router": global_config["stakingRouter"], + "staking_router_impl": core_config["newStakingRouterImpl"], + "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"], + "validator_exit_delay_verifier": locator_impl.validatorExitDelayVerifier(), + "easytrack_evm_script_executor": global_config["easyTrackEVMScriptExecutor"], + "circuit_breaker": global_config["circuitBreaker"], + "consolidation_gateway": core_config["consolidationGateway"], + "curated_module_committee": core_config["curatedModuleCommittee"], + "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_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["verifier"], + "verifier_v3": csm_config["verifierV3"], + "old_permissionless_gate": csm_config["oldPermissionlessGate"], + "new_permissionless_gate": csm_config["permissionlessGate"], + "ics_manager": csm_config["identifiedCommunityStakersGateManager"], + "csm_general_delayed_penalty_reporter": csm_config["generalDelayedPenaltyReporter"], + "csm_penalties_manager": csm_config["penaltiesManager"], + "old_csm_ejector": old_csm_ejector, + "csm_ejector": csm_config["ejector"], + "curated_module": curated_config["module"], + "curated_accounting": curated_config["accounting"], + "curated_ejector": curated_config["ejector"], + "curated_hash_consensus": curated_config["hashConsensus"], + "curated_module_item": StakingModuleItem( + id=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"], + "create_or_update_operator_group_factory": easy_track_new_factories["CreateOrUpdateOperatorGroup"], + "consolidation_migrator": core_config["consolidationMigrator"], + "meta_registry": curated_config["metaRegistry"], } @pytest.fixture(scope="module") -def dual_governance_proposal_calls(runtime_upgrade_addresses): +def dual_governance_proposal_calls(runtime_upgrade_context): dg_items = get_dg_items() proposal_calls = [] @@ -551,11 +568,13 @@ def dual_governance_proposal_calls(runtime_upgrade_addresses): return proposal_calls -def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_governance_proposal_calls): - voting = interface.Voting(VOTING) - agent = interface.Agent(AGENT) +def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_governance_proposal_calls, runtime_upgrade_context): + ctx = runtime_upgrade_context + + voting = interface.Voting(ctx["voting"]) + agent = interface.Agent(ctx["agent"]) timelock = interface.EmergencyProtectedTimelock(EMERGENCY_PROTECTED_TIMELOCK) - dual_governance = interface.DualGovernance(DUAL_GOVERNANCE) + dual_governance = interface.DualGovernance(ctx["dual_governance"]) # TODO: restore once Easy Track items are enabled in the vote again. # easy_track = interface.EasyTrack(EASYTRACK) # staking_router = interface.StakingRouter(STAKING_ROUTER) @@ -564,7 +583,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g vote_desc_items, call_script_items = get_vote_items(dg_only=DG_ONLY_MODE) dg_items = get_dg_items() - upgrade_template = get_state_address("upgradeTemplate") + upgrade_template = ctx["upgrade_template"] expected_vote_events_count = EXPECTED_VOTE_EVENTS_COUNT or len(call_script_items) expected_dg_events_from_agent = EXPECTED_DG_EVENTS_FROM_AGENT or len(dg_items) @@ -633,8 +652,8 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g validate_dual_governance_submit_event( vote_events[0], proposal_id=expected_dg_proposal_id, - proposer=VOTING, - executor=DUAL_GOVERNANCE_ADMIN_EXECUTOR, + proposer=ctx["voting"], + executor=ctx["dual_governance_admin_executor"], metadata=DG_PROPOSAL_METADATA, proposal_calls=dual_governance_proposal_calls, ) @@ -695,9 +714,13 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g dg_events = group_dg_events_from_receipt( dg_tx, timelock=EMERGENCY_PROTECTED_TIMELOCK, - admin_executor=DUAL_GOVERNANCE_ADMIN_EXECUTOR, + admin_executor=ctx["dual_governance_admin_executor"], + ) + raw_dg_events = _group_raw_dg_events_from_receipt( + dg_tx, + timelock=EMERGENCY_PROTECTED_TIMELOCK, + admin_executor=ctx["dual_governance_admin_executor"], ) - raw_dg_events = _group_raw_dg_events_from_receipt(dg_tx) assert count_vote_items_by_events(dg_tx, agent.address) == expected_dg_events_from_agent assert len(dg_events) == expected_dg_events_count assert len(raw_dg_events) == expected_dg_events_count @@ -710,13 +733,13 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g _assert_emitted_by(upgrade_started_event, upgrade_template) # 2. Upgrade LidoLocator proxy - validate_proxy_upgrade_event(dg_events[1], LIDO_LOCATOR_IMPL, emitted_by=LIDO_LOCATOR) + validate_proxy_upgrade_event(dg_events[1], ctx["lido_locator_impl"], emitted_by=ctx["lido_locator"]) # 3. Upgrade and finalize StakingRouter validate_proxy_upgrade_event( dg_events[2], - STAKING_ROUTER_IMPL, - emitted_by=STAKING_ROUTER, + ctx["staking_router_impl"], + emitted_by=ctx["staking_router"], events_chain=[ "LogScriptCall", "Upgraded", @@ -738,29 +761,29 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g for role_granted_event, (role_hash, account) in zip( role_grants, [ - (DEFAULT_ADMIN_ROLE, AGENT), - (STAKING_MODULE_MANAGE_ROLE, AGENT), + (DEFAULT_ADMIN_ROLE, ctx["agent"]), + (STAKING_MODULE_MANAGE_ROLE, ctx["agent"]), (STAKING_MODULE_MANAGE_ROLE, HOODI_LEGACY_STAKING_MODULE_MANAGER), - (STAKING_MODULE_UNVETTING_ROLE, OLD_DEPOSIT_SECURITY_MODULE), - (REPORT_EXITED_VALIDATORS_ROLE, ACCOUNTING_ORACLE), - (REPORT_VALIDATOR_EXITING_STATUS_ROLE, VALIDATOR_EXIT_DELAY_VERIFIER), - (REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE, TRIGGERABLE_WITHDRAWALS_GATEWAY), - (REPORT_REWARDS_MINTED_ROLE, ACCOUNTING), + (STAKING_MODULE_UNVETTING_ROLE, ctx["old_deposit_security_module"]), + (REPORT_EXITED_VALIDATORS_ROLE, ctx["accounting_oracle"]), + (REPORT_VALIDATOR_EXITING_STATUS_ROLE, ctx["validator_exit_delay_verifier"]), + (REPORT_VALIDATOR_EXIT_TRIGGERED_ROLE, ctx["triggerable_withdrawals_gateway"]), + (REPORT_REWARDS_MINTED_ROLE, ctx["accounting"]), ], ): assert _normalize_role(role_granted_event["role"]) == role_hash.replace("0x", "") assert convert.to_address(role_granted_event["account"]) == convert.to_address(account) - assert convert.to_address(role_granted_event["sender"]) == convert.to_address(AGENT) - _assert_emitted_by(role_granted_event, STAKING_ROUTER) + 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"] == 4 - _assert_emitted_by(initialized_event, STAKING_ROUTER) + _assert_emitted_by(initialized_event, ctx["staking_router"]) # 4. Upgrade and finalize AccountingOracle validate_proxy_upgrade_event( dg_events[3], - ACCOUNTING_ORACLE_IMPL, - emitted_by=ACCOUNTING_ORACLE, + ctx["accounting_oracle_impl"], + emitted_by=ctx["accounting_oracle"], events_chain=[ "LogScriptCall", "Upgraded", @@ -773,7 +796,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g validate_contract_version_set_event( dg_events[3], AO_CONTRACT_VERSION, - emitted_by=ACCOUNTING_ORACLE, + emitted_by=ctx["accounting_oracle"], events_chain=[ "LogScriptCall", "Upgraded", @@ -787,7 +810,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g dg_events[3], AO_CONSENSUS_VERSION, AO_PREV_CONSENSUS_VERSION, - emitted_by=ACCOUNTING_ORACLE, + emitted_by=ctx["accounting_oracle"], events_chain=[ "LogScriptCall", "Upgraded", @@ -801,8 +824,8 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g # 5. Upgrade and finalize ValidatorsExitBusOracle validate_proxy_upgrade_event( dg_events[4], - VALIDATORS_EXIT_BUS_ORACLE_IMPL, - emitted_by=VALIDATORS_EXIT_BUS_ORACLE, + ctx["validators_exit_bus_oracle_impl"], + emitted_by=ctx["validators_exit_bus_oracle"], events_chain=[ "LogScriptCall", "Upgraded", @@ -817,7 +840,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g validate_contract_version_set_event( dg_events[4], VEBO_CONTRACT_VERSION, - emitted_by=VALIDATORS_EXIT_BUS_ORACLE, + emitted_by=ctx["validators_exit_bus_oracle"], events_chain=[ "LogScriptCall", "Upgraded", @@ -833,7 +856,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g dg_events[4], VEBO_CONSENSUS_VERSION, VEBO_PREV_CONSENSUS_VERSION, - emitted_by=VALIDATORS_EXIT_BUS_ORACLE, + emitted_by=ctx["validators_exit_bus_oracle"], events_chain=[ "LogScriptCall", "Upgraded", @@ -847,50 +870,50 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g ) 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, VALIDATORS_EXIT_BUS_ORACLE) - validate_exit_balance_limit_set_raw_group(raw_dg_events[4]) + _assert_emitted_by(set_max_validators_event, ctx["validators_exit_bus_oracle"]) + validate_exit_balance_limit_set_raw_group(raw_dg_events[4], ctx["validators_exit_bus_oracle"]) # 6. Upgrade Accounting implementation - validate_proxy_upgrade_event(dg_events[5], ACCOUNTING_IMPL, emitted_by=ACCOUNTING) + validate_proxy_upgrade_event(dg_events[5], ctx["accounting_impl"], emitted_by=ctx["accounting"]) # 7. Upgrade and finalize WithdrawalVault validate_proxy_upgrade_event( dg_events[6], - WITHDRAWAL_VAULT_IMPL, - emitted_by=WITHDRAWAL_VAULT, + ctx["withdrawal_vault_impl"], + emitted_by=ctx["withdrawal_vault"], events_chain=["LogScriptCall", "Upgraded", "ContractVersionSet", "ScriptResult", "Executed"], ) validate_contract_version_set_event( dg_events[6], WITHDRAWAL_VAULT_CONTRACT_VERSION, - emitted_by=WITHDRAWAL_VAULT, + emitted_by=ctx["withdrawal_vault"], events_chain=["LogScriptCall", "Upgraded", "ContractVersionSet", "ScriptResult", "Executed"], ) # 8. Grant APP_MANAGER_ROLE on Kernel to Agent validate_aragon_grant_permission_event( dg_events[7], - entity=AGENT, - app=ARAGON_KERNEL, + entity=ctx["agent"], + app=ctx["aragon_kernel"], role=APP_MANAGER_ROLE, - emitted_by=ACL, + emitted_by=ctx["acl"], ) # 9. Set new Lido implementation in Kernel validate_aragon_set_app_event( dg_events[8], - app_id=LIDO_APP_ID, - app=LIDO_IMPL, - emitted_by=ARAGON_KERNEL, + app_id=ctx["lido_app_id"], + app=ctx["lido_impl"], + emitted_by=ctx["aragon_kernel"], ) # 10. Revoke APP_MANAGER_ROLE on Kernel from Agent validate_aragon_revoke_permission_event( dg_events[9], - entity=AGENT, - app=ARAGON_KERNEL, + entity=ctx["agent"], + app=ctx["aragon_kernel"], role=APP_MANAGER_ROLE, - emitted_by=ACL, + emitted_by=ctx["acl"], ) # 11. Grant BUFFER_RESERVE_MANAGER_ROLE on Lido and transfer permission manager to Agent @@ -899,50 +922,54 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g ["LogScriptCall", "SetPermission", "ChangePermissionManager", "ScriptResult", "Executed"], ) set_permission_event = _single_event(dg_events[10], "SetPermission") - assert convert.to_address(set_permission_event["entity"]) == convert.to_address(AGENT) - assert convert.to_address(set_permission_event["app"]) == convert.to_address(LIDO) + 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, ACL) + _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(LIDO) + 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(AGENT) - _assert_emitted_by(change_permission_manager_event, ACL) + assert convert.to_address(change_permission_manager_event["manager"]) == convert.to_address(ctx["agent"]) + _assert_emitted_by(change_permission_manager_event, ctx["acl"]) # 12. Finalize Lido contract version - validate_contract_version_set_event(dg_events[11], LIDO_CONTRACT_VERSION, emitted_by=LIDO) + validate_contract_version_set_event(dg_events[11], LIDO_CONTRACT_VERSION, emitted_by=ctx["lido"]) # 13. Grant STAKING_MODULE_SHARE_MANAGE_ROLE to EasyTrack executor validate_role_grant_event( dg_events[12], STAKING_MODULE_SHARE_MANAGE_ROLE, - EASYTRACK_EVMSCRIPT_EXECUTOR, - emitted_by=STAKING_ROUTER, + ctx["easytrack_evm_script_executor"], + sender=ctx["agent"], + emitted_by=ctx["staking_router"], ) # 14. Revoke STAKING_MODULE_UNVETTING_ROLE from old DSM validate_role_revoke_event( dg_events[13], STAKING_MODULE_UNVETTING_ROLE, - OLD_DEPOSIT_SECURITY_MODULE, - emitted_by=STAKING_ROUTER, + ctx["old_deposit_security_module"], + sender=ctx["agent"], + emitted_by=ctx["staking_router"], ) # 15. Grant STAKING_MODULE_UNVETTING_ROLE to new DSM validate_role_grant_event( dg_events[14], STAKING_MODULE_UNVETTING_ROLE, - NEW_DEPOSIT_SECURITY_MODULE, - emitted_by=STAKING_ROUTER, + ctx["new_deposit_security_module"], + sender=ctx["agent"], + emitted_by=ctx["staking_router"], ) # 16. Grant TW_EXIT_LIMIT_MANAGER_ROLE to Agent validate_role_grant_event( dg_events[15], TW_EXIT_LIMIT_MANAGER_ROLE, - AGENT, - emitted_by=TRIGGERABLE_WITHDRAWALS_GATEWAY, + ctx["agent"], + sender=ctx["agent"], + emitted_by=ctx["triggerable_withdrawals_gateway"], ) # 17. Set TWG exit limits @@ -954,169 +981,184 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g 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, TRIGGERABLE_WITHDRAWALS_GATEWAY) + _assert_emitted_by(exit_requests_limit_set_event, ctx["triggerable_withdrawals_gateway"]) # 18. Register CircuitBreaker integration - validate_circuit_breaker_registration_raw_group(raw_dg_events[17]) + validate_circuit_breaker_registration_raw_group( + raw_dg_events[17], + circuit_breaker=ctx["circuit_breaker"], + consolidation_gateway=ctx["consolidation_gateway"], + curated_module_committee=ctx["curated_module_committee"], + ) # 19. Upgrade and initialize CSM validate_proxy_upgrade_event( dg_events[18], - CSM_IMPL, - emitted_by=CSM, + ctx["csm_impl"], + emitted_by=ctx["csm"], events_chain=["LogScriptCall", "Upgraded", "Initialized", "ScriptResult", "Executed"], ) initialized_event = _single_event(dg_events[18], "Initialized") assert initialized_event["version"] == 3 - _assert_emitted_by(initialized_event, CSM) + _assert_emitted_by(initialized_event, ctx["csm"]) # 20. Upgrade and initialize CSParametersRegistry validate_proxy_upgrade_event( dg_events[19], - CS_PARAMETERS_REGISTRY_IMPL, - emitted_by=CS_PARAMETERS_REGISTRY, + ctx["cs_parameters_registry_impl"], + emitted_by=ctx["cs_parameters_registry"], events_chain=["LogScriptCall", "Upgraded", "Initialized", "ScriptResult", "Executed"], ) initialized_event = _single_event(dg_events[19], "Initialized") assert initialized_event["version"] == 3 - _assert_emitted_by(initialized_event, CS_PARAMETERS_REGISTRY) + _assert_emitted_by(initialized_event, ctx["cs_parameters_registry"]) # 21. Upgrade and finalize CSFeeOracle validate_proxy_upgrade_event( dg_events[20], - CS_FEE_ORACLE_IMPL, - emitted_by=CS_FEE_ORACLE, + ctx["cs_fee_oracle_impl"], + emitted_by=ctx["cs_fee_oracle"], events_chain=["LogScriptCall", "Upgraded", "ConsensusVersionSet", "ContractVersionSet", "ScriptResult", "Executed"], ) validate_consensus_version_set_event( dg_events[20], 4, 3, - emitted_by=CS_FEE_ORACLE, + emitted_by=ctx["cs_fee_oracle"], events_chain=["LogScriptCall", "Upgraded", "ConsensusVersionSet", "ContractVersionSet", "ScriptResult", "Executed"], ) validate_contract_version_set_event( dg_events[20], 3, - emitted_by=CS_FEE_ORACLE, + emitted_by=ctx["cs_fee_oracle"], events_chain=["LogScriptCall", "Upgraded", "ConsensusVersionSet", "ContractVersionSet", "ScriptResult", "Executed"], ) # 22. Upgrade CSVettedGate - validate_proxy_upgrade_event(dg_events[21], CS_VETTED_GATE_IMPL, emitted_by=CS_VETTED_GATE) + validate_proxy_upgrade_event(dg_events[21], ctx["cs_vetted_gate_impl"], emitted_by=ctx["cs_vetted_gate"]) # 23. Upgrade and initialize CSAccounting validate_proxy_upgrade_event( dg_events[22], - CS_ACCOUNTING_IMPL, - emitted_by=CS_ACCOUNTING, + ctx["cs_accounting_impl"], + emitted_by=ctx["cs_accounting"], events_chain=["LogScriptCall", "Upgraded", "Initialized", "ScriptResult", "Executed"], ) initialized_event = _single_event(dg_events[22], "Initialized") assert initialized_event["version"] == 3 - _assert_emitted_by(initialized_event, CS_ACCOUNTING) + _assert_emitted_by(initialized_event, ctx["cs_accounting"]) # 24. Upgrade and initialize CSFeeDistributor validate_proxy_upgrade_event( dg_events[23], - CS_FEE_DISTRIBUTOR_IMPL, - emitted_by=CS_FEE_DISTRIBUTOR, + ctx["cs_fee_distributor_impl"], + emitted_by=ctx["cs_fee_distributor"], events_chain=["LogScriptCall", "Upgraded", "Initialized", "ScriptResult", "Executed"], ) initialized_event = _single_event(dg_events[23], "Initialized") assert initialized_event["version"] == 3 - _assert_emitted_by(initialized_event, CS_FEE_DISTRIBUTOR) + _assert_emitted_by(initialized_event, ctx["cs_fee_distributor"]) # 25. Upgrade CSExitPenalties - validate_proxy_upgrade_event(dg_events[24], CS_EXIT_PENALTIES_IMPL, emitted_by=CS_EXIT_PENALTIES) + validate_proxy_upgrade_event(dg_events[24], ctx["cs_exit_penalties_impl"], emitted_by=ctx["cs_exit_penalties"]) # 26. Upgrade CSValidatorStrikes - validate_proxy_upgrade_event(dg_events[25], CS_VALIDATOR_STRIKES_IMPL, emitted_by=CS_VALIDATOR_STRIKES) + validate_proxy_upgrade_event(dg_events[25], ctx["cs_validator_strikes_impl"], emitted_by=ctx["cs_validator_strikes"]) # 27. Set CSM ejector validate_events_chain([e.name for e in dg_events[26]], ["LogScriptCall", "EjectorSet", "ScriptResult", "Executed"]) ejector_set_event = _single_event(dg_events[26], "EjectorSet") - assert convert.to_address(ejector_set_event["ejector"]) == convert.to_address(CSM_EJECTOR) - _assert_emitted_by(ejector_set_event, CS_VALIDATOR_STRIKES) + assert convert.to_address(ejector_set_event["ejector"]) == convert.to_address(ctx["csm_ejector"]) + _assert_emitted_by(ejector_set_event, ctx["cs_validator_strikes"]) # 28. Grant REPORT_GENERAL_DELAYED_PENALTY_ROLE validate_role_grant_event( dg_events[27], REPORT_GENERAL_DELAYED_PENALTY_ROLE, - CSM_GENERAL_DELAYED_PENALTY_REPORTER, - emitted_by=CSM, + ctx["csm_general_delayed_penalty_reporter"], + sender=ctx["agent"], + emitted_by=ctx["csm"], ) # 29. Grant SETTLE_GENERAL_DELAYED_PENALTY_ROLE validate_role_grant_event( dg_events[28], SETTLE_GENERAL_DELAYED_PENALTY_ROLE, - EASYTRACK_EVMSCRIPT_EXECUTOR, - emitted_by=CSM, + ctx["easytrack_evm_script_executor"], + sender=ctx["agent"], + emitted_by=ctx["csm"], ) # 30. Revoke REPORT_EL_REWARDS_STEALING_PENALTY_ROLE validate_role_revoke_event( dg_events[29], REPORT_EL_REWARDS_STEALING_PENALTY_ROLE, - CSM_GENERAL_DELAYED_PENALTY_REPORTER, - emitted_by=CSM, + ctx["csm_general_delayed_penalty_reporter"], + sender=ctx["agent"], + emitted_by=ctx["csm"], ) # 31. Revoke SETTLE_EL_REWARDS_STEALING_PENALTY_ROLE validate_role_revoke_event( dg_events[30], SETTLE_EL_REWARDS_STEALING_PENALTY_ROLE, - EASYTRACK_EVMSCRIPT_EXECUTOR, - emitted_by=CSM, + ctx["easytrack_evm_script_executor"], + sender=ctx["agent"], + emitted_by=ctx["csm"], ) # 32. Revoke VERIFIER_ROLE from old verifier validate_role_revoke_event( dg_events[31], VERIFIER_ROLE, - OLD_VERIFIER, - emitted_by=CSM, + ctx["old_verifier"], + sender=ctx["agent"], + emitted_by=ctx["csm"], ) # 33. Grant VERIFIER_ROLE to verifier v3 validate_role_grant_event( dg_events[32], VERIFIER_ROLE, - VERIFIER_V3, - emitted_by=CSM, + ctx["verifier_v3"], + sender=ctx["agent"], + emitted_by=ctx["csm"], ) # 34. Grant REPORT_REGULAR_WITHDRAWN_VALIDATORS_ROLE validate_role_grant_event( dg_events[33], REPORT_REGULAR_WITHDRAWN_VALIDATORS_ROLE, - VERIFIER_V3, - emitted_by=CSM, + ctx["verifier_v3"], + sender=ctx["agent"], + emitted_by=ctx["csm"], ) # 35. Grant REPORT_SLASHED_WITHDRAWN_VALIDATORS_ROLE validate_role_grant_event( dg_events[34], REPORT_SLASHED_WITHDRAWN_VALIDATORS_ROLE, - EASYTRACK_EVMSCRIPT_EXECUTOR, - emitted_by=CSM, + ctx["easytrack_evm_script_executor"], + sender=ctx["agent"], + emitted_by=ctx["csm"], ) # 36. Revoke CREATE_NODE_OPERATOR_ROLE from old permissionless gate validate_role_revoke_event( dg_events[35], CREATE_NODE_OPERATOR_ROLE, - OLD_PERMISSIONLESS_GATE, - emitted_by=CSM, + ctx["old_permissionless_gate"], + sender=ctx["agent"], + emitted_by=ctx["csm"], ) # 37. Grant CREATE_NODE_OPERATOR_ROLE to new permissionless gate validate_role_grant_event( dg_events[36], CREATE_NODE_OPERATOR_ROLE, - NEW_PERMISSIONLESS_GATE, - emitted_by=CSM, + ctx["new_permissionless_gate"], + sender=ctx["agent"], + emitted_by=ctx["csm"], ) # 38. No-op DG item @@ -1135,16 +1177,18 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g validate_role_revoke_event( dg_events[41], START_REFERRAL_SEASON_ROLE, - AGENT, - emitted_by=CS_VETTED_GATE, + ctx["agent"], + sender=ctx["agent"], + emitted_by=ctx["cs_vetted_gate"], ) # 43. Revoke END_REFERRAL_SEASON_ROLE from ICS manager validate_role_revoke_event( dg_events[42], END_REFERRAL_SEASON_ROLE, - ICS_MANAGER, - emitted_by=CS_VETTED_GATE, + ctx["ics_manager"], + sender=ctx["agent"], + emitted_by=ctx["cs_vetted_gate"], ) # 44. No-op DG item @@ -1163,80 +1207,89 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g validate_role_grant_event( dg_events[47], MANAGE_GENERAL_PENALTIES_AND_CHARGES_ROLE, - CSM_PENALTIES_MANAGER, - emitted_by=CS_PARAMETERS_REGISTRY, + ctx["csm_penalties_manager"], + sender=ctx["agent"], + emitted_by=ctx["cs_parameters_registry"], ) # 49. Revoke REQUEST_BURN_SHARES_ROLE from CSAccounting validate_role_revoke_event( dg_events[48], REQUEST_BURN_SHARES_ROLE, - CS_ACCOUNTING, - emitted_by=BURNER, + ctx["cs_accounting"], + sender=ctx["agent"], + emitted_by=ctx["burner"], ) # 50. Grant REQUEST_BURN_MY_STETH_ROLE to CSAccounting validate_role_grant_event( dg_events[49], REQUEST_BURN_MY_STETH_ROLE, - CS_ACCOUNTING, - emitted_by=BURNER, + ctx["cs_accounting"], + sender=ctx["agent"], + emitted_by=ctx["burner"], ) # 51. Revoke ADD_FULL_WITHDRAWAL_REQUEST_ROLE from old CSM ejector validate_role_revoke_event( dg_events[50], ADD_FULL_WITHDRAWAL_REQUEST_ROLE, - OLD_CSM_EJECTOR, - emitted_by=TRIGGERABLE_WITHDRAWALS_GATEWAY, + ctx["old_csm_ejector"], + sender=ctx["agent"], + emitted_by=ctx["triggerable_withdrawals_gateway"], ) # 52. Grant ADD_FULL_WITHDRAWAL_REQUEST_ROLE to CSM ejector validate_role_grant_event( dg_events[51], ADD_FULL_WITHDRAWAL_REQUEST_ROLE, - CSM_EJECTOR, - emitted_by=TRIGGERABLE_WITHDRAWALS_GATEWAY, + ctx["csm_ejector"], + sender=ctx["agent"], + emitted_by=ctx["triggerable_withdrawals_gateway"], ) # 53. Add curated-onchain-v2 module - validate_module_add(dg_events[52], CURATED_MODULE_V2, emitted_by=STAKING_ROUTER) + validate_module_add(dg_events[52], ctx["curated_module_item"], emitted_by=ctx["staking_router"], sender=ctx["agent"]) # 54. Grant REQUEST_BURN_MY_STETH_ROLE to curated accounting validate_role_grant_event( dg_events[53], REQUEST_BURN_MY_STETH_ROLE, - CURATED_ACCOUNTING, - emitted_by=BURNER, + ctx["curated_accounting"], + sender=ctx["agent"], + emitted_by=ctx["burner"], ) # 55. Grant ADD_FULL_WITHDRAWAL_REQUEST_ROLE to curated ejector validate_role_grant_event( dg_events[54], ADD_FULL_WITHDRAWAL_REQUEST_ROLE, - CURATED_EJECTOR, - emitted_by=TRIGGERABLE_WITHDRAWALS_GATEWAY, + ctx["curated_ejector"], + sender=ctx["agent"], + emitted_by=ctx["triggerable_withdrawals_gateway"], ) # 56. Grant RESUME_ROLE on curated module to Agent validate_role_grant_event( dg_events[55], RESUME_ROLE, - AGENT, - emitted_by=CURATED_MODULE, + ctx["agent"], + sender=ctx["agent"], + emitted_by=ctx["curated_module"], ) # 57. Resume curated module validate_events_chain([e.name for e in dg_events[56]], ["LogScriptCall", "Resumed", "ScriptResult", "Executed"]) resumed_event = _single_event(dg_events[56], "Resumed") - _assert_emitted_by(resumed_event, CURATED_MODULE) + _assert_emitted_by(resumed_event, ctx["curated_module"]) # 58. Revoke RESUME_ROLE from Agent validate_role_revoke_event( dg_events[57], RESUME_ROLE, - AGENT, - emitted_by=CURATED_MODULE, + ctx["agent"], + sender=ctx["agent"], + emitted_by=ctx["curated_module"], ) # 59. Set curated HashConsensus frame config @@ -1244,7 +1297,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g frame_config_set_event = _single_event(dg_events[58], "FrameConfigSet") assert frame_config_set_event["newInitialEpoch"] == CURATED_INITIAL_EPOCH assert frame_config_set_event["newEpochsPerFrame"] == CURATED_EPOCHS_PER_FRAME - _assert_emitted_by(frame_config_set_event, CURATED_HASH_CONSENSUS) + _assert_emitted_by(frame_config_set_event, ctx["curated_hash_consensus"]) # 60. Call UpgradeTemplate.finishUpgrade validate_events_chain([e.name for e in dg_events[59]], ["LogScriptCall", "UpgradeFinished", "ScriptResult", "Executed"]) diff --git a/utils/hoodi_upgrade.py b/utils/hoodi_upgrade.py new file mode 100644 index 00000000..8d1fb287 --- /dev/null +++ b/utils/hoodi_upgrade.py @@ -0,0 +1,139 @@ +import json +import os +from pathlib import Path +from typing import Any, Dict + +from brownie import Contract + +try: + import tomllib # type: ignore[attr-defined] +except ModuleNotFoundError: + import toml as tomllib # type: ignore[no-redef] + + +ZERO_ADDRESS = "0x0000000000000000000000000000000000000000" + +PROJECT_ROOT = Path(__file__).resolve().parents[1] +LIDO_CORE_ROOT = PROJECT_ROOT / "lido-core" + +DEFAULT_DEPLOYED_LOCAL_FILE = "deployed-local.json" +DEFAULT_UPGRADE_PARAMS_FILE = "scripts/upgrade/upgrade-params-hoodi.toml" +DEFAULT_CURATED_MODULE_ARTIFACT = "artifacts/contracts/upgrade/UpgradeTypes.sol/ICuratedModule.json" + + +def _resolve_lido_core_path(env_name: str, default_relative_path: str) -> Path: + value = os.getenv(env_name, default_relative_path) + path = Path(value) + if not path.is_absolute(): + path = LIDO_CORE_ROOT / path + return path + + +def get_deployed_local_path() -> Path: + return _resolve_lido_core_path("LIDO_CORE_DEPLOYED_FILE", DEFAULT_DEPLOYED_LOCAL_FILE) + + +def get_upgrade_params_path() -> Path: + return _resolve_lido_core_path("LIDO_CORE_UPGRADE_PARAMS_FILE", DEFAULT_UPGRADE_PARAMS_FILE) + + +def get_curated_module_artifact_path() -> Path: + return _resolve_lido_core_path("LIDO_CORE_CURATED_MODULE_ARTIFACT", DEFAULT_CURATED_MODULE_ARTIFACT) + + +def load_deployed_local_state() -> Dict[str, Any]: + state_path = get_deployed_local_path() + if not state_path.exists(): + raise FileNotFoundError(f"local deployment state file not found: {state_path}") + return json.loads(state_path.read_text()) + + +def _loads_toml(text: str) -> Dict[str, Any]: + return tomllib.loads(text) + + +def load_upgrade_params() -> Dict[str, Any]: + params_path = get_upgrade_params_path() + if not params_path.exists(): + raise FileNotFoundError(f"upgrade params file not found: {params_path}") + return _loads_toml(params_path.read_text()) + + +def get_state_address(key: str) -> str: + state = load_deployed_local_state() + item = state.get(key) + if item is None: + raise KeyError(f"deployment state key is missing: {key}") + + if isinstance(item, dict): + address = item.get("address") + if isinstance(address, str): + return address + + proxy = item.get("proxy") + if isinstance(proxy, dict) and isinstance(proxy.get("address"), str): + return proxy["address"] + + raise KeyError(f"could not extract address from deployment state key: {key}") + + +def get_optional_state_address(key: str, default: str = ZERO_ADDRESS) -> str: + try: + return get_state_address(key) + except Exception: + return default + + +def get_upgrade_vote_script_address() -> str: + return get_state_address("upgradeVoteScript") + + +def get_optional_upgrade_vote_script_address(default: str = ZERO_ADDRESS) -> str: + return get_optional_state_address("upgradeVoteScript", default) + + +def get_consolidation_migrator_address() -> str: + return get_state_address("consolidationMigrator") + + +def get_optional_consolidation_migrator_address(default: str = ZERO_ADDRESS) -> str: + return get_optional_state_address("consolidationMigrator", default) + + +def get_easy_track_new_factories() -> Dict[str, str]: + params = load_upgrade_params() + return dict(params["easyTrack"]["newFactories"]) + + +def get_optional_easy_track_new_factories() -> Dict[str, str]: + try: + return get_easy_track_new_factories() + except Exception: + return { + "UpdateStakingModuleShareLimits": ZERO_ADDRESS, + "AllowConsolidationPair": ZERO_ADDRESS, + "CreateOrUpdateOperatorGroup": ZERO_ADDRESS, + } + + +def get_curated_module_address() -> str: + params = load_upgrade_params() + return params["curatedModule"]["module"] + + +def get_meta_registry_address() -> str: + artifact_path = get_curated_module_artifact_path() + if not artifact_path.exists(): + raise FileNotFoundError(f"curated module artifact not found: {artifact_path}") + + artifact = json.loads(artifact_path.read_text()) + abi = artifact["abi"] + curated_module = Contract.from_abi("ICuratedModule", get_curated_module_address(), abi) + return curated_module.META_REGISTRY() + + +def get_optional_meta_registry_address(default: str = ZERO_ADDRESS) -> str: + try: + return get_meta_registry_address() + except Exception: + return default diff --git a/utils/test/event_validators/dual_governance.py b/utils/test/event_validators/dual_governance.py index 922fb93c..e537d0be 100644 --- a/utils/test/event_validators/dual_governance.py +++ b/utils/test/event_validators/dual_governance.py @@ -4,6 +4,19 @@ from utils.config import DUAL_GOVERNANCE, TIMELOCK +def _normalize_hex_data(value: any) -> str: + if isinstance(value, (bytes, bytearray)): + return "0x" + bytes(value).hex() + + if hasattr(value, "hex"): + hex_value = value.hex() + if isinstance(hex_value, str): + return hex_value.lower() if hex_value.startswith("0x") else f"0x{hex_value.lower()}" + + value_str = str(value).lower() + return value_str if value_str.startswith("0x") else f"0x{value_str}" + + def validate_dual_governance_submit_event( event: EventDict, proposal_id: int, @@ -23,9 +36,13 @@ def validate_dual_governance_submit_event( assert len(event["ProposalSubmitted"][0]["calls"]) == len(proposal_calls), "Wrong callsCount" for i in range(0, len(proposal_calls)): - assert event["ProposalSubmitted"][0]["calls"][i][0] == proposal_calls[i]["target"], f"Wrong target {i}: {event['ProposalSubmitted'][0]['calls'][i][0]} : {proposal_calls[i]['target']}" + assert convert.to_address(event["ProposalSubmitted"][0]["calls"][i][0]) == convert.to_address( + proposal_calls[i]["target"] + ), f"Wrong target {i}: {event['ProposalSubmitted'][0]['calls'][i][0]} : {proposal_calls[i]['target']}" assert event["ProposalSubmitted"][0]["calls"][i][1] == proposal_calls[i]["value"], f"Wrong value {i}" - assert event["ProposalSubmitted"][0]["calls"][i][2] == proposal_calls[i]["data"], f'Wrong data {i}' + assert _normalize_hex_data(event["ProposalSubmitted"][0]["calls"][i][2]) == _normalize_hex_data( + proposal_calls[i]["data"] + ), f"Wrong data {i}" assert event["ProposalSubmitted"][1]["proposalId"] == proposal_id, "Wrong proposalId" assert event["ProposalSubmitted"][1]["proposerAccount"] == proposer, "Wrong proposer" From 9dddebeca4c2de2f1b6498dfe76b9f3b54606534 Mon Sep 17 00:00:00 2001 From: Eddort Date: Thu, 23 Apr 2026 22:42:45 +0200 Subject: [PATCH 04/15] feat: update upgrade vote script handling and improve error messaging --- ...grade_2026_04_14_hoodi_protocol_upgrade.py | 66 ++++++++++++++----- .../test_2026_04_14_hoodi_protocol_upgrade.py | 28 +++++--- 2 files changed, 69 insertions(+), 25 deletions(-) diff --git a/scripts/upgrade_2026_04_14_hoodi_protocol_upgrade.py b/scripts/upgrade_2026_04_14_hoodi_protocol_upgrade.py index c4c04088..550a89a8 100644 --- a/scripts/upgrade_2026_04_14_hoodi_protocol_upgrade.py +++ b/scripts/upgrade_2026_04_14_hoodi_protocol_upgrade.py @@ -15,7 +15,6 @@ from brownie import interface from utils.config import get_deployer_account, get_is_live, get_priority_fee -from utils.hoodi_upgrade import get_optional_upgrade_vote_script_address, get_upgrade_vote_script_address 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 @@ -23,7 +22,7 @@ # ============================== Addresses =================================== -UPGRADE_VOTE_SCRIPT = get_optional_upgrade_vote_script_address() +UPGRADE_VOTE_SCRIPT = "0xfaAddC93baf78e89DCf37bA67943E1bE8F37Bb8c" HOODI_DG_ONLY_ENV = "HOODI_DG_ONLY" @@ -167,8 +166,6 @@ # ================================ Main ====================================== -def _get_upgrade_vote_script(): - return interface.UpgradeVoteScript(get_upgrade_vote_script_address()) def is_dg_only_mode() -> bool: @@ -180,8 +177,15 @@ def get_ipfs_description(dg_only: Optional[bool] = None) -> str: return DG_ONLY_IPFS_DESCRIPTION if dg_only else IPFS_DESCRIPTION -def get_dg_items() -> List[Tuple[str, str]]: - omnibus = _get_upgrade_vote_script() +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 vote_script_address.lower() in ("", "0x0000000000000000000000000000000000000000"): + 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(): @@ -190,14 +194,24 @@ def get_dg_items() -> List[Tuple[str, str]]: return dg_items -def get_vote_items(dg_only: Optional[bool] = None) -> Tuple[List[str], List[Tuple[str, str]]]: +def get_vote_items( + dg_only: Optional[bool] = None, + upgrade_vote_script: Optional[str] = None, +) -> Tuple[List[str], List[Tuple[str, str]]]: dg_only = is_dg_only_mode() if dg_only is None else dg_only - omnibus = _get_upgrade_vote_script() + vote_script_address = (upgrade_vote_script or UPGRADE_VOTE_SCRIPT).strip() + if vote_script_address.lower() in ("", "0x0000000000000000000000000000000000000000"): + 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() + 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) @@ -212,9 +226,17 @@ def get_vote_items(dg_only: Optional[bool] = None) -> Tuple[List[str], List[Tupl return vote_desc_items, call_script_items -def start_vote(tx_params: Dict[str, str], silent: bool = False, dg_only: Optional[bool] = None): +def start_vote( + tx_params: Dict[str, str], + silent: bool = False, + dg_only: Optional[bool] = None, + upgrade_vote_script: Optional[str] = None, +): dg_only = is_dg_only_mode() if dg_only is None else dg_only - vote_desc_items, call_script_items = get_vote_items(dg_only=dg_only) + vote_desc_items, call_script_items = get_vote_items( + dg_only=dg_only, + upgrade_vote_script=upgrade_vote_script, + ) vote_items = bake_vote_items(list(vote_desc_items), list(call_script_items)) ipfs_description = get_ipfs_description(dg_only=dg_only) @@ -229,25 +251,37 @@ def start_vote(tx_params: Dict[str, str], silent: bool = False, dg_only: Optiona ) if not dg_only: - assert _get_upgrade_vote_script().isValidVoteScript(vote_id, DG_PROPOSAL_METADATA) + 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(): +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) + 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(): +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) + 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/test_2026_04_14_hoodi_protocol_upgrade.py b/tests/test_2026_04_14_hoodi_protocol_upgrade.py index 5ef17760..4c021fe9 100644 --- a/tests/test_2026_04_14_hoodi_protocol_upgrade.py +++ b/tests/test_2026_04_14_hoodi_protocol_upgrade.py @@ -7,9 +7,6 @@ from brownie.network.transaction import TransactionReceipt from utils.config import network_name -from utils.hoodi_upgrade import ( - get_upgrade_vote_script_address, -) from utils.test.tx_tracing_helpers import ( count_vote_items_by_events, display_dg_events, @@ -40,6 +37,7 @@ get_vote_items, get_dg_items, DG_PROPOSAL_METADATA, + UPGRADE_VOTE_SCRIPT, ) @@ -432,13 +430,17 @@ def runtime_upgrade_context(): if network_name() != "hoodi-fork": pytest.skip("Run the dedicated Hoodi upgrade test on --network hoodi-fork.") - upgrade_vote_script = get_upgrade_vote_script_address() + upgrade_vote_script = UPGRADE_VOTE_SCRIPT + if ( _is_placeholder_address(upgrade_vote_script) or _is_placeholder_text(DG_PROPOSAL_METADATA) or _is_placeholder_text(get_ipfs_description(dg_only=DG_ONLY_MODE)) ): - pytest.skip("Local Hoodi upgrade artifacts are missing. Run the lido-core deploy flow first.") + pytest.skip( + "Upgrade vote script address is missing. Set UPGRADE_VOTE_SCRIPT in " + "scripts/upgrade_2026_04_14_hoodi_protocol_upgrade.py first." + ) vote_script = interface.UpgradeVoteScript(upgrade_vote_script) upgrade_template = vote_script.TEMPLATE() @@ -553,7 +555,7 @@ def runtime_upgrade_context(): @pytest.fixture(scope="module") def dual_governance_proposal_calls(runtime_upgrade_context): - dg_items = get_dg_items() + dg_items = get_dg_items(runtime_upgrade_context["upgrade_vote_script"]) proposal_calls = [] for target, data in dg_items: @@ -581,8 +583,11 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g # consolidation_migrator = interface.ConsolidationMigrator(CONSOLIDATION_MIGRATOR) # meta_registry = interface.IMetaRegistry(META_REGISTRY) - vote_desc_items, call_script_items = get_vote_items(dg_only=DG_ONLY_MODE) - dg_items = get_dg_items() + vote_desc_items, call_script_items = get_vote_items( + dg_only=DG_ONLY_MODE, + upgrade_vote_script=ctx["upgrade_vote_script"], + ) + dg_items = get_dg_items(ctx["upgrade_vote_script"]) upgrade_template = ctx["upgrade_template"] expected_vote_events_count = EXPECTED_VOTE_EVENTS_COUNT or len(call_script_items) @@ -602,7 +607,12 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g 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, dg_only=DG_ONLY_MODE) + vote_id, _ = start_vote( + {"from": ldo_holder}, + silent=True, + dg_only=DG_ONLY_MODE, + 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() From 85ed2b21b4a9267cbee7962cf70fd8db196e0460 Mon Sep 17 00:00:00 2001 From: Eddort Date: Tue, 28 Apr 2026 15:02:12 +0200 Subject: [PATCH 05/15] wip: srv3 hoodi dg + voting --- interfaces/CSParametersRegistry.json | 2 +- interfaces/CircuitBreaker.json | 506 +++++++ interfaces/OneShotCurveSetup.json | 15 + interfaces/UpgradeConfig.json | 1184 +---------------- interfaces/UpgradeVoteScript.json | 358 +---- interfaces/ValidatorsExitBusOracle.json | 2 +- .../test_2026_04_14_hoodi_protocol_upgrade.py | 806 +++++++---- 7 files changed, 1065 insertions(+), 1808 deletions(-) create mode 100644 interfaces/CircuitBreaker.json create mode 100644 interfaces/OneShotCurveSetup.json diff --git a/interfaces/CSParametersRegistry.json b/interfaces/CSParametersRegistry.json index 8a41979f..120a2270 100644 --- a/interfaces/CSParametersRegistry.json +++ b/interfaces/CSParametersRegistry.json @@ -1 +1 @@ -[{"type":"constructor","inputs":[{"name":"queueLowestPriority","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"DEFAULT_ADMIN_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"QUEUE_LEGACY_PRIORITY","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"QUEUE_LOWEST_PRIORITY","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"defaultAllowedExitDelay","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"defaultBadPerformancePenalty","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"defaultElRewardsStealingAdditionalFine","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"defaultExitDelayPenalty","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"defaultKeyRemovalCharge","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"defaultKeysLimit","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"defaultMaxWithdrawalRequestFee","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"defaultPerformanceCoefficients","inputs":[],"outputs":[{"name":"attestationsWeight","type":"uint32","internalType":"uint32"},{"name":"blocksWeight","type":"uint32","internalType":"uint32"},{"name":"syncWeight","type":"uint32","internalType":"uint32"}],"stateMutability":"view"},{"type":"function","name":"defaultPerformanceLeeway","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"defaultQueueConfig","inputs":[],"outputs":[{"name":"priority","type":"uint32","internalType":"uint32"},{"name":"maxDeposits","type":"uint32","internalType":"uint32"}],"stateMutability":"view"},{"type":"function","name":"defaultRewardShare","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"defaultStrikesParams","inputs":[],"outputs":[{"name":"lifetime","type":"uint32","internalType":"uint32"},{"name":"threshold","type":"uint32","internalType":"uint32"}],"stateMutability":"view"},{"type":"function","name":"getAllowedExitDelay","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"delay","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getBadPerformancePenalty","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"penalty","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getElRewardsStealingAdditionalFine","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"fine","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getExitDelayPenalty","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"penalty","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getInitializedVersion","inputs":[],"outputs":[{"name":"","type":"uint64","internalType":"uint64"}],"stateMutability":"view"},{"type":"function","name":"getKeyRemovalCharge","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"keyRemovalCharge","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getKeysLimit","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"limit","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getMaxWithdrawalRequestFee","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"fee","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getPerformanceCoefficients","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"attestationsWeight","type":"uint256","internalType":"uint256"},{"name":"blocksWeight","type":"uint256","internalType":"uint256"},{"name":"syncWeight","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getPerformanceLeewayData","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"data","type":"tuple[]","internalType":"struct ICSParametersRegistry.KeyNumberValueInterval[]","components":[{"name":"minKeyNumber","type":"uint256","internalType":"uint256"},{"name":"value","type":"uint256","internalType":"uint256"}]}],"stateMutability":"view"},{"type":"function","name":"getQueueConfig","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"queuePriority","type":"uint32","internalType":"uint32"},{"name":"maxDeposits","type":"uint32","internalType":"uint32"}],"stateMutability":"view"},{"type":"function","name":"getRewardShareData","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"data","type":"tuple[]","internalType":"struct ICSParametersRegistry.KeyNumberValueInterval[]","components":[{"name":"minKeyNumber","type":"uint256","internalType":"uint256"},{"name":"value","type":"uint256","internalType":"uint256"}]}],"stateMutability":"view"},{"type":"function","name":"getRoleAdmin","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"getRoleMember","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"index","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"getRoleMemberCount","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getStrikesParams","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"lifetime","type":"uint256","internalType":"uint256"},{"name":"threshold","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"grantRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"hasRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"initialize","inputs":[{"name":"admin","type":"address","internalType":"address"},{"name":"data","type":"tuple","internalType":"struct ICSParametersRegistry.InitializationData","components":[{"name":"keyRemovalCharge","type":"uint256","internalType":"uint256"},{"name":"elRewardsStealingAdditionalFine","type":"uint256","internalType":"uint256"},{"name":"keysLimit","type":"uint256","internalType":"uint256"},{"name":"rewardShare","type":"uint256","internalType":"uint256"},{"name":"performanceLeeway","type":"uint256","internalType":"uint256"},{"name":"strikesLifetime","type":"uint256","internalType":"uint256"},{"name":"strikesThreshold","type":"uint256","internalType":"uint256"},{"name":"defaultQueuePriority","type":"uint256","internalType":"uint256"},{"name":"defaultQueueMaxDeposits","type":"uint256","internalType":"uint256"},{"name":"badPerformancePenalty","type":"uint256","internalType":"uint256"},{"name":"attestationsWeight","type":"uint256","internalType":"uint256"},{"name":"blocksWeight","type":"uint256","internalType":"uint256"},{"name":"syncWeight","type":"uint256","internalType":"uint256"},{"name":"defaultAllowedExitDelay","type":"uint256","internalType":"uint256"},{"name":"defaultExitDelayPenalty","type":"uint256","internalType":"uint256"},{"name":"defaultMaxWithdrawalRequestFee","type":"uint256","internalType":"uint256"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"renounceRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"callerConfirmation","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"revokeRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setAllowedExitDelay","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"},{"name":"delay","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setBadPerformancePenalty","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"},{"name":"penalty","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setDefaultAllowedExitDelay","inputs":[{"name":"delay","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setDefaultBadPerformancePenalty","inputs":[{"name":"penalty","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setDefaultElRewardsStealingAdditionalFine","inputs":[{"name":"fine","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setDefaultExitDelayPenalty","inputs":[{"name":"penalty","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setDefaultKeyRemovalCharge","inputs":[{"name":"keyRemovalCharge","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setDefaultKeysLimit","inputs":[{"name":"limit","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setDefaultMaxWithdrawalRequestFee","inputs":[{"name":"fee","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setDefaultPerformanceCoefficients","inputs":[{"name":"attestationsWeight","type":"uint256","internalType":"uint256"},{"name":"blocksWeight","type":"uint256","internalType":"uint256"},{"name":"syncWeight","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setDefaultPerformanceLeeway","inputs":[{"name":"leeway","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setDefaultQueueConfig","inputs":[{"name":"priority","type":"uint256","internalType":"uint256"},{"name":"maxDeposits","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setDefaultRewardShare","inputs":[{"name":"share","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setDefaultStrikesParams","inputs":[{"name":"lifetime","type":"uint256","internalType":"uint256"},{"name":"threshold","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setElRewardsStealingAdditionalFine","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"},{"name":"fine","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setExitDelayPenalty","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"},{"name":"penalty","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setKeyRemovalCharge","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"},{"name":"keyRemovalCharge","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setKeysLimit","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"},{"name":"limit","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setMaxWithdrawalRequestFee","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"},{"name":"fee","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setPerformanceCoefficients","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"},{"name":"attestationsWeight","type":"uint256","internalType":"uint256"},{"name":"blocksWeight","type":"uint256","internalType":"uint256"},{"name":"syncWeight","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setPerformanceLeewayData","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"},{"name":"data","type":"tuple[]","internalType":"struct ICSParametersRegistry.KeyNumberValueInterval[]","components":[{"name":"minKeyNumber","type":"uint256","internalType":"uint256"},{"name":"value","type":"uint256","internalType":"uint256"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setQueueConfig","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"},{"name":"priority","type":"uint256","internalType":"uint256"},{"name":"maxDeposits","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setRewardShareData","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"},{"name":"data","type":"tuple[]","internalType":"struct ICSParametersRegistry.KeyNumberValueInterval[]","components":[{"name":"minKeyNumber","type":"uint256","internalType":"uint256"},{"name":"value","type":"uint256","internalType":"uint256"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setStrikesParams","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"},{"name":"lifetime","type":"uint256","internalType":"uint256"},{"name":"threshold","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"supportsInterface","inputs":[{"name":"interfaceId","type":"bytes4","internalType":"bytes4"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"unsetAllowedExitDelay","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"unsetBadPerformancePenalty","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"unsetElRewardsStealingAdditionalFine","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"unsetExitDelayPenalty","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"unsetKeyRemovalCharge","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"unsetKeysLimit","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"unsetMaxWithdrawalRequestFee","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"unsetPerformanceCoefficients","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"unsetPerformanceLeewayData","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"unsetQueueConfig","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"unsetRewardShareData","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"unsetStrikesParams","inputs":[{"name":"curveId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"event","name":"AllowedExitDelaySet","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"delay","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"AllowedExitDelayUnset","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"BadPerformancePenaltySet","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"penalty","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"BadPerformancePenaltyUnset","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"DefaultAllowedExitDelaySet","inputs":[{"name":"delay","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"DefaultBadPerformancePenaltySet","inputs":[{"name":"value","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"DefaultElRewardsStealingAdditionalFineSet","inputs":[{"name":"value","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"DefaultExitDelayPenaltySet","inputs":[{"name":"penalty","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"DefaultKeyRemovalChargeSet","inputs":[{"name":"value","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"DefaultKeysLimitSet","inputs":[{"name":"value","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"DefaultMaxWithdrawalRequestFeeSet","inputs":[{"name":"fee","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"DefaultPerformanceCoefficientsSet","inputs":[{"name":"attestationsWeight","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"blocksWeight","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"syncWeight","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"DefaultPerformanceLeewaySet","inputs":[{"name":"value","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"DefaultQueueConfigSet","inputs":[{"name":"priority","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"maxDeposits","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"DefaultRewardShareSet","inputs":[{"name":"value","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"DefaultStrikesParamsSet","inputs":[{"name":"lifetime","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"threshold","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ElRewardsStealingAdditionalFineSet","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"fine","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ElRewardsStealingAdditionalFineUnset","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ExitDelayPenaltySet","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"penalty","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ExitDelayPenaltyUnset","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"Initialized","inputs":[{"name":"version","type":"uint64","indexed":false,"internalType":"uint64"}],"anonymous":false},{"type":"event","name":"KeyRemovalChargeSet","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"keyRemovalCharge","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"KeyRemovalChargeUnset","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"KeysLimitSet","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"limit","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"KeysLimitUnset","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"MaxWithdrawalRequestFeeSet","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"fee","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"MaxWithdrawalRequestFeeUnset","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"PerformanceCoefficientsSet","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"attestationsWeight","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"blocksWeight","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"syncWeight","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"PerformanceCoefficientsUnset","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"PerformanceLeewayDataSet","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"data","type":"tuple[]","indexed":false,"internalType":"struct ICSParametersRegistry.KeyNumberValueInterval[]","components":[{"name":"minKeyNumber","type":"uint256","internalType":"uint256"},{"name":"value","type":"uint256","internalType":"uint256"}]}],"anonymous":false},{"type":"event","name":"PerformanceLeewayDataUnset","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"QueueConfigSet","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"priority","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"maxDeposits","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"QueueConfigUnset","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"RewardShareDataSet","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"data","type":"tuple[]","indexed":false,"internalType":"struct ICSParametersRegistry.KeyNumberValueInterval[]","components":[{"name":"minKeyNumber","type":"uint256","internalType":"uint256"},{"name":"value","type":"uint256","internalType":"uint256"}]}],"anonymous":false},{"type":"event","name":"RewardShareDataUnset","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"RoleAdminChanged","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"previousAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"newAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"}],"anonymous":false},{"type":"event","name":"RoleGranted","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"RoleRevoked","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"StrikesParamsSet","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"lifetime","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"threshold","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"StrikesParamsUnset","inputs":[{"name":"curveId","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"type":"error","name":"AccessControlBadConfirmation","inputs":[]},{"type":"error","name":"AccessControlUnauthorizedAccount","inputs":[{"name":"account","type":"address","internalType":"address"},{"name":"neededRole","type":"bytes32","internalType":"bytes32"}]},{"type":"error","name":"InvalidAllowedExitDelay","inputs":[]},{"type":"error","name":"InvalidInitialization","inputs":[]},{"type":"error","name":"InvalidKeyNumberValueIntervals","inputs":[]},{"type":"error","name":"InvalidPerformanceCoefficients","inputs":[]},{"type":"error","name":"InvalidPerformanceLeewayData","inputs":[]},{"type":"error","name":"InvalidRewardShareData","inputs":[]},{"type":"error","name":"InvalidStrikesParams","inputs":[]},{"type":"error","name":"NotInitializing","inputs":[]},{"type":"error","name":"QueueCannotBeUsed","inputs":[]},{"type":"error","name":"SafeCastOverflowedUintDowncast","inputs":[{"name":"bits","type":"uint8","internalType":"uint8"},{"name":"value","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"ZeroAdminAddress","inputs":[]},{"type":"error","name":"ZeroMaxDeposits","inputs":[]},{"type":"error","name":"ZeroQueueLowestPriority","inputs":[]}] +[{"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":"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 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":"penalty","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":"penalty","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":[]}] diff --git a/interfaces/CircuitBreaker.json b/interfaces/CircuitBreaker.json new file mode 100644 index 00000000..b05cf2e9 --- /dev/null +++ b/interfaces/CircuitBreaker.json @@ -0,0 +1,506 @@ +[ + { + "type": "constructor", + "inputs": [ + { + "name": "_admin", + "type": "address", + "internalType": "address" + }, + { + "name": "_minPauseDuration", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "_maxPauseDuration", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "_minHeartbeatInterval", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "_maxHeartbeatInterval", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "_initialPauseDuration", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "_initialHeartbeatInterval", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "ADMIN", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "MAX_HEARTBEAT_INTERVAL", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "MAX_PAUSE_DURATION", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "MIN_HEARTBEAT_INTERVAL", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "MIN_PAUSE_DURATION", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getPausableCount", + "inputs": [ + { + "name": "_pauser", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getPausables", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address[]", + "internalType": "address[]" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getPauser", + "inputs": [ + { + "name": "_pausable", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "heartbeat", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "heartbeatExpiry", + "inputs": [ + { + "name": "pauser", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "timestamp", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "heartbeatInterval", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "isPauserLive", + "inputs": [ + { + "name": "_pauser", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "pause", + "inputs": [ + { + "name": "_pausable", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "pauseDuration", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "registerPauser", + "inputs": [ + { + "name": "_pausable", + "type": "address", + "internalType": "address" + }, + { + "name": "_newPauser", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setHeartbeatInterval", + "inputs": [ + { + "name": "_newHeartbeatInterval", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setPauseDuration", + "inputs": [ + { + "name": "_newPauseDuration", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "event", + "name": "CircuitBreakerInitialized", + "inputs": [ + { + "name": "admin", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "minPauseDuration", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "maxPauseDuration", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "minHeartbeatInterval", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "maxHeartbeatInterval", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "HeartbeatIntervalUpdated", + "inputs": [ + { + "name": "previousHeartbeatInterval", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "newHeartbeatInterval", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "HeartbeatUpdated", + "inputs": [ + { + "name": "pauser", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "newHeartbeatExpiry", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "PauseDurationUpdated", + "inputs": [ + { + "name": "previousPauseDuration", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "newPauseDuration", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "PauseTriggered", + "inputs": [ + { + "name": "pausable", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "pauser", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "pauseDuration", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "PauserSet", + "inputs": [ + { + "name": "pausable", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "previousPauser", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "newPauser", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "error", + "name": "AdminZero", + "inputs": [] + }, + { + "type": "error", + "name": "HeartbeatExpired", + "inputs": [] + }, + { + "type": "error", + "name": "HeartbeatIntervalAboveMax", + "inputs": [] + }, + { + "type": "error", + "name": "HeartbeatIntervalBelowMin", + "inputs": [] + }, + { + "type": "error", + "name": "MinHeartbeatIntervalExceedsMax", + "inputs": [] + }, + { + "type": "error", + "name": "MinHeartbeatIntervalZero", + "inputs": [] + }, + { + "type": "error", + "name": "MinPauseDurationExceedsMax", + "inputs": [] + }, + { + "type": "error", + "name": "MinPauseDurationZero", + "inputs": [] + }, + { + "type": "error", + "name": "PausableZero", + "inputs": [] + }, + { + "type": "error", + "name": "PauseDurationAboveMax", + "inputs": [] + }, + { + "type": "error", + "name": "PauseDurationBelowMin", + "inputs": [] + }, + { + "type": "error", + "name": "PauseFailed", + "inputs": [] + }, + { + "type": "error", + "name": "ReentrantCall", + "inputs": [] + }, + { + "type": "error", + "name": "SenderNotAdmin", + "inputs": [] + }, + { + "type": "error", + "name": "SenderNotPauser", + "inputs": [] + } +] diff --git a/interfaces/OneShotCurveSetup.json b/interfaces/OneShotCurveSetup.json new file mode 100644 index 00000000..06caa769 --- /dev/null +++ b/interfaces/OneShotCurveSetup.json @@ -0,0 +1,15 @@ +[ + { + "type": "event", + "name": "BondCurveDeployed", + "inputs": [ + { + "name": "curveId", + "type": "uint256", + "indexed": true, + "internalType": "uint256" + } + ], + "anonymous": false + } +] diff --git a/interfaces/UpgradeConfig.json b/interfaces/UpgradeConfig.json index 5268dc77..026aa553 100644 --- a/interfaces/UpgradeConfig.json +++ b/interfaces/UpgradeConfig.json @@ -1,1183 +1 @@ -[ - { - "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": "resealManager", - "type": "address" - }, - { - "internalType": "address", - "name": "circuitBreaker", - "type": "address" - }, - { - "internalType": "address", - "name": "easyTrack", - "type": "address" - }, - { - "components": [ - { - "internalType": "address", - "name": "UpdateStakingModuleShareLimits", - "type": "address" - }, - { - "internalType": "address", - "name": "AllowConsolidationPair", - "type": "address" - }, - { - "internalType": "address", - "name": "AllowedMerkleGatesRegistryForCSM", - "type": "address" - }, - { - "internalType": "address", - "name": "SetMerkleGateTreeForCSM", - "type": "address" - }, - { - "internalType": "address", - "name": "ReportWithdrawalsForSlashedValidatorsForCSM", - "type": "address" - }, - { - "internalType": "address", - "name": "SettleGeneralDelayedPenaltyForCSM", - "type": "address" - }, - { - "internalType": "address", - "name": "AllowedMerkleGatesRegistryForCM", - "type": "address" - }, - { - "internalType": "address", - "name": "SetMerkleGateTreeForCM", - "type": "address" - }, - { - "internalType": "address", - "name": "ReportWithdrawalsForSlashedValidatorsForCM", - "type": "address" - }, - { - "internalType": "address", - "name": "SettleGeneralDelayedPenaltyForCM", - "type": "address" - }, - { - "internalType": "address", - "name": "CreateOrUpdateOperatorGroup", - "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": "oldLocatorImpl", - "type": "address" - }, - { - "internalType": "address", - "name": "oldLidoImpl", - "type": "address" - }, - { - "internalType": "address", - "name": "oldAccountingImpl", - "type": "address" - }, - { - "internalType": "address", - "name": "oldAccountingOracleImpl", - "type": "address" - }, - { - "internalType": "address", - "name": "oldStakingRouterImpl", - "type": "address" - }, - { - "internalType": "address", - "name": "oldWithdrawalVaultImpl", - "type": "address" - }, - { - "internalType": "address", - "name": "oldValidatorsExitBusOracleImpl", - "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": "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": "address", - "name": "topUpGateway", - "type": "address" - }, - { - "internalType": "uint256", - "name": "lidoDepositsReserveTarget", - "type": "uint256" - }, - { - "internalType": "address", - "name": "curatedModuleCommittee", - "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": "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": "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": "permissionlessGate", - "type": "address" - }, - { - "internalType": "address", - "name": "verifier", - "type": "address" - }, - { - "internalType": "address", - "name": "verifierV3", - "type": "address" - }, - { - "internalType": "address", - "name": "ejector", - "type": "address" - }, - { - "internalType": "address", - "name": "identifiedCommunityStakersGateManager", - "type": "address" - }, - { - "internalType": "address", - "name": "gateSeal", - "type": "address" - }, - { - "internalType": "address", - "name": "generalDelayedPenaltyReporter", - "type": "address" - }, - { - "internalType": "address", - "name": "penaltiesManager", - "type": "address" - } - ], - "internalType": "struct CSMUpgradeParams", - "name": "csmUpgrade", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "address", - "name": "module", - "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": "hashConsensusInitialEpoch", - "type": "uint256" - } - ], - "internalType": "struct CuratedModuleParams", - "name": "curatedModule", - "type": "tuple" - } - ], - "internalType": "struct UpgradeParameters", - "name": "params", - "type": "tuple" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "NewAndOldLocatorImplementationsMustBeDifferent", - "type": "error" - }, - { - "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": "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": "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": "verifier", - "type": "address" - }, - { - "internalType": "address", - "name": "verifierV3", - "type": "address" - }, - { - "internalType": "address", - "name": "permissionlessGate", - "type": "address" - }, - { - "internalType": "address", - "name": "ejector", - "type": "address" - }, - { - "internalType": "address", - "name": "identifiedCommunityStakersGateManager", - "type": "address" - }, - { - "internalType": "address", - "name": "gateSeal", - "type": "address" - }, - { - "internalType": "address", - "name": "generalDelayedPenaltyReporter", - "type": "address" - }, - { - "internalType": "address", - "name": "penaltiesManager", - "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": "oldLocatorImpl", - "type": "address" - }, - { - "internalType": "address", - "name": "oldLidoImpl", - "type": "address" - }, - { - "internalType": "address", - "name": "oldAccountingImpl", - "type": "address" - }, - { - "internalType": "address", - "name": "oldAccountingOracleImpl", - "type": "address" - }, - { - "internalType": "address", - "name": "oldStakingRouterImpl", - "type": "address" - }, - { - "internalType": "address", - "name": "oldWithdrawalVaultImpl", - "type": "address" - }, - { - "internalType": "address", - "name": "oldValidatorsExitBusOracleImpl", - "type": "address" - }, - { - "internalType": "address", - "name": "oldOracleReportSanityChecker", - "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": "curatedModuleCommittee", - "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": "struct CoreUpgradeConfig", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getCuratedModuleConfig", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "module", - "type": "address" - }, - { - "internalType": "address", - "name": "accounting", - "type": "address" - }, - { - "internalType": "address", - "name": "ejector", - "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": "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": "AllowedMerkleGatesRegistryForCSM", - "type": "address" - }, - { - "internalType": "address", - "name": "SetMerkleGateTreeForCSM", - "type": "address" - }, - { - "internalType": "address", - "name": "ReportWithdrawalsForSlashedValidatorsForCSM", - "type": "address" - }, - { - "internalType": "address", - "name": "SettleGeneralDelayedPenaltyForCSM", - "type": "address" - }, - { - "internalType": "address", - "name": "AllowedMerkleGatesRegistryForCM", - "type": "address" - }, - { - "internalType": "address", - "name": "SetMerkleGateTreeForCM", - "type": "address" - }, - { - "internalType": "address", - "name": "ReportWithdrawalsForSlashedValidatorsForCM", - "type": "address" - }, - { - "internalType": "address", - "name": "SettleGeneralDelayedPenaltyForCM", - "type": "address" - }, - { - "internalType": "address", - "name": "CreateOrUpdateOperatorGroup", - "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": "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" - } -] +[{"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":"resealManager","type":"address"},{"internalType":"address","name":"circuitBreaker","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":"oldLocatorImpl","type":"address"},{"internalType":"address","name":"oldLidoImpl","type":"address"},{"internalType":"address","name":"oldAccountingImpl","type":"address"},{"internalType":"address","name":"oldAccountingOracleImpl","type":"address"},{"internalType":"address","name":"oldStakingRouterImpl","type":"address"},{"internalType":"address","name":"oldWithdrawalVaultImpl","type":"address"},{"internalType":"address","name":"oldValidatorsExitBusOracleImpl","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":"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":"address","name":"topUpGateway","type":"address"},{"internalType":"uint256","name":"lidoDepositsReserveTarget","type":"uint256"},{"internalType":"address","name":"curatedModuleCommittee","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":"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":"ejector","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":"NewAndOldLocatorImplementationsMustBeDifferent","type":"error"},{"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":"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":"identifiedDVTClusterGate","type":"address"},{"internalType":"address","name":"identifiedDVTClusterCurveSetup","type":"address"},{"internalType":"uint256","name":"identifiedDVTClusterBondCurveId","type":"uint256"},{"internalType":"address","name":"vettedGateImpl","type":"address"},{"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":"oldVerifier","type":"address"},{"internalType":"address","name":"newVerifier","type":"address"},{"internalType":"address","name":"newPermissionlessGate","type":"address"},{"internalType":"address","name":"oldEjector","type":"address"},{"internalType":"address","name":"ejector","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":"oldLocatorImpl","type":"address"},{"internalType":"address","name":"oldLidoImpl","type":"address"},{"internalType":"address","name":"oldAccountingImpl","type":"address"},{"internalType":"address","name":"oldAccountingOracleImpl","type":"address"},{"internalType":"address","name":"oldStakingRouterImpl","type":"address"},{"internalType":"address","name":"oldWithdrawalVaultImpl","type":"address"},{"internalType":"address","name":"oldValidatorsExitBusOracleImpl","type":"address"},{"internalType":"address","name":"oldOracleReportSanityChecker","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":"curatedModuleCommittee","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":"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":"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/UpgradeVoteScript.json b/interfaces/UpgradeVoteScript.json index d4e3acd1..b2d293e7 100644 --- a/interfaces/UpgradeVoteScript.json +++ b/interfaces/UpgradeVoteScript.json @@ -1,357 +1 @@ -[ - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "upgradeTemplate", - "type": "address" - }, - { - "internalType": "address", - "name": "timeConstraints", - "type": "address" - }, - { - "internalType": "uint32", - "name": "enabledDaySpanStart", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "enabledDaySpanEnd", - "type": "uint32" - } - ], - "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": "ENABLED_DAY_SPAN_END", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "ENABLED_DAY_SPAN_START", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "TEMPLATE", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "TIME_CONSTRAINTS", - "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": "getVoteItemsPacked", - "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" - } -] +[{"inputs":[{"components":[{"internalType":"address","name":"upgradeTemplate","type":"address"},{"internalType":"address","name":"timeConstraints","type":"address"},{"internalType":"uint32","name":"enabledDaySpanStart","type":"uint32"},{"internalType":"uint32","name":"enabledDaySpanEnd","type":"uint32"}],"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":"InvalidMerkleGateAddress","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":"ENABLED_DAY_SPAN_END","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ENABLED_DAY_SPAN_START","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TEMPLATE","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TIME_CONSTRAINTS","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/ValidatorsExitBusOracle.json b/interfaces/ValidatorsExitBusOracle.json index ba352a4f..2fc38211 100644 --- a/interfaces/ValidatorsExitBusOracle.json +++ b/interfaces/ValidatorsExitBusOracle.json @@ -1 +1 @@ -[{"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"}] diff --git a/tests/test_2026_04_14_hoodi_protocol_upgrade.py b/tests/test_2026_04_14_hoodi_protocol_upgrade.py index 4c021fe9..92934b82 100644 --- a/tests/test_2026_04_14_hoodi_protocol_upgrade.py +++ b/tests/test_2026_04_14_hoodi_protocol_upgrade.py @@ -8,6 +8,7 @@ from utils.config import network_name from utils.test.tx_tracing_helpers import ( + add_event_emitter, count_vote_items_by_events, display_dg_events, display_voting_events, @@ -17,13 +18,13 @@ from utils.tx_tracing import tx_events_from_receipt from utils.evm_script import encode_call_script from utils.dual_governance import PROPOSAL_STATUS -from utils.test.event_validators.aragon import ( - validate_aragon_grant_permission_event, - validate_aragon_revoke_permission_event, - validate_aragon_set_app_event, -) 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 @@ -44,6 +45,11 @@ # ============================================================================ # ============================== Constants =================================== # ============================================================================ +def _selector(signature: str) -> str: + return web3.keccak(text=signature).hex()[:10] + + +ZERO_ADDRESS = "0x0000000000000000000000000000000000000000" EMERGENCY_PROTECTED_TIMELOCK = "0x0A5E22782C0Bd4AddF10D771f0bF0406B038282d" HOODI_LEGACY_STAKING_MODULE_MANAGER = "0xE28f573b732632fdE03BD5507A7d475383e8512E" DEFAULT_ADMIN_ROLE = "0x0000000000000000000000000000000000000000000000000000000000000000" @@ -65,6 +71,9 @@ 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() RESUME_ROLE = web3.keccak(text="RESUME_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() @@ -72,9 +81,17 @@ 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() ADD_FULL_WITHDRAWAL_REQUEST_ROLE = web3.keccak(text="ADD_FULL_WITHDRAWAL_REQUEST_ROLE").hex() -EXIT_BALANCE_LIMIT_SET_TOPIC = web3.keccak(text="ExitBalanceLimitSet(uint256,uint256,uint256)").hex() -CIRCUIT_BREAKER_PAUSER_SET_TOPIC = web3.keccak(text="PauserSet(address,address,address)").hex() -CIRCUIT_BREAKER_HEARTBEAT_UPDATED_TOPIC = web3.keccak(text="HeartbeatUpdated(address,uint256)").hex() +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_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_SELECTOR = _selector( + "createOrUpdateOperatorGroup(uint256,((uint64,uint16)[],(bytes)[]))" +) AO_CONTRACT_VERSION = 5 AO_CONSENSUS_VERSION = 6 AO_PREV_CONSENSUS_VERSION = 5 @@ -93,15 +110,14 @@ CURATED_MODULE_ID = 5 CURATED_INITIAL_EPOCH = 47480 CURATED_EPOCHS_PER_FRAME = 1575 -# TODO: restore Easy Track checks when full ET flow is enabled again. -# EASYTRACK = "0x284D91a7D47850d21A6DEaaC6E538AC7E5E6fc2a" -# STAKING_ROUTER = "0xCc820558B39ee15C7C45B59390B503b83fb499A8" -# UPDATE_STAKING_MODULE_SHARE_LIMITS_FACTORY = "0x0000000000000000000000000000000000000000" -# ALLOW_CONSOLIDATION_PAIR_FACTORY = "0x0000000000000000000000000000000000000000" -# CREATE_OR_UPDATE_OPERATOR_GROUP_FACTORY = "0x0000000000000000000000000000000000000000" -# CONSOLIDATION_MIGRATOR = "0x0000000000000000000000000000000000000000" -# META_REGISTRY = "0x0000000000000000000000000000000000000000" - +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 # ============================================================================ # ============================= Test params ================================== @@ -109,10 +125,10 @@ EXPECTED_VOTE_ID = None EXPECTED_DG_PROPOSAL_ID = None EXPECTED_VOTE_EVENTS_COUNT = None -EXPECTED_DG_EVENTS_FROM_AGENT = 60 -EXPECTED_DG_EVENTS_COUNT = 60 +EXPECTED_DG_EVENTS_FROM_AGENT = 65 +EXPECTED_DG_EVENTS_COUNT = 65 IPFS_DESCRIPTION_HASH = None -DG_ONLY_MODE = True +DG_ONLY_MODE = False class StakingModuleItem(NamedTuple): @@ -162,28 +178,17 @@ def _assert_emitted_by(event_item, emitted_by: str) -> None: ), f"Wrong event emitter: expected {emitted_by}, got {event_item['_emitted_by']}" -def _address_to_topic(address: str) -> str: - return "0x" + "0" * 24 + address.lower().replace("0x", "") - - -def _raw_event_values(raw_event: dict) -> dict: - return {item["name"]: item["value"] for item in raw_event["data"]} +def _permission(contract_address: str, selector: str) -> str: + return convert.to_address(contract_address).lower() + selector.lower().replace("0x", "") -def _decode_uint256_words(data_hex) -> list[int]: - normalized = _normalize_hex_data(data_hex) - return [int(normalized[i : i + 64], 16) for i in range(0, len(normalized), 64) if normalized[i : i + 64]] +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 _normalize_hex_data(data_hex) -> str: - if isinstance(data_hex, bytes): - normalized = data_hex.hex() - elif hasattr(data_hex, "hex") and callable(data_hex.hex): - normalized = data_hex.hex() - else: - normalized = str(data_hex) - - return normalized.replace("0x", "") +def _raw_event_values(raw_event: dict) -> dict: + return {item["name"]: item["value"] for item in raw_event["data"]} def _group_raw_dg_events_from_receipt( @@ -215,13 +220,69 @@ def _group_raw_dg_events_from_receipt( return groups +def _group_agent_dg_events_from_receipt(receipt: TransactionReceipt, timelock: str, agent: str) -> list[EventDict]: + 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] + + +def _group_raw_agent_dg_events_from_receipt(receipt: TransactionReceipt, timelock: str, agent: str) -> list[list[dict]]: + events = tx_events_from_receipt(receipt) + + assert len(events) >= 1, "Unexpected raw DG events count" + assert ( + convert.to_address(events[-1]["address"]) == convert.to_address(timelock) + and events[-1]["name"] == "ProposalExecuted" + ), "Unexpected raw DG 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 raw DG events chain" + current_group.append(event) + + return groups + + 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", "ScriptResult", "Executed"] + _events_chain = events_chain or ["LogScriptCall", "Upgraded"] validate_events_chain([e.name for e in event], _events_chain) assert event.count("LogScriptCall") == 1 @@ -240,7 +301,7 @@ def validate_contract_version_set_event( emitted_by: Optional[str] = None, events_chain: Optional[list[str]] = None, ) -> None: - _events_chain = events_chain or ["LogScriptCall", "ContractVersionSet", "ScriptResult", "Executed"] + _events_chain = events_chain or ["LogScriptCall", "ContractVersionSet"] validate_events_chain([e.name for e in event], _events_chain) assert event.count("ContractVersionSet") == 1 @@ -258,7 +319,7 @@ def validate_consensus_version_set_event( emitted_by: Optional[str] = None, events_chain: Optional[list[str]] = None, ) -> None: - _events_chain = events_chain or ["LogScriptCall", "ConsensusVersionSet", "ScriptResult", "Executed"] + _events_chain = events_chain or ["LogScriptCall", "ConsensusVersionSet"] validate_events_chain([e.name for e in event], _events_chain) assert event.count("ConsensusVersionSet") == 1 @@ -277,7 +338,7 @@ def validate_role_grant_event( sender: str, emitted_by: Optional[str] = None, ) -> None: - validate_events_chain([e.name for e in event], ["LogScriptCall", "RoleGranted", "ScriptResult", "Executed"]) + validate_events_chain([e.name for e in event], ["LogScriptCall", "RoleGranted"]) assert event.count("RoleGranted") == 1 role_granted_event = _single_event(event, "RoleGranted") @@ -296,7 +357,7 @@ def validate_role_revoke_event( sender: str, emitted_by: Optional[str] = None, ) -> None: - validate_events_chain([e.name for e in event], ["LogScriptCall", "RoleRevoked", "ScriptResult", "Executed"]) + validate_events_chain([e.name for e in event], ["LogScriptCall", "RoleRevoked"]) assert event.count("RoleRevoked") == 1 role_revoked_event = _single_event(event, "RoleRevoked") @@ -307,12 +368,6 @@ def validate_role_revoke_event( if emitted_by is not None: _assert_emitted_by(role_revoked_event, emitted_by) -def validate_dg_noop_event(event: EventDict) -> None: - validate_events_chain([e.name for e in event], ["LogScriptCall", "ScriptResult", "Executed"]) - assert event.count("LogScriptCall") == 1 - assert event.count("ScriptResult") == 1 - assert event.count("Executed") == 1 - def validate_module_add(event: EventDict, module: StakingModuleItem, emitted_by: str, sender: str) -> None: validate_events_chain( [e.name for e in event], @@ -324,8 +379,6 @@ def validate_module_add(event: EventDict, module: StakingModuleItem, emitted_by: "StakingModuleMaxDepositsPerBlockSet", "StakingModuleMinDepositBlockDistanceSet", "StakingRouterETHDeposited", - "ScriptResult", - "Executed", ], ) @@ -368,61 +421,27 @@ def validate_module_add(event: EventDict, module: StakingModuleItem, emitted_by: _assert_emitted_by(deposited_event, emitted_by) -def validate_exit_balance_limit_set_raw_group(raw_group: list[dict], validators_exit_bus_oracle: str) -> None: - validate_events_chain( - [event["name"] for event in raw_group], - [ - "LogScriptCall", - "Upgraded", - "ContractVersionSet", - "ConsensusVersionSet", - "SetMaxValidatorsPerReport", - "(unknown)", - "ScriptResult", - "Executed", - ], - ) - - unknown_event = raw_group[5] - unknown_event_values = _raw_event_values(unknown_event) - assert convert.to_address(unknown_event["address"]) == convert.to_address(validators_exit_bus_oracle) - assert unknown_event_values["topic1"] == EXIT_BALANCE_LIMIT_SET_TOPIC - - decoded_words = _decode_uint256_words(unknown_event_values["data"]) - assert decoded_words == [ - VALIDATORS_EXIT_BUS_MAX_EXIT_BALANCE_ETH, - VALIDATORS_EXIT_BUS_BALANCE_PER_FRAME_ETH, - VALIDATORS_EXIT_BUS_FRAME_DURATION_IN_SEC, - ] - - -def validate_circuit_breaker_registration_raw_group( - raw_group: list[dict], +def validate_circuit_breaker_registration_event( + event: EventDict, circuit_breaker: str, - consolidation_gateway: str, - curated_module_committee: str, + pausable: str, + pauser: str, ) -> None: validate_events_chain( - [event["name"] for event in raw_group], - ["LogScriptCall", "(unknown)", "(unknown)", "ScriptResult", "Executed"], + [e.name for e in event], + ["LogScriptCall", "PauserSet", "HeartbeatUpdated"], ) - first_unknown_event = raw_group[1] - second_unknown_event = raw_group[2] - - assert convert.to_address(first_unknown_event["address"]) == convert.to_address(circuit_breaker) - first_unknown_event_values = _raw_event_values(first_unknown_event) - assert first_unknown_event_values["topic1"] == CIRCUIT_BREAKER_PAUSER_SET_TOPIC - assert first_unknown_event_values["topic2"] == _address_to_topic(consolidation_gateway) - assert first_unknown_event_values["topic3"] == _address_to_topic("0x0000000000000000000000000000000000000000") - assert first_unknown_event_values["topic4"] == _address_to_topic(curated_module_committee) - assert _normalize_hex_data(first_unknown_event_values["data"]) == "00" + 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) - assert convert.to_address(second_unknown_event["address"]) == convert.to_address(circuit_breaker) - second_unknown_event_values = _raw_event_values(second_unknown_event) - assert second_unknown_event_values["topic1"] == CIRCUIT_BREAKER_HEARTBEAT_UPDATED_TOPIC - assert second_unknown_event_values["topic2"] == _address_to_topic(curated_module_committee) - assert int(_normalize_hex_data(second_unknown_event_values["data"]), 16) > 0 + 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) @pytest.fixture(scope="module") @@ -451,7 +470,13 @@ def runtime_upgrade_context(): core_config = upgrade_config.getCoreUpgradeConfig() csm_config = upgrade_config.getCSMUpgradeConfig() curated_config = upgrade_config.getCuratedModuleConfig() - easy_track_new_factories, _ = upgrade_config.getEasyTrackConfig() + 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"]) dual_governance = interface.DualGovernance(upgrade_config.DUAL_GOVERNANCE()) dual_governance_admin_executor = None @@ -482,6 +507,7 @@ def runtime_upgrade_context(): "acl": core_config["acl"], "aragon_kernel": core_config["kernel"], "lido": global_config["lido"], + "easy_track": global_config["easyTrack"], "lido_app_id": core_config["lidoAppId"], "lido_impl": core_config["newLidoImpl"], "lido_locator": core_config["locator"], @@ -521,18 +547,23 @@ def runtime_upgrade_context(): "cs_exit_penalties_impl": csm_config["exitPenaltiesImpl"], "cs_validator_strikes": csm_config["strikes"], "cs_validator_strikes_impl": csm_config["strikesImpl"], - "old_verifier": csm_config["verifier"], - "verifier_v3": csm_config["verifierV3"], + "old_verifier": csm_config["oldVerifier"], + "verifier_v3": csm_config["newVerifier"], "old_permissionless_gate": csm_config["oldPermissionlessGate"], - "new_permissionless_gate": csm_config["permissionlessGate"], - "ics_manager": csm_config["identifiedCommunityStakersGateManager"], - "csm_general_delayed_penalty_reporter": csm_config["generalDelayedPenaltyReporter"], - "csm_penalties_manager": csm_config["penaltiesManager"], + "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, "csm_ejector": csm_config["ejector"], + "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_hash_consensus": curated_config["hashConsensus"], "curated_module_item": StakingModuleItem( id=CURATED_MODULE_ID, @@ -547,7 +578,23 @@ def runtime_upgrade_context(): ), "update_staking_module_share_limits_factory": easy_track_new_factories["UpdateStakingModuleShareLimits"], "allow_consolidation_pair_factory": easy_track_new_factories["AllowConsolidationPair"], - "create_or_update_operator_group_factory": easy_track_new_factories["CreateOrUpdateOperatorGroup"], + "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"], "meta_registry": curated_config["metaRegistry"], } @@ -577,11 +624,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g agent = interface.Agent(ctx["agent"]) timelock = interface.EmergencyProtectedTimelock(EMERGENCY_PROTECTED_TIMELOCK) dual_governance = interface.DualGovernance(ctx["dual_governance"]) - # TODO: restore once Easy Track items are enabled in the vote again. - # easy_track = interface.EasyTrack(EASYTRACK) - # staking_router = interface.StakingRouter(STAKING_ROUTER) - # consolidation_migrator = interface.ConsolidationMigrator(CONSOLIDATION_MIGRATOR) - # meta_registry = interface.IMetaRegistry(META_REGISTRY) + easy_track = interface.EasyTrack(ctx["easy_track"]) vote_desc_items, call_script_items = get_vote_items( dg_only=DG_ONLY_MODE, @@ -596,6 +639,28 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g expected_ipfs_description_hash = IPFS_DESCRIPTION_HASH or calculate_vote_ipfs_description( get_ipfs_description(dg_only=DG_ONLY_MODE) )["cid"] + 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"], + ] + csm_tree_gate_permissions = _concat_permissions( + _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(gate, SET_TREE_PARAMS_SELECTOR) for gate in ctx["curated_gates"]] + ) # ========================================================================= # ======================== Identify or Create vote ======================== @@ -629,11 +694,11 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g # ========================= Before voting checks ======================== # ======================================================================= - # TODO: restore Easy Track pre-vote checks together with full ET flow. - # initial_factories = easy_track.getEVMScriptFactories() - # assert UPDATE_STAKING_MODULE_SHARE_LIMITS_FACTORY not in initial_factories - # assert ALLOW_CONSOLIDATION_PAIR_FACTORY not in initial_factories - # assert CREATE_OR_UPDATE_OPERATOR_GROUP_FACTORY not in initial_factories + initial_factories = easy_track.getEVMScriptFactories() + for factory in old_easy_track_factories: + assert factory in initial_factories + for factory in new_easy_track_factories: + assert factory not in initial_factories assert get_lido_vote_cid_from_str(find_metadata_by_vote_id(vote_id)) == expected_ipfs_description_hash @@ -645,11 +710,11 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g # ========================= After voting checks ========================= # ======================================================================= - # TODO: restore Easy Track post-vote checks together with full ET flow. - # new_factories = easy_track.getEVMScriptFactories() - # assert UPDATE_STAKING_MODULE_SHARE_LIMITS_FACTORY in new_factories - # assert ALLOW_CONSOLIDATION_PAIR_FACTORY in new_factories - # assert CREATE_OR_UPDATE_OPERATOR_GROUP_FACTORY in new_factories + new_factories = easy_track.getEVMScriptFactories() + for factory in old_easy_track_factories: + assert factory not in new_factories + for factory in new_easy_track_factories: + assert factory in new_factories assert len(vote_events) == expected_vote_events_count assert count_vote_items_by_events(vote_tx, voting.address) == expected_vote_events_count @@ -668,33 +733,116 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g proposal_calls=dual_governance_proposal_calls, ) - # TODO: restore ET event validation when full ET flow is enabled again. - # validate_evmscript_factory_added_event( - # event=vote_events[1], - # p=EVMScriptFactoryAdded( - # factory_addr=UPDATE_STAKING_MODULE_SHARE_LIMITS_FACTORY, - # permissions=create_permissions(staking_router, "updateModuleShares"), - # ), - # emitted_by=easy_track, - # ) - # - # validate_evmscript_factory_added_event( - # event=vote_events[2], - # p=EVMScriptFactoryAdded( - # factory_addr=ALLOW_CONSOLIDATION_PAIR_FACTORY, - # permissions=create_permissions(consolidation_migrator, "allowPair"), - # ), - # emitted_by=easy_track, - # ) - # - # validate_evmscript_factory_added_event( - # event=vote_events[3], - # p=EVMScriptFactoryAdded( - # factory_addr=CREATE_OR_UPDATE_OPERATOR_GROUP_FACTORY, - # permissions=create_permissions(meta_registry, "createOrUpdateOperatorGroup"), - # ), - # emitted_by=easy_track, - # ) + # Validate EasyTrack factory removal/addition events + # 2. Remove old CSMSettleElStealingPenalty 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 old CSMSetVettedGateTree 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 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 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 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 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 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 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 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 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 factory + validate_evmscript_factory_added_event( + event=vote_events[11], + p=EVMScriptFactoryAdded( + factory_addr=ctx["create_or_update_operator_group_factory"], + permissions=_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 live Hoodi vote.") @@ -704,14 +852,6 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g if expected_dg_proposal_id is not None: details = timelock.getProposalDetails(expected_dg_proposal_id) if details["status"] != PROPOSAL_STATUS["executed"]: - # ========================================================================= - # ================== DG before proposal executed checks =================== - # ========================================================================= - - # TODO Acceptance tests (before DG state) - - # TODO Scenario tests (before DG state) - if details["status"] == PROPOSAL_STATUS["submitted"]: chain.sleep(timelock.getAfterSubmitDelay() + 1) dual_governance.scheduleProposal(expected_dg_proposal_id, {"from": stranger}) @@ -721,24 +861,30 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g dg_tx: TransactionReceipt = timelock.execute(expected_dg_proposal_id, {"from": stranger}) display_dg_events(dg_tx) - dg_events = group_dg_events_from_receipt( + outer_dg_events = group_dg_events_from_receipt( dg_tx, timelock=EMERGENCY_PROTECTED_TIMELOCK, admin_executor=ctx["dual_governance_admin_executor"], ) - raw_dg_events = _group_raw_dg_events_from_receipt( + dg_events = _group_agent_dg_events_from_receipt( dg_tx, timelock=EMERGENCY_PROTECTED_TIMELOCK, - admin_executor=ctx["dual_governance_admin_executor"], + agent=agent.address, + ) + raw_dg_events = _group_raw_agent_dg_events_from_receipt( + dg_tx, + timelock=EMERGENCY_PROTECTED_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 assert len(raw_dg_events) == expected_dg_events_count # === DG EXECUTION EVENTS VALIDATION === # 1. Call UpgradeTemplate.startUpgrade - validate_events_chain([e.name for e in dg_events[0]], ["LogScriptCall", "UpgradeStarted", "ScriptResult", "Executed"]) + validate_events_chain([e.name for e in dg_events[0]], ["LogScriptCall", "UpgradeStarted"]) upgrade_started_event = _single_event(dg_events[0], "UpgradeStarted") _assert_emitted_by(upgrade_started_event, upgrade_template) @@ -762,8 +908,6 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g "RoleGranted", "RoleGranted", "Initialized", - "ScriptResult", - "Executed", ], ) role_grants = _event_list(dg_events[2], "RoleGranted") @@ -799,8 +943,6 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g "Upgraded", "ContractVersionSet", "ConsensusVersionSet", - "ScriptResult", - "Executed", ], ) validate_contract_version_set_event( @@ -812,8 +954,6 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g "Upgraded", "ContractVersionSet", "ConsensusVersionSet", - "ScriptResult", - "Executed", ], ) validate_consensus_version_set_event( @@ -826,8 +966,6 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g "Upgraded", "ContractVersionSet", "ConsensusVersionSet", - "ScriptResult", - "Executed", ], ) @@ -842,9 +980,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g "ContractVersionSet", "ConsensusVersionSet", "SetMaxValidatorsPerReport", - "(unknown)", - "ScriptResult", - "Executed", + "ExitBalanceLimitSet", ], ) validate_contract_version_set_event( @@ -857,9 +993,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g "ContractVersionSet", "ConsensusVersionSet", "SetMaxValidatorsPerReport", - "(unknown)", - "ScriptResult", - "Executed", + "ExitBalanceLimitSet", ], ) validate_consensus_version_set_event( @@ -873,15 +1007,17 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g "ContractVersionSet", "ConsensusVersionSet", "SetMaxValidatorsPerReport", - "(unknown)", - "ScriptResult", - "Executed", + "ExitBalanceLimitSet", ], ) 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"]) - validate_exit_balance_limit_set_raw_group(raw_dg_events[4], 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"]) # 6. Upgrade Accounting implementation validate_proxy_upgrade_event(dg_events[5], ctx["accounting_impl"], emitted_by=ctx["accounting"]) @@ -891,45 +1027,44 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g dg_events[6], ctx["withdrawal_vault_impl"], emitted_by=ctx["withdrawal_vault"], - events_chain=["LogScriptCall", "Upgraded", "ContractVersionSet", "ScriptResult", "Executed"], + events_chain=["LogScriptCall", "Upgraded", "ContractVersionSet"], ) validate_contract_version_set_event( dg_events[6], WITHDRAWAL_VAULT_CONTRACT_VERSION, emitted_by=ctx["withdrawal_vault"], - events_chain=["LogScriptCall", "Upgraded", "ContractVersionSet", "ScriptResult", "Executed"], + events_chain=["LogScriptCall", "Upgraded", "ContractVersionSet"], ) # 8. Grant APP_MANAGER_ROLE on Kernel to Agent - validate_aragon_grant_permission_event( - dg_events[7], - entity=ctx["agent"], - app=ctx["aragon_kernel"], - role=APP_MANAGER_ROLE, - emitted_by=ctx["acl"], - ) + 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"]) # 9. Set new Lido implementation in Kernel - validate_aragon_set_app_event( - dg_events[8], - app_id=ctx["lido_app_id"], - app=ctx["lido_impl"], - emitted_by=ctx["aragon_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"]) # 10. Revoke APP_MANAGER_ROLE on Kernel from Agent - validate_aragon_revoke_permission_event( - dg_events[9], - entity=ctx["agent"], - app=ctx["aragon_kernel"], - role=APP_MANAGER_ROLE, - emitted_by=ctx["acl"], - ) + 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"]) # 11. Grant BUFFER_RESERVE_MANAGER_ROLE on Lido and transfer permission manager to Agent validate_events_chain( [e.name for e in dg_events[10]], - ["LogScriptCall", "SetPermission", "ChangePermissionManager", "ScriptResult", "Executed"], + ["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"]) @@ -985,7 +1120,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g # 17. Set TWG exit limits validate_events_chain( [e.name for e in dg_events[16]], - ["LogScriptCall", "ExitRequestsLimitSet", "ScriptResult", "Executed"], + ["LogScriptCall", "ExitRequestsLimitSet"], ) exit_requests_limit_set_event = _single_event(dg_events[16], "ExitRequestsLimitSet") assert exit_requests_limit_set_event["maxExitRequestsLimit"] == TW_MAX_EXIT_REQUESTS @@ -994,11 +1129,11 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g _assert_emitted_by(exit_requests_limit_set_event, ctx["triggerable_withdrawals_gateway"]) # 18. Register CircuitBreaker integration - validate_circuit_breaker_registration_raw_group( - raw_dg_events[17], + validate_circuit_breaker_registration_event( + dg_events[17], circuit_breaker=ctx["circuit_breaker"], - consolidation_gateway=ctx["consolidation_gateway"], - curated_module_committee=ctx["curated_module_committee"], + pausable=ctx["consolidation_gateway"], + pauser=ctx["curated_module_committee"], ) # 19. Upgrade and initialize CSM @@ -1006,7 +1141,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g dg_events[18], ctx["csm_impl"], emitted_by=ctx["csm"], - events_chain=["LogScriptCall", "Upgraded", "Initialized", "ScriptResult", "Executed"], + events_chain=["LogScriptCall", "Upgraded", "Initialized"], ) initialized_event = _single_event(dg_events[18], "Initialized") assert initialized_event["version"] == 3 @@ -1017,7 +1152,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g dg_events[19], ctx["cs_parameters_registry_impl"], emitted_by=ctx["cs_parameters_registry"], - events_chain=["LogScriptCall", "Upgraded", "Initialized", "ScriptResult", "Executed"], + events_chain=["LogScriptCall", "Upgraded", "Initialized"], ) initialized_event = _single_event(dg_events[19], "Initialized") assert initialized_event["version"] == 3 @@ -1028,20 +1163,20 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g dg_events[20], ctx["cs_fee_oracle_impl"], emitted_by=ctx["cs_fee_oracle"], - events_chain=["LogScriptCall", "Upgraded", "ConsensusVersionSet", "ContractVersionSet", "ScriptResult", "Executed"], + events_chain=["LogScriptCall", "Upgraded", "ConsensusVersionSet", "ContractVersionSet"], ) validate_consensus_version_set_event( dg_events[20], 4, 3, emitted_by=ctx["cs_fee_oracle"], - events_chain=["LogScriptCall", "Upgraded", "ConsensusVersionSet", "ContractVersionSet", "ScriptResult", "Executed"], + events_chain=["LogScriptCall", "Upgraded", "ConsensusVersionSet", "ContractVersionSet"], ) validate_contract_version_set_event( dg_events[20], 3, emitted_by=ctx["cs_fee_oracle"], - events_chain=["LogScriptCall", "Upgraded", "ConsensusVersionSet", "ContractVersionSet", "ScriptResult", "Executed"], + events_chain=["LogScriptCall", "Upgraded", "ConsensusVersionSet", "ContractVersionSet"], ) # 22. Upgrade CSVettedGate @@ -1052,7 +1187,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g dg_events[22], ctx["cs_accounting_impl"], emitted_by=ctx["cs_accounting"], - events_chain=["LogScriptCall", "Upgraded", "Initialized", "ScriptResult", "Executed"], + events_chain=["LogScriptCall", "Upgraded", "Initialized"], ) initialized_event = _single_event(dg_events[22], "Initialized") assert initialized_event["version"] == 3 @@ -1063,7 +1198,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g dg_events[23], ctx["cs_fee_distributor_impl"], emitted_by=ctx["cs_fee_distributor"], - events_chain=["LogScriptCall", "Upgraded", "Initialized", "ScriptResult", "Executed"], + events_chain=["LogScriptCall", "Upgraded", "Initialized"], ) initialized_event = _single_event(dg_events[23], "Initialized") assert initialized_event["version"] == 3 @@ -1076,42 +1211,42 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g validate_proxy_upgrade_event(dg_events[25], ctx["cs_validator_strikes_impl"], emitted_by=ctx["cs_validator_strikes"]) # 27. Set CSM ejector - validate_events_chain([e.name for e in dg_events[26]], ["LogScriptCall", "EjectorSet", "ScriptResult", "Executed"]) + validate_events_chain([e.name for e in dg_events[26]], ["LogScriptCall", "EjectorSet"]) ejector_set_event = _single_event(dg_events[26], "EjectorSet") assert convert.to_address(ejector_set_event["ejector"]) == convert.to_address(ctx["csm_ejector"]) _assert_emitted_by(ejector_set_event, ctx["cs_validator_strikes"]) - # 28. Grant REPORT_GENERAL_DELAYED_PENALTY_ROLE - validate_role_grant_event( + # 28. Revoke REPORT_EL_REWARDS_STEALING_PENALTY_ROLE + validate_role_revoke_event( dg_events[27], - REPORT_GENERAL_DELAYED_PENALTY_ROLE, - ctx["csm_general_delayed_penalty_reporter"], + REPORT_EL_REWARDS_STEALING_PENALTY_ROLE, + ctx["csm_committee"], sender=ctx["agent"], emitted_by=ctx["csm"], ) - # 29. Grant SETTLE_GENERAL_DELAYED_PENALTY_ROLE + # 29. Grant REPORT_GENERAL_DELAYED_PENALTY_ROLE validate_role_grant_event( dg_events[28], - SETTLE_GENERAL_DELAYED_PENALTY_ROLE, - ctx["easytrack_evm_script_executor"], + REPORT_GENERAL_DELAYED_PENALTY_ROLE, + ctx["csm_committee"], sender=ctx["agent"], emitted_by=ctx["csm"], ) - # 30. Revoke REPORT_EL_REWARDS_STEALING_PENALTY_ROLE + # 30. Revoke SETTLE_EL_REWARDS_STEALING_PENALTY_ROLE validate_role_revoke_event( dg_events[29], - REPORT_EL_REWARDS_STEALING_PENALTY_ROLE, - ctx["csm_general_delayed_penalty_reporter"], + SETTLE_EL_REWARDS_STEALING_PENALTY_ROLE, + ctx["easytrack_evm_script_executor"], sender=ctx["agent"], emitted_by=ctx["csm"], ) - # 31. Revoke SETTLE_EL_REWARDS_STEALING_PENALTY_ROLE - validate_role_revoke_event( + # 31. Grant SETTLE_GENERAL_DELAYED_PENALTY_ROLE + validate_role_grant_event( dg_events[30], - SETTLE_EL_REWARDS_STEALING_PENALTY_ROLE, + SETTLE_GENERAL_DELAYED_PENALTY_ROLE, ctx["easytrack_evm_script_executor"], sender=ctx["agent"], emitted_by=ctx["csm"], @@ -1171,53 +1306,160 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g emitted_by=ctx["csm"], ) - # 38. No-op DG item - validate_dg_noop_event(dg_events[37]) - - # 39. No-op DG item - validate_dg_noop_event(dg_events[38]) - - # 40. No-op DG item - validate_dg_noop_event(dg_events[39]) - - # 41. No-op DG item - validate_dg_noop_event(dg_events[40]) - - # 42. Revoke START_REFERRAL_SEASON_ROLE from Agent + # 38. Revoke START_REFERRAL_SEASON_ROLE from Agent validate_role_revoke_event( - dg_events[41], + dg_events[37], START_REFERRAL_SEASON_ROLE, ctx["agent"], sender=ctx["agent"], emitted_by=ctx["cs_vetted_gate"], ) - # 43. Revoke END_REFERRAL_SEASON_ROLE from ICS manager + # 39. Revoke END_REFERRAL_SEASON_ROLE from CSM committee validate_role_revoke_event( - dg_events[42], + dg_events[38], END_REFERRAL_SEASON_ROLE, - ctx["ics_manager"], + ctx["csm_committee"], sender=ctx["agent"], emitted_by=ctx["cs_vetted_gate"], ) - # 44. No-op DG item - validate_dg_noop_event(dg_events[43]) + # 40. Register CircuitBreaker pauser for CSM new verifier + validate_circuit_breaker_registration_event( + dg_events[39], + circuit_breaker=ctx["circuit_breaker"], + pausable=ctx["verifier_v3"], + pauser=ctx["csm_committee"], + ) + + # 41. Register CircuitBreaker pauser for CSM ejector + validate_circuit_breaker_registration_event( + dg_events[40], + circuit_breaker=ctx["circuit_breaker"], + pausable=ctx["csm_ejector"], + pauser=ctx["csm_committee"], + ) + + # 42. Register CircuitBreaker pauser for identified DVT cluster gate + validate_circuit_breaker_registration_event( + dg_events[41], + circuit_breaker=ctx["circuit_breaker"], + pausable=ctx["identified_dvt_cluster_gate"], + pauser=ctx["csm_committee"], + ) + + # 43. Grant CREATE_NODE_OPERATOR_ROLE to identified DVT cluster gate + validate_role_grant_event( + dg_events[42], + CREATE_NODE_OPERATOR_ROLE, + ctx["identified_dvt_cluster_gate"], + sender=ctx["agent"], + emitted_by=ctx["csm"], + ) - # 45. No-op DG item - validate_dg_noop_event(dg_events[44]) + # 44. Grant SET_BOND_CURVE_ROLE to identified DVT cluster gate + validate_role_grant_event( + dg_events[43], + SET_BOND_CURVE_ROLE, + ctx["identified_dvt_cluster_gate"], + sender=ctx["agent"], + emitted_by=ctx["cs_accounting"], + ) - # 46. No-op DG item - validate_dg_noop_event(dg_events[45]) + # 45. Grant MANAGE_BOND_CURVES_ROLE to identified DVT cluster curve setup + validate_role_grant_event( + dg_events[44], + MANAGE_BOND_CURVES_ROLE, + ctx["identified_dvt_cluster_curve_setup"], + sender=ctx["agent"], + emitted_by=ctx["cs_accounting"], + ) - # 47. No-op DG item - validate_dg_noop_event(dg_events[46]) + # 46. Grant MANAGE_CURVE_PARAMETERS_ROLE to identified DVT cluster curve setup + validate_role_grant_event( + dg_events[45], + MANAGE_CURVE_PARAMETERS_ROLE, + ctx["identified_dvt_cluster_curve_setup"], + sender=ctx["agent"], + emitted_by=ctx["cs_parameters_registry"], + ) + + # 47. Execute identified DVT cluster curve setup + validate_events_chain( + [e.name for e in dg_events[46]], + [ + "LogScriptCall", + "BondCurveAdded", + "KeyRemovalChargeSet", + "GeneralDelayedPenaltyAdditionalFineSet", + "QueueConfigSet", + "RewardShareDataSet", + "AllowedExitDelaySet", + "ExitDelayFeeSet", + "RoleRevoked", + "RoleRevoked", + "BondCurveDeployed", + ], + ) + bond_curve_added_event = _single_event(dg_events[46], "BondCurveAdded") + assert bond_curve_added_event["curveId"] == ctx["identified_dvt_cluster_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[46], "KeyRemovalChargeSet") + assert key_removal_charge_set_event["curveId"] == ctx["identified_dvt_cluster_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[46], + "GeneralDelayedPenaltyAdditionalFineSet", + ) + assert general_delayed_penalty_fine_event["curveId"] == ctx["identified_dvt_cluster_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[46], "QueueConfigSet") + assert queue_config_set_event["curveId"] == ctx["identified_dvt_cluster_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[46], "RewardShareDataSet") + assert reward_share_data_set_event["curveId"] == ctx["identified_dvt_cluster_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[46], "AllowedExitDelaySet") + assert allowed_exit_delay_set_event["curveId"] == ctx["identified_dvt_cluster_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[46], "ExitDelayFeeSet") + assert exit_delay_fee_event["curveId"] == ctx["identified_dvt_cluster_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[46], "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[46], "BondCurveDeployed") + assert bond_curve_deployed_event["curveId"] == ctx["identified_dvt_cluster_bond_curve_id"] + _assert_emitted_by(bond_curve_deployed_event, ctx["identified_dvt_cluster_curve_setup"]) # 48. Grant MANAGE_GENERAL_PENALTIES_AND_CHARGES_ROLE validate_role_grant_event( dg_events[47], MANAGE_GENERAL_PENALTIES_AND_CHARGES_ROLE, - ctx["csm_penalties_manager"], + ctx["csm_committee"], sender=ctx["agent"], emitted_by=ctx["cs_parameters_registry"], ) @@ -1289,7 +1531,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g ) # 57. Resume curated module - validate_events_chain([e.name for e in dg_events[56]], ["LogScriptCall", "Resumed", "ScriptResult", "Executed"]) + validate_events_chain([e.name for e in dg_events[56]], ["LogScriptCall", "Resumed"]) resumed_event = _single_event(dg_events[56], "Resumed") _assert_emitted_by(resumed_event, ctx["curated_module"]) @@ -1303,21 +1545,53 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g ) # 59. Set curated HashConsensus frame config - validate_events_chain([e.name for e in dg_events[58]], ["LogScriptCall", "FrameConfigSet", "ScriptResult", "Executed"]) + validate_events_chain([e.name for e in dg_events[58]], ["LogScriptCall", "FrameConfigSet"]) frame_config_set_event = _single_event(dg_events[58], "FrameConfigSet") assert frame_config_set_event["newInitialEpoch"] == CURATED_INITIAL_EPOCH assert frame_config_set_event["newEpochsPerFrame"] == CURATED_EPOCHS_PER_FRAME _assert_emitted_by(frame_config_set_event, ctx["curated_hash_consensus"]) - # 60. Call UpgradeTemplate.finishUpgrade - validate_events_chain([e.name for e in dg_events[59]], ["LogScriptCall", "UpgradeFinished", "ScriptResult", "Executed"]) - upgrade_finished_event = _single_event(dg_events[59], "UpgradeFinished") - _assert_emitted_by(upgrade_finished_event, upgrade_template) + # 60. Register CircuitBreaker pauser for Curated module + validate_circuit_breaker_registration_event( + dg_events[59], + circuit_breaker=ctx["circuit_breaker"], + pausable=ctx["curated_module"], + pauser=ctx["curated_circuit_breaker_pauser"], + ) - # ========================================================================= - # ==================== After DG proposal executed checks ================== - # ========================================================================= + # 61. Register CircuitBreaker pauser for Curated accounting + validate_circuit_breaker_registration_event( + dg_events[60], + circuit_breaker=ctx["circuit_breaker"], + pausable=ctx["curated_accounting"], + pauser=ctx["curated_circuit_breaker_pauser"], + ) - # TODO Acceptance tests (after DG state) + # 62. Register CircuitBreaker pauser for Curated fee oracle + validate_circuit_breaker_registration_event( + dg_events[61], + circuit_breaker=ctx["circuit_breaker"], + pausable=ctx["curated_fee_oracle"], + pauser=ctx["curated_circuit_breaker_pauser"], + ) - # TODO Scenario tests (after DG state) + # 63. Register CircuitBreaker pauser for Curated verifier + validate_circuit_breaker_registration_event( + dg_events[62], + circuit_breaker=ctx["circuit_breaker"], + pausable=ctx["curated_verifier"], + pauser=ctx["curated_circuit_breaker_pauser"], + ) + + # 64. Register CircuitBreaker pauser for Curated ejector + validate_circuit_breaker_registration_event( + dg_events[63], + circuit_breaker=ctx["circuit_breaker"], + pausable=ctx["curated_ejector"], + pauser=ctx["curated_circuit_breaker_pauser"], + ) + + # 65. Call UpgradeTemplate.finishUpgrade + validate_events_chain([e.name for e in dg_events[64]], ["LogScriptCall", "UpgradeFinished", "ScriptResult", "Executed"]) + upgrade_finished_event = _single_event(dg_events[64], "UpgradeFinished") + _assert_emitted_by(upgrade_finished_event, upgrade_template) From 3480c23ec8b66c854ec07095c8aee856922fc9b2 Mon Sep 17 00:00:00 2001 From: Eddort Date: Tue, 28 Apr 2026 16:07:08 +0200 Subject: [PATCH 06/15] feat: add consolidation gateway pauser to upgrade context and update test validation --- interfaces/UpgradeConfig.json | 2 +- tests/test_2026_04_14_hoodi_protocol_upgrade.py | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/interfaces/UpgradeConfig.json b/interfaces/UpgradeConfig.json index 026aa553..7a004dfd 100644 --- a/interfaces/UpgradeConfig.json +++ b/interfaces/UpgradeConfig.json @@ -1 +1 @@ -[{"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":"resealManager","type":"address"},{"internalType":"address","name":"circuitBreaker","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":"oldLocatorImpl","type":"address"},{"internalType":"address","name":"oldLidoImpl","type":"address"},{"internalType":"address","name":"oldAccountingImpl","type":"address"},{"internalType":"address","name":"oldAccountingOracleImpl","type":"address"},{"internalType":"address","name":"oldStakingRouterImpl","type":"address"},{"internalType":"address","name":"oldWithdrawalVaultImpl","type":"address"},{"internalType":"address","name":"oldValidatorsExitBusOracleImpl","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":"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":"address","name":"topUpGateway","type":"address"},{"internalType":"uint256","name":"lidoDepositsReserveTarget","type":"uint256"},{"internalType":"address","name":"curatedModuleCommittee","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":"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":"ejector","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":"NewAndOldLocatorImplementationsMustBeDifferent","type":"error"},{"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":"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":"identifiedDVTClusterGate","type":"address"},{"internalType":"address","name":"identifiedDVTClusterCurveSetup","type":"address"},{"internalType":"uint256","name":"identifiedDVTClusterBondCurveId","type":"uint256"},{"internalType":"address","name":"vettedGateImpl","type":"address"},{"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":"oldVerifier","type":"address"},{"internalType":"address","name":"newVerifier","type":"address"},{"internalType":"address","name":"newPermissionlessGate","type":"address"},{"internalType":"address","name":"oldEjector","type":"address"},{"internalType":"address","name":"ejector","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":"oldLocatorImpl","type":"address"},{"internalType":"address","name":"oldLidoImpl","type":"address"},{"internalType":"address","name":"oldAccountingImpl","type":"address"},{"internalType":"address","name":"oldAccountingOracleImpl","type":"address"},{"internalType":"address","name":"oldStakingRouterImpl","type":"address"},{"internalType":"address","name":"oldWithdrawalVaultImpl","type":"address"},{"internalType":"address","name":"oldValidatorsExitBusOracleImpl","type":"address"},{"internalType":"address","name":"oldOracleReportSanityChecker","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":"curatedModuleCommittee","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":"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":"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"}] +[{"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":"resealManager","type":"address"},{"internalType":"address","name":"circuitBreaker","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":"oldLocatorImpl","type":"address"},{"internalType":"address","name":"oldLidoImpl","type":"address"},{"internalType":"address","name":"oldAccountingImpl","type":"address"},{"internalType":"address","name":"oldAccountingOracleImpl","type":"address"},{"internalType":"address","name":"oldStakingRouterImpl","type":"address"},{"internalType":"address","name":"oldWithdrawalVaultImpl","type":"address"},{"internalType":"address","name":"oldValidatorsExitBusOracleImpl","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":"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":"address","name":"topUpGateway","type":"address"},{"internalType":"uint256","name":"lidoDepositsReserveTarget","type":"uint256"},{"internalType":"address","name":"curatedModuleCommittee","type":"address"},{"internalType":"address","name":"topUpGatewayDepositor","type":"address"},{"internalType":"address","name":"consolidationGatewayPauser","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":"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":"ejector","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":"NewAndOldLocatorImplementationsMustBeDifferent","type":"error"},{"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":"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":"identifiedDVTClusterGate","type":"address"},{"internalType":"address","name":"identifiedDVTClusterCurveSetup","type":"address"},{"internalType":"uint256","name":"identifiedDVTClusterBondCurveId","type":"uint256"},{"internalType":"address","name":"vettedGateImpl","type":"address"},{"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":"oldVerifier","type":"address"},{"internalType":"address","name":"newVerifier","type":"address"},{"internalType":"address","name":"newPermissionlessGate","type":"address"},{"internalType":"address","name":"oldEjector","type":"address"},{"internalType":"address","name":"ejector","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":"oldLocatorImpl","type":"address"},{"internalType":"address","name":"oldLidoImpl","type":"address"},{"internalType":"address","name":"oldAccountingImpl","type":"address"},{"internalType":"address","name":"oldAccountingOracleImpl","type":"address"},{"internalType":"address","name":"oldStakingRouterImpl","type":"address"},{"internalType":"address","name":"oldWithdrawalVaultImpl","type":"address"},{"internalType":"address","name":"oldValidatorsExitBusOracleImpl","type":"address"},{"internalType":"address","name":"oldOracleReportSanityChecker","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":"curatedModuleCommittee","type":"address"},{"internalType":"address","name":"topUpGatewayDepositor","type":"address"},{"internalType":"address","name":"consolidationGatewayPauser","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":"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":"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/tests/test_2026_04_14_hoodi_protocol_upgrade.py b/tests/test_2026_04_14_hoodi_protocol_upgrade.py index 92934b82..63f57267 100644 --- a/tests/test_2026_04_14_hoodi_protocol_upgrade.py +++ b/tests/test_2026_04_14_hoodi_protocol_upgrade.py @@ -526,6 +526,7 @@ def runtime_upgrade_context(): "easytrack_evm_script_executor": global_config["easyTrackEVMScriptExecutor"], "circuit_breaker": global_config["circuitBreaker"], "consolidation_gateway": core_config["consolidationGateway"], + "consolidation_gateway_pauser": core_config["consolidationGatewayPauser"], "curated_module_committee": core_config["curatedModuleCommittee"], "old_deposit_security_module": core_config["oldDepositSecurityModule"], "new_deposit_security_module": core_config["newDepositSecurityModule"], @@ -1128,12 +1129,12 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g assert exit_requests_limit_set_event["frameDurationInSec"] == TW_FRAME_DURATION_IN_SEC _assert_emitted_by(exit_requests_limit_set_event, ctx["triggerable_withdrawals_gateway"]) - # 18. Register CircuitBreaker integration + # 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["curated_module_committee"], + pauser=ctx["consolidation_gateway_pauser"], ) # 19. Upgrade and initialize CSM From 9d8b73d3e2565a46ab95e42153718bca0f510c4b Mon Sep 17 00:00:00 2001 From: Eddort Date: Tue, 28 Apr 2026 16:34:40 +0200 Subject: [PATCH 07/15] feat: srv3 smv2 hoodi --- ...grade_2026_04_14_hoodi_protocol_upgrade.py | 287 ------------------ scripts/upgrade_2026_04_X_hoodi_srv3_cmv2.py | 245 +++++++++++++++ ...e.py => test_2026_04_X_hoodi_srv3_cmv2.py} | 13 +- 3 files changed, 253 insertions(+), 292 deletions(-) delete mode 100644 scripts/upgrade_2026_04_14_hoodi_protocol_upgrade.py create mode 100644 scripts/upgrade_2026_04_X_hoodi_srv3_cmv2.py rename tests/{test_2026_04_14_hoodi_protocol_upgrade.py => test_2026_04_X_hoodi_srv3_cmv2.py} (99%) diff --git a/scripts/upgrade_2026_04_14_hoodi_protocol_upgrade.py b/scripts/upgrade_2026_04_14_hoodi_protocol_upgrade.py deleted file mode 100644 index 550a89a8..00000000 --- a/scripts/upgrade_2026_04_14_hoodi_protocol_upgrade.py +++ /dev/null @@ -1,287 +0,0 @@ -""" -TODO Vote 2026_04_14 - -Uses deployed `UpgradeVoteScript` as the source of truth for both: -1. DG items returned by `getVoteItems()` -2. Immediate voting items returned by `getVotingVoteItems()` - -Replace the TODO values below after the Hoodi deployment. -""" - -import os - -from typing import Dict, List, Optional, Tuple - -from brownie import interface - -from utils.config import 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 - - -# ============================== Addresses =================================== -UPGRADE_VOTE_SCRIPT = "0xfaAddC93baf78e89DCf37bA67943E1bE8F37Bb8c" -HOODI_DG_ONLY_ENV = "HOODI_DG_ONLY" - - -# ============================= Description ================================== -DG_PROPOSAL_METADATA = "Upgrade Lido protocol contracts on Ethereum Hoodi testnet" -DG_SUBMISSION_DESCRIPTION = "1. Submit a Dual Governance proposal for the Lido protocol upgrade on Ethereum Hoodi testnet" -IPFS_DESCRIPTION = """ -**Lido protocol upgrade on Ethereum Hoodi testnet** - -**Dual Governance proposal** -1. Submit a Dual Governance proposal for the Lido protocol upgrade on Ethereum Hoodi testnet. -1.1. Call UpgradeTemplate.startUpgrade -1.2. Upgrade LidoLocator implementation -1.3. Grant Aragon APP_MANAGER_ROLE to the AGENT -1.4. Set Lido implementation in Kernel -1.5. Revoke Aragon APP_MANAGER_ROLE from the AGENT -1.6. Upgrade StakingRouter implementation and finalize v4 migration -1.7. Grant STAKING_MODULE_SHARE_MANAGE_ROLE to EasyTrack executor -1.8. Upgrade AccountingOracle implementation -1.9. Upgrade Accounting implementation -1.10. Upgrade WithdrawalVault implementation -1.11. Upgrade and finalize CSM v3 -1.12. Upgrade and finalize ParametersRegistry v3 -1.13. Upgrade and finalize FeeOracle v3 -1.14. Upgrade VettedGate implementation -1.15. Upgrade and finalize Accounting v3 -1.16. Upgrade and finalize FeeDistributor v3 -1.17. Upgrade ExitPenalties implementation -1.18. Upgrade ValidatorStrikes implementation -1.19. Point ValidatorStrikes to the new Ejector -1.20. Grant REPORT_GENERAL_DELAYED_PENALTY_ROLE -1.21. Grant SETTLE_GENERAL_DELAYED_PENALTY_ROLE -1.22. Revoke REPORT_EL_REWARDS_STEALING_PENALTY_ROLE -1.23. Revoke SETTLE_EL_REWARDS_STEALING_PENALTY_ROLE -1.24. Revoke VERIFIER_ROLE from old verifier -1.25. Grant VERIFIER_ROLE to VerifierV3 -1.26. Grant REPORT_REGULAR_WITHDRAWN_VALIDATORS_ROLE to VerifierV3 -1.27. Grant REPORT_SLASHED_WITHDRAWN_VALIDATORS_ROLE to Easy Track -1.28. Revoke CREATE_NODE_OPERATOR_ROLE from old PermissionlessGate -1.29. Grant CREATE_NODE_OPERATOR_ROLE to new PermissionlessGate -1.30. Revoke PAUSE_ROLE from old gate seal on CSModule -1.31. Revoke PAUSE_ROLE from old gate seal on Accounting -1.32. Revoke PAUSE_ROLE from old gate seal on FeeOracle -1.33. Revoke PAUSE_ROLE from old gate seal on VettedGate -1.34. Revoke PAUSE_ROLE from old gate seal on old Verifier -1.35. Revoke PAUSE_ROLE from old gate seal on old Ejector -1.36. Revoke PAUSE_ROLE from reseal manager on old Verifier -1.37. Revoke RESUME_ROLE from reseal manager on old Verifier -1.38. Revoke PAUSE_ROLE from reseal manager on old Ejector -1.39. Revoke RESUME_ROLE from reseal manager on old Ejector -1.40. Revoke START_REFERRAL_SEASON_ROLE -1.41. Revoke END_REFERRAL_SEASON_ROLE -1.42. Grant PAUSE_ROLE to GateSealV3 on CSModule -1.43. Grant PAUSE_ROLE to GateSealV3 on Accounting -1.44. Grant PAUSE_ROLE to GateSealV3 on FeeOracle -1.45. Grant PAUSE_ROLE to GateSealV3 on VettedGate -1.46. Grant MANAGE_GENERAL_PENALTIES_AND_CHARGES_ROLE to penaltiesManager -1.47. Revoke REQUEST_BURN_SHARES_ROLE from CSM Accounting -1.48. Grant REQUEST_BURN_MY_STETH_ROLE to CSM Accounting -1.49. Revoke TWG full-withdrawal role from old Ejector -1.50. Grant TWG full-withdrawal role to new Ejector -1.51. Add Curated module to StakingRouter -1.52. Grant REQUEST_BURN_MY_STETH_ROLE to Curated Accounting -1.53. Grant TWG full-withdrawal role to Curated Ejector -1.54. Grant RESUME_ROLE to agent on Curated module -1.55. Resume Curated module -1.56. Revoke RESUME_ROLE from agent on Curated module -1.57. Update Curated HashConsensus initial epoch -1.58. Call UpgradeTemplate.finishUpgrade - -**Immediate voting items** -2. Add UpdateStakingModuleShareLimits ET factory -3. Add AllowConsolidationPair ET factory -4. Add CreateOrUpdateOperatorGroup ET factory -""" - -DG_ONLY_IPFS_DESCRIPTION = """ -**Lido protocol upgrade on Ethereum Hoodi testnet** - -**Dual Governance proposal** -1. Submit a Dual Governance proposal for the Lido protocol upgrade on Ethereum Hoodi testnet. -1.1. Call UpgradeTemplate.startUpgrade -1.2. Upgrade LidoLocator implementation -1.3. Grant Aragon APP_MANAGER_ROLE to the AGENT -1.4. Set Lido implementation in Kernel -1.5. Revoke Aragon APP_MANAGER_ROLE from the AGENT -1.6. Upgrade StakingRouter implementation and finalize v4 migration -1.7. Grant STAKING_MODULE_SHARE_MANAGE_ROLE to EasyTrack executor -1.8. Upgrade AccountingOracle implementation -1.9. Upgrade Accounting implementation -1.10. Upgrade WithdrawalVault implementation -1.11. Upgrade and finalize CSM v3 -1.12. Upgrade and finalize ParametersRegistry v3 -1.13. Upgrade and finalize FeeOracle v3 -1.14. Upgrade VettedGate implementation -1.15. Upgrade and finalize Accounting v3 -1.16. Upgrade and finalize FeeDistributor v3 -1.17. Upgrade ExitPenalties implementation -1.18. Upgrade ValidatorStrikes implementation -1.19. Point ValidatorStrikes to the new Ejector -1.20. Grant REPORT_GENERAL_DELAYED_PENALTY_ROLE -1.21. Grant SETTLE_GENERAL_DELAYED_PENALTY_ROLE -1.22. Revoke REPORT_EL_REWARDS_STEALING_PENALTY_ROLE -1.23. Revoke SETTLE_EL_REWARDS_STEALING_PENALTY_ROLE -1.24. Revoke VERIFIER_ROLE from old verifier -1.25. Grant VERIFIER_ROLE to VerifierV3 -1.26. Grant REPORT_REGULAR_WITHDRAWN_VALIDATORS_ROLE to VerifierV3 -1.27. Grant REPORT_SLASHED_WITHDRAWN_VALIDATORS_ROLE to Easy Track -1.28. Revoke CREATE_NODE_OPERATOR_ROLE from old PermissionlessGate -1.29. Grant CREATE_NODE_OPERATOR_ROLE to new PermissionlessGate -1.30. Revoke PAUSE_ROLE from old gate seal on CSModule -1.31. Revoke PAUSE_ROLE from old gate seal on Accounting -1.32. Revoke PAUSE_ROLE from old gate seal on FeeOracle -1.33. Revoke PAUSE_ROLE from old gate seal on VettedGate -1.34. Revoke PAUSE_ROLE from old gate seal on old Verifier -1.35. Revoke PAUSE_ROLE from old gate seal on old Ejector -1.36. Revoke PAUSE_ROLE from reseal manager on old Verifier -1.37. Revoke RESUME_ROLE from reseal manager on old Verifier -1.38. Revoke PAUSE_ROLE from reseal manager on old Ejector -1.39. Revoke RESUME_ROLE from reseal manager on old Ejector -1.40. Revoke START_REFERRAL_SEASON_ROLE -1.41. Revoke END_REFERRAL_SEASON_ROLE -1.42. Grant PAUSE_ROLE to GateSealV3 on CSModule -1.43. Grant PAUSE_ROLE to GateSealV3 on Accounting -1.44. Grant PAUSE_ROLE to GateSealV3 on FeeOracle -1.45. Grant PAUSE_ROLE to GateSealV3 on VettedGate -1.46. Grant MANAGE_GENERAL_PENALTIES_AND_CHARGES_ROLE to penaltiesManager -1.47. Revoke REQUEST_BURN_SHARES_ROLE from CSM Accounting -1.48. Grant REQUEST_BURN_MY_STETH_ROLE to CSM Accounting -1.49. Revoke TWG full-withdrawal role from old Ejector -1.50. Grant TWG full-withdrawal role to new Ejector -1.51. Add Curated module to StakingRouter -1.52. Grant REQUEST_BURN_MY_STETH_ROLE to Curated Accounting -1.53. Grant TWG full-withdrawal role to Curated Ejector -1.54. Grant RESUME_ROLE to agent on Curated module -1.55. Resume Curated module -1.56. Revoke RESUME_ROLE from agent on Curated module -1.57. Update Curated HashConsensus initial epoch -1.58. Call UpgradeTemplate.finishUpgrade -""" - - -# ================================ Main ====================================== - - -def is_dg_only_mode() -> bool: - return os.getenv(HOODI_DG_ONLY_ENV, "").lower() in ("1", "true", "yes", "on") - - -def get_ipfs_description(dg_only: Optional[bool] = None) -> str: - dg_only = is_dg_only_mode() if dg_only is None else dg_only - return DG_ONLY_IPFS_DESCRIPTION if dg_only else IPFS_DESCRIPTION - - -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 vote_script_address.lower() in ("", "0x0000000000000000000000000000000000000000"): - 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( - dg_only: Optional[bool] = None, - upgrade_vote_script: Optional[str] = None, -) -> Tuple[List[str], List[Tuple[str, str]]]: - dg_only = is_dg_only_mode() if dg_only is None else dg_only - vote_script_address = (upgrade_vote_script or UPGRADE_VOTE_SCRIPT).strip() - if vote_script_address.lower() in ("", "0x0000000000000000000000000000000000000000"): - 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]) - - if not dg_only: - 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, - dg_only: Optional[bool] = None, - upgrade_vote_script: Optional[str] = None, -): - dg_only = is_dg_only_mode() if dg_only is None else dg_only - vote_desc_items, call_script_items = get_vote_items( - dg_only=dg_only, - upgrade_vote_script=upgrade_vote_script, - ) - vote_items = bake_vote_items(list(vote_desc_items), list(call_script_items)) - ipfs_description = get_ipfs_description(dg_only=dg_only) - - 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) - ) - - if not dg_only: - 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/scripts/upgrade_2026_04_X_hoodi_srv3_cmv2.py b/scripts/upgrade_2026_04_X_hoodi_srv3_cmv2.py new file mode 100644 index 00000000..7caef221 --- /dev/null +++ b/scripts/upgrade_2026_04_X_hoodi_srv3_cmv2.py @@ -0,0 +1,245 @@ +""" +TODO Vote 2026_04_14 + +Uses deployed `UpgradeVoteScript` as the source of truth for both: +1. DG items returned by `getVoteItems()` +2. Immediate voting items returned by `getVotingVoteItems()` + +Replace the TODO values below after the Hoodi deployment. +""" + +import os + +from typing import Dict, List, Optional, Tuple + +from brownie import interface + +from utils.config import 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 + + +# ============================== Addresses =================================== +UPGRADE_VOTE_SCRIPT = "TODO: set deployed UpgradeVoteScript address" +HOODI_DG_ONLY_ENV = "HOODI_DG_ONLY" + + +# ============================= Description ================================== +DG_PROPOSAL_METADATA = "Upgrade Lido protocol contracts on Ethereum Hoodi testnet" +DG_SUBMISSION_DESCRIPTION = "1. Submit a Dual Governance proposal for the Lido protocol upgrade on Ethereum Hoodi testnet" +DG_IPFS_DESCRIPTION = """ +**Lido protocol upgrade on Ethereum Hoodi testnet** + +**Dual Governance proposal** +1. Submit a Dual Governance proposal for the Lido protocol upgrade on Ethereum Hoodi testnet. +1.1. Call UpgradeTemplate.startUpgrade +1.2. Upgrade LidoLocator implementation +1.3. Upgrade StakingRouter implementation +1.4. Upgrade AccountingOracle implementation +1.5. Upgrade ValidatorsExitBusOracle implementation +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 +1.19. Upgrade and finalize CSM v3 +1.20. Upgrade and finalize ParametersRegistry v3 +1.21. Upgrade and finalize FeeOracle v3 +1.22. Upgrade VettedGate 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.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 initial epoch +1.60. Register CircuitBreaker pauser for CuratedModule +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.65. Call UpgradeTemplate.finishUpgrade +""" + +IMMEDIATE_VOTING_IPFS_DESCRIPTION = """**Immediate voting items** +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 +""" + +IPFS_DESCRIPTION = DG_IPFS_DESCRIPTION + "\n" + IMMEDIATE_VOTING_IPFS_DESCRIPTION + + +# ================================ Main ====================================== + + +def is_dg_only_mode() -> bool: + return os.getenv(HOODI_DG_ONLY_ENV, "").lower() in ("1", "true", "yes", "on") + + +def is_placeholder_vote_script_address(value: str) -> bool: + normalized = value.strip().lower() + return normalized in ("", "0x0000000000000000000000000000000000000000") or normalized.startswith("todo") + + +def get_ipfs_description(dg_only: Optional[bool] = None) -> str: + dg_only = is_dg_only_mode() if dg_only is None else dg_only + return DG_IPFS_DESCRIPTION if dg_only else IPFS_DESCRIPTION + + +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( + dg_only: Optional[bool] = None, + upgrade_vote_script: Optional[str] = None, +) -> Tuple[List[str], List[Tuple[str, str]]]: + dg_only = is_dg_only_mode() if dg_only is None else dg_only + 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]) + + if not dg_only: + 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, + dg_only: Optional[bool] = None, + upgrade_vote_script: Optional[str] = None, +): + dg_only = is_dg_only_mode() if dg_only is None else dg_only + vote_desc_items, call_script_items = get_vote_items( + dg_only=dg_only, + upgrade_vote_script=upgrade_vote_script, + ) + vote_items = bake_vote_items(list(vote_desc_items), list(call_script_items)) + ipfs_description = get_ipfs_description(dg_only=dg_only) + + 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) + ) + + if not dg_only: + 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/test_2026_04_14_hoodi_protocol_upgrade.py b/tests/test_2026_04_X_hoodi_srv3_cmv2.py similarity index 99% rename from tests/test_2026_04_14_hoodi_protocol_upgrade.py rename to tests/test_2026_04_X_hoodi_srv3_cmv2.py index 63f57267..be4091e9 100644 --- a/tests/test_2026_04_14_hoodi_protocol_upgrade.py +++ b/tests/test_2026_04_X_hoodi_srv3_cmv2.py @@ -1,3 +1,5 @@ +import os + from typing import NamedTuple, Optional import pytest @@ -32,7 +34,7 @@ # ============================================================================ # ============================== Import vote ================================= # ============================================================================ -from scripts.upgrade_2026_04_14_hoodi_protocol_upgrade import ( +from scripts.upgrade_2026_04_X_hoodi_srv3_cmv2 import ( get_ipfs_description, start_vote, get_vote_items, @@ -129,6 +131,7 @@ def _selector(signature: str) -> str: EXPECTED_DG_EVENTS_COUNT = 65 IPFS_DESCRIPTION_HASH = None DG_ONLY_MODE = False +UPGRADE_VOTE_SCRIPT_ENV = "HOODI_UPGRADE_VOTE_SCRIPT" class StakingModuleItem(NamedTuple): @@ -145,7 +148,7 @@ class StakingModuleItem(NamedTuple): def _is_placeholder_address(value: str) -> bool: normalized = str(value).lower() - return normalized in ("", "0x0000000000000000000000000000000000000000") + return normalized in ("", "0x0000000000000000000000000000000000000000") or normalized.startswith("todo") def _is_placeholder_text(value: str) -> bool: @@ -449,7 +452,7 @@ def runtime_upgrade_context(): if network_name() != "hoodi-fork": pytest.skip("Run the dedicated Hoodi upgrade test on --network hoodi-fork.") - upgrade_vote_script = UPGRADE_VOTE_SCRIPT + upgrade_vote_script = os.getenv(UPGRADE_VOTE_SCRIPT_ENV, UPGRADE_VOTE_SCRIPT) if ( _is_placeholder_address(upgrade_vote_script) @@ -457,8 +460,8 @@ def runtime_upgrade_context(): or _is_placeholder_text(get_ipfs_description(dg_only=DG_ONLY_MODE)) ): pytest.skip( - "Upgrade vote script address is missing. Set UPGRADE_VOTE_SCRIPT in " - "scripts/upgrade_2026_04_14_hoodi_protocol_upgrade.py first." + "Upgrade vote script address is missing. Set HOODI_UPGRADE_VOTE_SCRIPT " + "or UPGRADE_VOTE_SCRIPT in scripts/upgrade_2026_04_X_hoodi_srv3_cmv2.py first." ) vote_script = interface.UpgradeVoteScript(upgrade_vote_script) From 1b32e2ab6166c039d76529fa1f501e5e1022403e Mon Sep 17 00:00:00 2001 From: Eddort Date: Tue, 28 Apr 2026 16:42:21 +0200 Subject: [PATCH 08/15] feat: remove hoodi_upgrade.py utility script --- utils/hoodi_upgrade.py | 139 ----------------------------------------- 1 file changed, 139 deletions(-) delete mode 100644 utils/hoodi_upgrade.py diff --git a/utils/hoodi_upgrade.py b/utils/hoodi_upgrade.py deleted file mode 100644 index 8d1fb287..00000000 --- a/utils/hoodi_upgrade.py +++ /dev/null @@ -1,139 +0,0 @@ -import json -import os -from pathlib import Path -from typing import Any, Dict - -from brownie import Contract - -try: - import tomllib # type: ignore[attr-defined] -except ModuleNotFoundError: - import toml as tomllib # type: ignore[no-redef] - - -ZERO_ADDRESS = "0x0000000000000000000000000000000000000000" - -PROJECT_ROOT = Path(__file__).resolve().parents[1] -LIDO_CORE_ROOT = PROJECT_ROOT / "lido-core" - -DEFAULT_DEPLOYED_LOCAL_FILE = "deployed-local.json" -DEFAULT_UPGRADE_PARAMS_FILE = "scripts/upgrade/upgrade-params-hoodi.toml" -DEFAULT_CURATED_MODULE_ARTIFACT = "artifacts/contracts/upgrade/UpgradeTypes.sol/ICuratedModule.json" - - -def _resolve_lido_core_path(env_name: str, default_relative_path: str) -> Path: - value = os.getenv(env_name, default_relative_path) - path = Path(value) - if not path.is_absolute(): - path = LIDO_CORE_ROOT / path - return path - - -def get_deployed_local_path() -> Path: - return _resolve_lido_core_path("LIDO_CORE_DEPLOYED_FILE", DEFAULT_DEPLOYED_LOCAL_FILE) - - -def get_upgrade_params_path() -> Path: - return _resolve_lido_core_path("LIDO_CORE_UPGRADE_PARAMS_FILE", DEFAULT_UPGRADE_PARAMS_FILE) - - -def get_curated_module_artifact_path() -> Path: - return _resolve_lido_core_path("LIDO_CORE_CURATED_MODULE_ARTIFACT", DEFAULT_CURATED_MODULE_ARTIFACT) - - -def load_deployed_local_state() -> Dict[str, Any]: - state_path = get_deployed_local_path() - if not state_path.exists(): - raise FileNotFoundError(f"local deployment state file not found: {state_path}") - return json.loads(state_path.read_text()) - - -def _loads_toml(text: str) -> Dict[str, Any]: - return tomllib.loads(text) - - -def load_upgrade_params() -> Dict[str, Any]: - params_path = get_upgrade_params_path() - if not params_path.exists(): - raise FileNotFoundError(f"upgrade params file not found: {params_path}") - return _loads_toml(params_path.read_text()) - - -def get_state_address(key: str) -> str: - state = load_deployed_local_state() - item = state.get(key) - if item is None: - raise KeyError(f"deployment state key is missing: {key}") - - if isinstance(item, dict): - address = item.get("address") - if isinstance(address, str): - return address - - proxy = item.get("proxy") - if isinstance(proxy, dict) and isinstance(proxy.get("address"), str): - return proxy["address"] - - raise KeyError(f"could not extract address from deployment state key: {key}") - - -def get_optional_state_address(key: str, default: str = ZERO_ADDRESS) -> str: - try: - return get_state_address(key) - except Exception: - return default - - -def get_upgrade_vote_script_address() -> str: - return get_state_address("upgradeVoteScript") - - -def get_optional_upgrade_vote_script_address(default: str = ZERO_ADDRESS) -> str: - return get_optional_state_address("upgradeVoteScript", default) - - -def get_consolidation_migrator_address() -> str: - return get_state_address("consolidationMigrator") - - -def get_optional_consolidation_migrator_address(default: str = ZERO_ADDRESS) -> str: - return get_optional_state_address("consolidationMigrator", default) - - -def get_easy_track_new_factories() -> Dict[str, str]: - params = load_upgrade_params() - return dict(params["easyTrack"]["newFactories"]) - - -def get_optional_easy_track_new_factories() -> Dict[str, str]: - try: - return get_easy_track_new_factories() - except Exception: - return { - "UpdateStakingModuleShareLimits": ZERO_ADDRESS, - "AllowConsolidationPair": ZERO_ADDRESS, - "CreateOrUpdateOperatorGroup": ZERO_ADDRESS, - } - - -def get_curated_module_address() -> str: - params = load_upgrade_params() - return params["curatedModule"]["module"] - - -def get_meta_registry_address() -> str: - artifact_path = get_curated_module_artifact_path() - if not artifact_path.exists(): - raise FileNotFoundError(f"curated module artifact not found: {artifact_path}") - - artifact = json.loads(artifact_path.read_text()) - abi = artifact["abi"] - curated_module = Contract.from_abi("ICuratedModule", get_curated_module_address(), abi) - return curated_module.META_REGISTRY() - - -def get_optional_meta_registry_address(default: str = ZERO_ADDRESS) -> str: - try: - return get_meta_registry_address() - except Exception: - return default From 0ebddaa705a9d0389e9394d55a3a42d76b35cb0e Mon Sep 17 00:00:00 2001 From: Eddort Date: Wed, 29 Apr 2026 20:33:43 +0200 Subject: [PATCH 09/15] refactor: hoodi srv3 and cmv2 --- ... => upgrade_2026_04_30_hoodi_srv4_cmv2.py} | 117 ++++------ ....py => test_2026_04_30_hoodi_srv4_cmv2.py} | 202 +++++++----------- 2 files changed, 129 insertions(+), 190 deletions(-) rename scripts/{upgrade_2026_04_X_hoodi_srv3_cmv2.py => upgrade_2026_04_30_hoodi_srv4_cmv2.py} (76%) rename tests/{test_2026_04_X_hoodi_srv3_cmv2.py => test_2026_04_30_hoodi_srv4_cmv2.py} (91%) diff --git a/scripts/upgrade_2026_04_X_hoodi_srv3_cmv2.py b/scripts/upgrade_2026_04_30_hoodi_srv4_cmv2.py similarity index 76% rename from scripts/upgrade_2026_04_X_hoodi_srv3_cmv2.py rename to scripts/upgrade_2026_04_30_hoodi_srv4_cmv2.py index 7caef221..26c70820 100644 --- a/scripts/upgrade_2026_04_X_hoodi_srv3_cmv2.py +++ b/scripts/upgrade_2026_04_30_hoodi_srv4_cmv2.py @@ -1,44 +1,13 @@ """ -TODO Vote 2026_04_14 +Vote 2026_04_30 -Uses deployed `UpgradeVoteScript` as the source of truth for both: -1. DG items returned by `getVoteItems()` -2. Immediate voting items returned by `getVotingVoteItems()` - -Replace the TODO values below after the Hoodi deployment. -""" - -import os - -from typing import Dict, List, Optional, Tuple - -from brownie import interface - -from utils.config import 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 - - -# ============================== Addresses =================================== -UPGRADE_VOTE_SCRIPT = "TODO: set deployed UpgradeVoteScript address" -HOODI_DG_ONLY_ENV = "HOODI_DG_ONLY" - - -# ============================= Description ================================== -DG_PROPOSAL_METADATA = "Upgrade Lido protocol contracts on Ethereum Hoodi testnet" -DG_SUBMISSION_DESCRIPTION = "1. Submit a Dual Governance proposal for the Lido protocol upgrade on Ethereum Hoodi testnet" -DG_IPFS_DESCRIPTION = """ -**Lido protocol upgrade on Ethereum Hoodi testnet** - -**Dual Governance proposal** -1. Submit a Dual Governance proposal for the Lido protocol upgrade on Ethereum Hoodi testnet. +1. Submit a Dual Governance proposal to activate Staking Router v4 + Curated Module v2 + Community Staking Module v3 +# ======================== Core ======================== 1.1. Call UpgradeTemplate.startUpgrade 1.2. Upgrade LidoLocator implementation -1.3. Upgrade StakingRouter implementation -1.4. Upgrade AccountingOracle implementation -1.5. Upgrade ValidatorsExitBusOracle 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 @@ -52,10 +21,11 @@ 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 VettedGate implementation +1.22. Upgrade CSVettedGate implementation 1.23. Upgrade and finalize Accounting v3 1.24. Upgrade and finalize FeeDistributor v3 1.25. Upgrade ExitPenalties implementation @@ -86,22 +56,23 @@ 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 initial epoch -1.60. Register CircuitBreaker pauser for CuratedModule +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 -""" -IMMEDIATE_VOTING_IPFS_DESCRIPTION = """**Immediate voting items** +# ======================== EasyTrack ======================== 2. Remove CSMSettleElStealingPenalty ET factory 3. Remove CSMSetVettedGateTree ET factory 4. Add UpdateStakingModuleShareLimits ET factory @@ -113,16 +84,34 @@ 10. Add ReportWithdrawalsForSlashedValidators CM ET factory 11. Add SettleGeneralDelayedPenalty CM ET factory 12. Add CreateOrUpdateOperatorGroup CM ET factory + """ -IPFS_DESCRIPTION = DG_IPFS_DESCRIPTION + "\n" + IMMEDIATE_VOTING_IPFS_DESCRIPTION +from typing import Dict, List, Optional, Tuple +from brownie import interface -# ================================ Main ====================================== +from utils.config import 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 -def is_dg_only_mode() -> bool: - return os.getenv(HOODI_DG_ONLY_ENV, "").lower() in ("1", "true", "yes", "on") +# ============================== Addresses =================================== +UPGRADE_VOTE_SCRIPT = "TODO: set deployed UpgradeVoteScript address" + + +# ============================= Description ================================== +DG_PROPOSAL_METADATA = "Activate Staking Router v4 + Curated Module v2 + Community Staking Module v3" +DG_SUBMISSION_DESCRIPTION = "1. Submit a Dual Governance proposal to activate Staking Router v4 + Curated Module v2 + Community Staking Module v3" +IPFS_DESCRIPTION = """ +1. **Activate Staking Router v4**, 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, identified DVT cluster setup, and triggerable withdrawals support. 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: @@ -130,11 +119,6 @@ def is_placeholder_vote_script_address(value: str) -> bool: return normalized in ("", "0x0000000000000000000000000000000000000000") or normalized.startswith("todo") -def get_ipfs_description(dg_only: Optional[bool] = None) -> str: - dg_only = is_dg_only_mode() if dg_only is None else dg_only - return DG_IPFS_DESCRIPTION if dg_only else IPFS_DESCRIPTION - - 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): @@ -153,10 +137,8 @@ def get_dg_items(upgrade_vote_script: Optional[str] = None) -> List[Tuple[str, s def get_vote_items( - dg_only: Optional[bool] = None, upgrade_vote_script: Optional[str] = None, ) -> Tuple[List[str], List[Tuple[str, str]]]: - dg_only = is_dg_only_mode() if dg_only is None else dg_only vote_script_address = (upgrade_vote_script or UPGRADE_VOTE_SCRIPT).strip() if is_placeholder_vote_script_address(vote_script_address): raise ValueError( @@ -175,11 +157,10 @@ def get_vote_items( vote_desc_items.append(DG_SUBMISSION_DESCRIPTION) call_script_items.append(dg_call_script[0]) - if not dg_only: - 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())) + 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 @@ -187,33 +168,27 @@ def get_vote_items( def start_vote( tx_params: Dict[str, str], silent: bool = False, - dg_only: Optional[bool] = None, upgrade_vote_script: Optional[str] = None, ): - dg_only = is_dg_only_mode() if dg_only is None else dg_only vote_desc_items, call_script_items = get_vote_items( - dg_only=dg_only, upgrade_vote_script=upgrade_vote_script, ) vote_items = bake_vote_items(list(vote_desc_items), list(call_script_items)) - ipfs_description = get_ipfs_description(dg_only=dg_only) - desc_ipfs = ( - calculate_vote_ipfs_description(ipfs_description) + calculate_vote_ipfs_description(IPFS_DESCRIPTION) if silent - else upload_vote_ipfs_description(ipfs_description) + 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) ) - if not dg_only: - vote_script_address = (upgrade_vote_script or UPGRADE_VOTE_SCRIPT).strip() - assert interface.UpgradeVoteScript(vote_script_address).isValidVoteScript( - vote_id, - DG_PROPOSAL_METADATA, - ) + 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 diff --git a/tests/test_2026_04_X_hoodi_srv3_cmv2.py b/tests/test_2026_04_30_hoodi_srv4_cmv2.py similarity index 91% rename from tests/test_2026_04_X_hoodi_srv3_cmv2.py rename to tests/test_2026_04_30_hoodi_srv4_cmv2.py index be4091e9..d377c783 100644 --- a/tests/test_2026_04_X_hoodi_srv3_cmv2.py +++ b/tests/test_2026_04_30_hoodi_srv4_cmv2.py @@ -34,8 +34,8 @@ # ============================================================================ # ============================== Import vote ================================= # ============================================================================ -from scripts.upgrade_2026_04_X_hoodi_srv3_cmv2 import ( - get_ipfs_description, +from scripts.upgrade_2026_04_30_hoodi_srv4_cmv2 import ( + IPFS_DESCRIPTION, start_vote, get_vote_items, get_dg_items, @@ -130,7 +130,6 @@ def _selector(signature: str) -> str: EXPECTED_DG_EVENTS_FROM_AGENT = 65 EXPECTED_DG_EVENTS_COUNT = 65 IPFS_DESCRIPTION_HASH = None -DG_ONLY_MODE = False UPGRADE_VOTE_SCRIPT_ENV = "HOODI_UPGRADE_VOTE_SCRIPT" @@ -194,35 +193,6 @@ def _raw_event_values(raw_event: dict) -> dict: return {item["name"]: item["value"] for item in raw_event["data"]} -def _group_raw_dg_events_from_receipt( - receipt: TransactionReceipt, - timelock: str, - admin_executor: str, -) -> list[list[dict]]: - events = tx_events_from_receipt(receipt) - - assert len(events) >= 1, "Unexpected raw DG events count" - assert ( - convert.to_address(events[-1]["address"]) == convert.to_address(timelock) - and events[-1]["name"] == "ProposalExecuted" - ), "Unexpected raw DG service event" - - groups = [] - current_group = [] - - for event in events[:-1]: - current_group.append(event) - - is_end_of_group = event["name"] == "Executed" and convert.to_address(event["address"]) == convert.to_address( - admin_executor - ) - if is_end_of_group: - groups.append(current_group) - current_group = [] - - return groups - - def _group_agent_dg_events_from_receipt(receipt: TransactionReceipt, timelock: str, agent: str) -> list[EventDict]: events = tx_events_from_receipt(receipt) @@ -457,11 +427,11 @@ def runtime_upgrade_context(): if ( _is_placeholder_address(upgrade_vote_script) or _is_placeholder_text(DG_PROPOSAL_METADATA) - or _is_placeholder_text(get_ipfs_description(dg_only=DG_ONLY_MODE)) + or _is_placeholder_text(IPFS_DESCRIPTION) ): pytest.skip( "Upgrade vote script address is missing. Set HOODI_UPGRADE_VOTE_SCRIPT " - "or UPGRADE_VOTE_SCRIPT in scripts/upgrade_2026_04_X_hoodi_srv3_cmv2.py first." + "or UPGRADE_VOTE_SCRIPT in scripts/upgrade_2026_04_30_hoodi_srv4_cmv2.py first." ) vote_script = interface.UpgradeVoteScript(upgrade_vote_script) @@ -630,19 +600,14 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g dual_governance = interface.DualGovernance(ctx["dual_governance"]) easy_track = interface.EasyTrack(ctx["easy_track"]) - vote_desc_items, call_script_items = get_vote_items( - dg_only=DG_ONLY_MODE, - upgrade_vote_script=ctx["upgrade_vote_script"], - ) + _, call_script_items = get_vote_items(upgrade_vote_script=ctx["upgrade_vote_script"]) dg_items = get_dg_items(ctx["upgrade_vote_script"]) upgrade_template = ctx["upgrade_template"] expected_vote_events_count = EXPECTED_VOTE_EVENTS_COUNT or len(call_script_items) expected_dg_events_from_agent = EXPECTED_DG_EVENTS_FROM_AGENT or len(dg_items) expected_dg_events_count = EXPECTED_DG_EVENTS_COUNT or len(dg_items) - expected_ipfs_description_hash = IPFS_DESCRIPTION_HASH or calculate_vote_ipfs_description( - get_ipfs_description(dg_only=DG_ONLY_MODE) - )["cid"] + expected_ipfs_description_hash = IPFS_DESCRIPTION_HASH or calculate_vote_ipfs_description(IPFS_DESCRIPTION)["cid"] old_easy_track_factories = [ ctx["old_csm_settle_el_stealing_penalty_factory"], ctx["old_csm_set_vetted_gate_tree_factory"], @@ -679,7 +644,6 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g vote_id, _ = start_vote( {"from": ldo_holder}, silent=True, - dg_only=DG_ONLY_MODE, upgrade_vote_script=ctx["upgrade_vote_script"], ) @@ -728,6 +692,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g assert expected_dg_proposal_id == timelock.getProposalsCount() + # 1. Submit a Dual Governance proposal to activate Staking Router v4 + Curated Module v2 + Community Staking Module v3 validate_dual_governance_submit_event( vote_events[0], proposal_id=expected_dg_proposal_id, @@ -737,22 +702,21 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g proposal_calls=dual_governance_proposal_calls, ) - # Validate EasyTrack factory removal/addition events - # 2. Remove old CSMSettleElStealingPenalty factory + # 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 old CSMSetVettedGateTree factory + # 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 factory + # 4. Add UpdateStakingModuleShareLimits ET factory validate_evmscript_factory_added_event( event=vote_events[3], p=EVMScriptFactoryAdded( @@ -768,7 +732,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g emitted_by=easy_track, ) - # 5. Add AllowConsolidationPair factory + # 5. Add AllowConsolidationPair ET factory validate_evmscript_factory_added_event( event=vote_events[4], p=EVMScriptFactoryAdded( @@ -778,7 +742,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g emitted_by=easy_track, ) - # 6. Add SetMerkleGateTree CSM factory + # 6. Add SetMerkleGateTree CSM ET factory validate_evmscript_factory_added_event( event=vote_events[5], p=EVMScriptFactoryAdded( @@ -788,7 +752,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g emitted_by=easy_track, ) - # 7. Add ReportWithdrawalsForSlashedValidators CSM factory + # 7. Add ReportWithdrawalsForSlashedValidators CSM ET factory validate_evmscript_factory_added_event( event=vote_events[6], p=EVMScriptFactoryAdded( @@ -798,7 +762,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g emitted_by=easy_track, ) - # 8. Add SettleGeneralDelayedPenalty CSM factory + # 8. Add SettleGeneralDelayedPenalty CSM ET factory validate_evmscript_factory_added_event( event=vote_events[7], p=EVMScriptFactoryAdded( @@ -808,7 +772,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g emitted_by=easy_track, ) - # 9. Add SetMerkleGateTree CM factory + # 9. Add SetMerkleGateTree CM ET factory validate_evmscript_factory_added_event( event=vote_events[8], p=EVMScriptFactoryAdded( @@ -818,7 +782,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g emitted_by=easy_track, ) - # 10. Add ReportWithdrawalsForSlashedValidators CM factory + # 10. Add ReportWithdrawalsForSlashedValidators CM ET factory validate_evmscript_factory_added_event( event=vote_events[9], p=EVMScriptFactoryAdded( @@ -828,7 +792,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g emitted_by=easy_track, ) - # 11. Add SettleGeneralDelayedPenalty CM factory + # 11. Add SettleGeneralDelayedPenalty CM ET factory validate_evmscript_factory_added_event( event=vote_events[10], p=EVMScriptFactoryAdded( @@ -838,7 +802,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g emitted_by=easy_track, ) - # 12. Add CreateOrUpdateOperatorGroup CM factory + # 12. Add CreateOrUpdateOperatorGroup CM ET factory validate_evmscript_factory_added_event( event=vote_events[11], p=EVMScriptFactoryAdded( @@ -887,15 +851,15 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g # === DG EXECUTION EVENTS VALIDATION === - # 1. Call UpgradeTemplate.startUpgrade + # 1.1. Call UpgradeTemplate.startUpgrade validate_events_chain([e.name for e in dg_events[0]], ["LogScriptCall", "UpgradeStarted"]) upgrade_started_event = _single_event(dg_events[0], "UpgradeStarted") _assert_emitted_by(upgrade_started_event, upgrade_template) - # 2. Upgrade LidoLocator proxy + # 1.2. Upgrade LidoLocator implementation validate_proxy_upgrade_event(dg_events[1], ctx["lido_locator_impl"], emitted_by=ctx["lido_locator"]) - # 3. Upgrade and finalize StakingRouter + # 1.3. Upgrade and finalize StakingRouter validate_proxy_upgrade_event( dg_events[2], ctx["staking_router_impl"], @@ -937,7 +901,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g assert initialized_event["version"] == 4 _assert_emitted_by(initialized_event, ctx["staking_router"]) - # 4. Upgrade and finalize AccountingOracle + # 1.4. Upgrade and finalize AccountingOracle validate_proxy_upgrade_event( dg_events[3], ctx["accounting_oracle_impl"], @@ -973,7 +937,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g ], ) - # 5. Upgrade and finalize ValidatorsExitBusOracle + # 1.5. Upgrade and finalize ValidatorsExitBusOracle validate_proxy_upgrade_event( dg_events[4], ctx["validators_exit_bus_oracle_impl"], @@ -1023,10 +987,10 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g 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"]) - # 6. Upgrade Accounting implementation + # 1.6. Upgrade Accounting implementation validate_proxy_upgrade_event(dg_events[5], ctx["accounting_impl"], emitted_by=ctx["accounting"]) - # 7. Upgrade and finalize WithdrawalVault + # 1.7. Upgrade WithdrawalVault implementation validate_proxy_upgrade_event( dg_events[6], ctx["withdrawal_vault_impl"], @@ -1040,7 +1004,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g events_chain=["LogScriptCall", "Upgraded", "ContractVersionSet"], ) - # 8. Grant APP_MANAGER_ROLE on Kernel to Agent + # 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"]) @@ -1049,14 +1013,14 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g assert set_permission_event["allowed"] is True _assert_emitted_by(set_permission_event, ctx["acl"]) - # 9. Set new Lido implementation in Kernel + # 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"]) - # 10. Revoke APP_MANAGER_ROLE on Kernel from Agent + # 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"]) @@ -1065,7 +1029,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g assert set_permission_event["allowed"] is False _assert_emitted_by(set_permission_event, ctx["acl"]) - # 11. Grant BUFFER_RESERVE_MANAGER_ROLE on Lido and transfer permission manager to Agent + # 1.11. Create and grant Aragon BUFFER_RESERVE_MANAGER_ROLE to the AGENT validate_events_chain( [e.name for e in dg_events[10]], ["LogScriptCall", "SetPermission", "ChangePermissionManager"], @@ -1082,10 +1046,10 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g assert convert.to_address(change_permission_manager_event["manager"]) == convert.to_address(ctx["agent"]) _assert_emitted_by(change_permission_manager_event, ctx["acl"]) - # 12. Finalize Lido contract version + # 1.12. Call finalizeUpgrade_v4 on Lido validate_contract_version_set_event(dg_events[11], LIDO_CONTRACT_VERSION, emitted_by=ctx["lido"]) - # 13. Grant STAKING_MODULE_SHARE_MANAGE_ROLE to EasyTrack executor + # 1.13. Grant STAKING_MODULE_SHARE_MANAGE_ROLE to EasyTrack executor validate_role_grant_event( dg_events[12], STAKING_MODULE_SHARE_MANAGE_ROLE, @@ -1094,7 +1058,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g emitted_by=ctx["staking_router"], ) - # 14. Revoke STAKING_MODULE_UNVETTING_ROLE from old DSM + # 1.14. Revoke STAKING_MODULE_UNVETTING_ROLE from old DSM validate_role_revoke_event( dg_events[13], STAKING_MODULE_UNVETTING_ROLE, @@ -1103,7 +1067,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g emitted_by=ctx["staking_router"], ) - # 15. Grant STAKING_MODULE_UNVETTING_ROLE to new DSM + # 1.15. Grant STAKING_MODULE_UNVETTING_ROLE to new DSM validate_role_grant_event( dg_events[14], STAKING_MODULE_UNVETTING_ROLE, @@ -1112,7 +1076,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g emitted_by=ctx["staking_router"], ) - # 16. Grant TW_EXIT_LIMIT_MANAGER_ROLE to Agent + # 1.16. Grant TW_EXIT_LIMIT_MANAGER_ROLE to Agent on TWGateway validate_role_grant_event( dg_events[15], TW_EXIT_LIMIT_MANAGER_ROLE, @@ -1121,7 +1085,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g emitted_by=ctx["triggerable_withdrawals_gateway"], ) - # 17. Set TWG exit limits + # 1.17. Set TWGateway exit request limits validate_events_chain( [e.name for e in dg_events[16]], ["LogScriptCall", "ExitRequestsLimitSet"], @@ -1132,7 +1096,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g assert exit_requests_limit_set_event["frameDurationInSec"] == TW_FRAME_DURATION_IN_SEC _assert_emitted_by(exit_requests_limit_set_event, ctx["triggerable_withdrawals_gateway"]) - # 18. Register CircuitBreaker pauser for ConsolidationGateway + # 1.18. Register CircuitBreaker pauser for ConsolidationGateway validate_circuit_breaker_registration_event( dg_events[17], circuit_breaker=ctx["circuit_breaker"], @@ -1140,7 +1104,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g pauser=ctx["consolidation_gateway_pauser"], ) - # 19. Upgrade and initialize CSM + # 1.19. Upgrade and finalize CSM v3 validate_proxy_upgrade_event( dg_events[18], ctx["csm_impl"], @@ -1151,7 +1115,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g assert initialized_event["version"] == 3 _assert_emitted_by(initialized_event, ctx["csm"]) - # 20. Upgrade and initialize CSParametersRegistry + # 1.20. Upgrade and finalize ParametersRegistry v3 validate_proxy_upgrade_event( dg_events[19], ctx["cs_parameters_registry_impl"], @@ -1162,7 +1126,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g assert initialized_event["version"] == 3 _assert_emitted_by(initialized_event, ctx["cs_parameters_registry"]) - # 21. Upgrade and finalize CSFeeOracle + # 1.21. Upgrade and finalize FeeOracle v3 validate_proxy_upgrade_event( dg_events[20], ctx["cs_fee_oracle_impl"], @@ -1183,10 +1147,10 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g events_chain=["LogScriptCall", "Upgraded", "ConsensusVersionSet", "ContractVersionSet"], ) - # 22. Upgrade CSVettedGate + # 1.22. Upgrade CSVettedGate implementation validate_proxy_upgrade_event(dg_events[21], ctx["cs_vetted_gate_impl"], emitted_by=ctx["cs_vetted_gate"]) - # 23. Upgrade and initialize CSAccounting + # 1.23. Upgrade and finalize Accounting v3 validate_proxy_upgrade_event( dg_events[22], ctx["cs_accounting_impl"], @@ -1197,7 +1161,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g assert initialized_event["version"] == 3 _assert_emitted_by(initialized_event, ctx["cs_accounting"]) - # 24. Upgrade and initialize CSFeeDistributor + # 1.24. Upgrade and finalize FeeDistributor v3 validate_proxy_upgrade_event( dg_events[23], ctx["cs_fee_distributor_impl"], @@ -1208,19 +1172,19 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g assert initialized_event["version"] == 3 _assert_emitted_by(initialized_event, ctx["cs_fee_distributor"]) - # 25. Upgrade CSExitPenalties + # 1.25. Upgrade ExitPenalties implementation validate_proxy_upgrade_event(dg_events[24], ctx["cs_exit_penalties_impl"], emitted_by=ctx["cs_exit_penalties"]) - # 26. Upgrade CSValidatorStrikes + # 1.26. Upgrade ValidatorStrikes implementation validate_proxy_upgrade_event(dg_events[25], ctx["cs_validator_strikes_impl"], emitted_by=ctx["cs_validator_strikes"]) - # 27. Set CSM ejector + # 1.27. Point ValidatorStrikes to the new Ejector validate_events_chain([e.name for e in dg_events[26]], ["LogScriptCall", "EjectorSet"]) ejector_set_event = _single_event(dg_events[26], "EjectorSet") assert convert.to_address(ejector_set_event["ejector"]) == convert.to_address(ctx["csm_ejector"]) _assert_emitted_by(ejector_set_event, ctx["cs_validator_strikes"]) - # 28. Revoke REPORT_EL_REWARDS_STEALING_PENALTY_ROLE + # 1.28. Revoke REPORT_EL_REWARDS_STEALING_PENALTY_ROLE validate_role_revoke_event( dg_events[27], REPORT_EL_REWARDS_STEALING_PENALTY_ROLE, @@ -1229,7 +1193,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g emitted_by=ctx["csm"], ) - # 29. Grant REPORT_GENERAL_DELAYED_PENALTY_ROLE + # 1.29. Grant REPORT_GENERAL_DELAYED_PENALTY_ROLE validate_role_grant_event( dg_events[28], REPORT_GENERAL_DELAYED_PENALTY_ROLE, @@ -1238,7 +1202,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g emitted_by=ctx["csm"], ) - # 30. Revoke SETTLE_EL_REWARDS_STEALING_PENALTY_ROLE + # 1.30. Revoke SETTLE_EL_REWARDS_STEALING_PENALTY_ROLE validate_role_revoke_event( dg_events[29], SETTLE_EL_REWARDS_STEALING_PENALTY_ROLE, @@ -1247,7 +1211,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g emitted_by=ctx["csm"], ) - # 31. Grant SETTLE_GENERAL_DELAYED_PENALTY_ROLE + # 1.31. Grant SETTLE_GENERAL_DELAYED_PENALTY_ROLE validate_role_grant_event( dg_events[30], SETTLE_GENERAL_DELAYED_PENALTY_ROLE, @@ -1256,7 +1220,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g emitted_by=ctx["csm"], ) - # 32. Revoke VERIFIER_ROLE from old verifier + # 1.32. Revoke VERIFIER_ROLE from old verifier validate_role_revoke_event( dg_events[31], VERIFIER_ROLE, @@ -1265,7 +1229,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g emitted_by=ctx["csm"], ) - # 33. Grant VERIFIER_ROLE to verifier v3 + # 1.33. Grant VERIFIER_ROLE to new verifier validate_role_grant_event( dg_events[32], VERIFIER_ROLE, @@ -1274,7 +1238,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g emitted_by=ctx["csm"], ) - # 34. Grant REPORT_REGULAR_WITHDRAWN_VALIDATORS_ROLE + # 1.34. Grant REPORT_REGULAR_WITHDRAWN_VALIDATORS_ROLE to VerifierV3 validate_role_grant_event( dg_events[33], REPORT_REGULAR_WITHDRAWN_VALIDATORS_ROLE, @@ -1283,7 +1247,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g emitted_by=ctx["csm"], ) - # 35. Grant REPORT_SLASHED_WITHDRAWN_VALIDATORS_ROLE + # 1.35. Grant REPORT_SLASHED_WITHDRAWN_VALIDATORS_ROLE to Easy Track validate_role_grant_event( dg_events[34], REPORT_SLASHED_WITHDRAWN_VALIDATORS_ROLE, @@ -1292,7 +1256,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g emitted_by=ctx["csm"], ) - # 36. Revoke CREATE_NODE_OPERATOR_ROLE from old permissionless gate + # 1.36. Revoke CREATE_NODE_OPERATOR_ROLE from old PermissionlessGate validate_role_revoke_event( dg_events[35], CREATE_NODE_OPERATOR_ROLE, @@ -1301,7 +1265,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g emitted_by=ctx["csm"], ) - # 37. Grant CREATE_NODE_OPERATOR_ROLE to new permissionless gate + # 1.37. Grant CREATE_NODE_OPERATOR_ROLE to new PermissionlessGate validate_role_grant_event( dg_events[36], CREATE_NODE_OPERATOR_ROLE, @@ -1310,7 +1274,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g emitted_by=ctx["csm"], ) - # 38. Revoke START_REFERRAL_SEASON_ROLE from Agent + # 1.38. Revoke START_REFERRAL_SEASON_ROLE validate_role_revoke_event( dg_events[37], START_REFERRAL_SEASON_ROLE, @@ -1319,7 +1283,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g emitted_by=ctx["cs_vetted_gate"], ) - # 39. Revoke END_REFERRAL_SEASON_ROLE from CSM committee + # 1.39. Revoke END_REFERRAL_SEASON_ROLE validate_role_revoke_event( dg_events[38], END_REFERRAL_SEASON_ROLE, @@ -1328,7 +1292,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g emitted_by=ctx["cs_vetted_gate"], ) - # 40. Register CircuitBreaker pauser for CSM new verifier + # 1.40. Register CircuitBreaker pauser for CSM new verifier validate_circuit_breaker_registration_event( dg_events[39], circuit_breaker=ctx["circuit_breaker"], @@ -1336,7 +1300,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g pauser=ctx["csm_committee"], ) - # 41. Register CircuitBreaker pauser for CSM ejector + # 1.41. Register CircuitBreaker pauser for CSM Ejector validate_circuit_breaker_registration_event( dg_events[40], circuit_breaker=ctx["circuit_breaker"], @@ -1344,7 +1308,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g pauser=ctx["csm_committee"], ) - # 42. Register CircuitBreaker pauser for identified DVT cluster gate + # 1.42. Register CircuitBreaker pauser for CSM identified DVT cluster gate validate_circuit_breaker_registration_event( dg_events[41], circuit_breaker=ctx["circuit_breaker"], @@ -1352,7 +1316,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g pauser=ctx["csm_committee"], ) - # 43. Grant CREATE_NODE_OPERATOR_ROLE to identified DVT cluster gate + # 1.43. Grant CREATE_NODE_OPERATOR_ROLE to identified DVT cluster gate validate_role_grant_event( dg_events[42], CREATE_NODE_OPERATOR_ROLE, @@ -1361,7 +1325,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g emitted_by=ctx["csm"], ) - # 44. Grant SET_BOND_CURVE_ROLE to identified DVT cluster gate + # 1.44. Grant SET_BOND_CURVE_ROLE to identified DVT cluster gate validate_role_grant_event( dg_events[43], SET_BOND_CURVE_ROLE, @@ -1370,7 +1334,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g emitted_by=ctx["cs_accounting"], ) - # 45. Grant MANAGE_BOND_CURVES_ROLE to identified DVT cluster curve setup + # 1.45. Grant MANAGE_BOND_CURVES_ROLE to identified DVT cluster curve setup validate_role_grant_event( dg_events[44], MANAGE_BOND_CURVES_ROLE, @@ -1379,7 +1343,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g emitted_by=ctx["cs_accounting"], ) - # 46. Grant MANAGE_CURVE_PARAMETERS_ROLE to identified DVT cluster curve setup + # 1.46. Grant MANAGE_CURVE_PARAMETERS_ROLE to identified DVT cluster curve setup validate_role_grant_event( dg_events[45], MANAGE_CURVE_PARAMETERS_ROLE, @@ -1388,7 +1352,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g emitted_by=ctx["cs_parameters_registry"], ) - # 47. Execute identified DVT cluster curve setup + # 1.47. Execute identified DVT cluster curve setup validate_events_chain( [e.name for e in dg_events[46]], [ @@ -1459,7 +1423,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g assert bond_curve_deployed_event["curveId"] == ctx["identified_dvt_cluster_bond_curve_id"] _assert_emitted_by(bond_curve_deployed_event, ctx["identified_dvt_cluster_curve_setup"]) - # 48. Grant MANAGE_GENERAL_PENALTIES_AND_CHARGES_ROLE + # 1.48. Grant MANAGE_GENERAL_PENALTIES_AND_CHARGES_ROLE to CSM Committee validate_role_grant_event( dg_events[47], MANAGE_GENERAL_PENALTIES_AND_CHARGES_ROLE, @@ -1468,7 +1432,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g emitted_by=ctx["cs_parameters_registry"], ) - # 49. Revoke REQUEST_BURN_SHARES_ROLE from CSAccounting + # 1.49. Revoke REQUEST_BURN_SHARES_ROLE from CSM Accounting validate_role_revoke_event( dg_events[48], REQUEST_BURN_SHARES_ROLE, @@ -1477,7 +1441,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g emitted_by=ctx["burner"], ) - # 50. Grant REQUEST_BURN_MY_STETH_ROLE to CSAccounting + # 1.50. Grant REQUEST_BURN_MY_STETH_ROLE to CSM Accounting validate_role_grant_event( dg_events[49], REQUEST_BURN_MY_STETH_ROLE, @@ -1486,7 +1450,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g emitted_by=ctx["burner"], ) - # 51. Revoke ADD_FULL_WITHDRAWAL_REQUEST_ROLE from old CSM ejector + # 1.51. Revoke TWG full-withdrawal role from old Ejector validate_role_revoke_event( dg_events[50], ADD_FULL_WITHDRAWAL_REQUEST_ROLE, @@ -1495,7 +1459,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g emitted_by=ctx["triggerable_withdrawals_gateway"], ) - # 52. Grant ADD_FULL_WITHDRAWAL_REQUEST_ROLE to CSM ejector + # 1.52. Grant TWG full-withdrawal role to new Ejector validate_role_grant_event( dg_events[51], ADD_FULL_WITHDRAWAL_REQUEST_ROLE, @@ -1504,10 +1468,10 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g emitted_by=ctx["triggerable_withdrawals_gateway"], ) - # 53. Add curated-onchain-v2 module + # 1.53. Add Curated module to StakingRouter validate_module_add(dg_events[52], ctx["curated_module_item"], emitted_by=ctx["staking_router"], sender=ctx["agent"]) - # 54. Grant REQUEST_BURN_MY_STETH_ROLE to curated accounting + # 1.54. Grant REQUEST_BURN_MY_STETH_ROLE to Curated Accounting validate_role_grant_event( dg_events[53], REQUEST_BURN_MY_STETH_ROLE, @@ -1516,7 +1480,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g emitted_by=ctx["burner"], ) - # 55. Grant ADD_FULL_WITHDRAWAL_REQUEST_ROLE to curated ejector + # 1.55. Grant TWG full-withdrawal role to Curated Ejector validate_role_grant_event( dg_events[54], ADD_FULL_WITHDRAWAL_REQUEST_ROLE, @@ -1525,7 +1489,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g emitted_by=ctx["triggerable_withdrawals_gateway"], ) - # 56. Grant RESUME_ROLE on curated module to Agent + # 1.56. Grant RESUME_ROLE to agent on Curated module validate_role_grant_event( dg_events[55], RESUME_ROLE, @@ -1534,12 +1498,12 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g emitted_by=ctx["curated_module"], ) - # 57. Resume curated module + # 1.57. Resume Curated module validate_events_chain([e.name for e in dg_events[56]], ["LogScriptCall", "Resumed"]) resumed_event = _single_event(dg_events[56], "Resumed") _assert_emitted_by(resumed_event, ctx["curated_module"]) - # 58. Revoke RESUME_ROLE from Agent + # 1.58. Revoke RESUME_ROLE from agent on Curated module validate_role_revoke_event( dg_events[57], RESUME_ROLE, @@ -1548,14 +1512,14 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g emitted_by=ctx["curated_module"], ) - # 59. Set curated HashConsensus frame config + # 1.59. Update Curated HashConsensus frame config validate_events_chain([e.name for e in dg_events[58]], ["LogScriptCall", "FrameConfigSet"]) frame_config_set_event = _single_event(dg_events[58], "FrameConfigSet") assert frame_config_set_event["newInitialEpoch"] == CURATED_INITIAL_EPOCH assert frame_config_set_event["newEpochsPerFrame"] == CURATED_EPOCHS_PER_FRAME _assert_emitted_by(frame_config_set_event, ctx["curated_hash_consensus"]) - # 60. Register CircuitBreaker pauser for Curated module + # 1.60. Register CircuitBreaker pauser for Curated module validate_circuit_breaker_registration_event( dg_events[59], circuit_breaker=ctx["circuit_breaker"], @@ -1563,7 +1527,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g pauser=ctx["curated_circuit_breaker_pauser"], ) - # 61. Register CircuitBreaker pauser for Curated accounting + # 1.61. Register CircuitBreaker pauser for Curated Accounting validate_circuit_breaker_registration_event( dg_events[60], circuit_breaker=ctx["circuit_breaker"], @@ -1571,7 +1535,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g pauser=ctx["curated_circuit_breaker_pauser"], ) - # 62. Register CircuitBreaker pauser for Curated fee oracle + # 1.62. Register CircuitBreaker pauser for Curated FeeOracle validate_circuit_breaker_registration_event( dg_events[61], circuit_breaker=ctx["circuit_breaker"], @@ -1579,7 +1543,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g pauser=ctx["curated_circuit_breaker_pauser"], ) - # 63. Register CircuitBreaker pauser for Curated verifier + # 1.63. Register CircuitBreaker pauser for Curated Verifier validate_circuit_breaker_registration_event( dg_events[62], circuit_breaker=ctx["circuit_breaker"], @@ -1587,7 +1551,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g pauser=ctx["curated_circuit_breaker_pauser"], ) - # 64. Register CircuitBreaker pauser for Curated ejector + # 1.64. Register CircuitBreaker pauser for Curated Ejector validate_circuit_breaker_registration_event( dg_events[63], circuit_breaker=ctx["circuit_breaker"], @@ -1595,7 +1559,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g pauser=ctx["curated_circuit_breaker_pauser"], ) - # 65. Call UpgradeTemplate.finishUpgrade + # 1.65. Call UpgradeTemplate.finishUpgrade validate_events_chain([e.name for e in dg_events[64]], ["LogScriptCall", "UpgradeFinished", "ScriptResult", "Executed"]) upgrade_finished_event = _single_event(dg_events[64], "UpgradeFinished") _assert_emitted_by(upgrade_finished_event, upgrade_template) From c612c1b6c58d8220546ff59b2c9350cf31c14326 Mon Sep 17 00:00:00 2001 From: Eddort Date: Thu, 30 Apr 2026 07:55:41 +0200 Subject: [PATCH 10/15] refactor: srv4 to srv3 --- ...srv4_cmv2.py => upgrade_2026_04_30_hoodi_srv3_cmv2.py} | 8 ++++---- ...di_srv4_cmv2.py => test_2026_04_30_hoodi_srv3_cmv2.py} | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) rename scripts/{upgrade_2026_04_30_hoodi_srv4_cmv2.py => upgrade_2026_04_30_hoodi_srv3_cmv2.py} (97%) rename tests/{test_2026_04_30_hoodi_srv4_cmv2.py => test_2026_04_30_hoodi_srv3_cmv2.py} (99%) diff --git a/scripts/upgrade_2026_04_30_hoodi_srv4_cmv2.py b/scripts/upgrade_2026_04_30_hoodi_srv3_cmv2.py similarity index 97% rename from scripts/upgrade_2026_04_30_hoodi_srv4_cmv2.py rename to scripts/upgrade_2026_04_30_hoodi_srv3_cmv2.py index 26c70820..de3794fa 100644 --- a/scripts/upgrade_2026_04_30_hoodi_srv4_cmv2.py +++ b/scripts/upgrade_2026_04_30_hoodi_srv3_cmv2.py @@ -1,7 +1,7 @@ """ Vote 2026_04_30 -1. Submit a Dual Governance proposal to activate Staking Router v4 + Curated Module v2 + Community Staking Module v3 +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 @@ -103,10 +103,10 @@ # ============================= Description ================================== -DG_PROPOSAL_METADATA = "Activate Staking Router v4 + Curated Module v2 + Community Staking Module v3" -DG_SUBMISSION_DESCRIPTION = "1. Submit a Dual Governance proposal to activate Staking Router v4 + Curated Module v2 + Community Staking Module v3" +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 v4**, including protocol contract upgrades and Dual Governance execution setup. Items 1.1-1.18. +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, identified DVT cluster setup, and triggerable withdrawals support. 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. diff --git a/tests/test_2026_04_30_hoodi_srv4_cmv2.py b/tests/test_2026_04_30_hoodi_srv3_cmv2.py similarity index 99% rename from tests/test_2026_04_30_hoodi_srv4_cmv2.py rename to tests/test_2026_04_30_hoodi_srv3_cmv2.py index d377c783..4948e89e 100644 --- a/tests/test_2026_04_30_hoodi_srv4_cmv2.py +++ b/tests/test_2026_04_30_hoodi_srv3_cmv2.py @@ -34,7 +34,7 @@ # ============================================================================ # ============================== Import vote ================================= # ============================================================================ -from scripts.upgrade_2026_04_30_hoodi_srv4_cmv2 import ( +from scripts.upgrade_2026_04_30_hoodi_srv3_cmv2 import ( IPFS_DESCRIPTION, start_vote, get_vote_items, @@ -431,7 +431,7 @@ def runtime_upgrade_context(): ): pytest.skip( "Upgrade vote script address is missing. Set HOODI_UPGRADE_VOTE_SCRIPT " - "or UPGRADE_VOTE_SCRIPT in scripts/upgrade_2026_04_30_hoodi_srv4_cmv2.py first." + "or UPGRADE_VOTE_SCRIPT in scripts/upgrade_2026_04_30_hoodi_srv3_cmv2.py first." ) vote_script = interface.UpgradeVoteScript(upgrade_vote_script) @@ -692,7 +692,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g assert expected_dg_proposal_id == timelock.getProposalsCount() - # 1. Submit a Dual Governance proposal to activate Staking Router v4 + Curated Module v2 + Community Staking Module v3 + # 1. Submit a Dual Governance proposal to activate Staking Router v3 + Curated Module v2 + Community Staking Module v3 validate_dual_governance_submit_event( vote_events[0], proposal_id=expected_dg_proposal_id, From fa1099cb8d41c8ee326628b57e57fbda5a5c4872 Mon Sep 17 00:00:00 2001 From: skhomuti Date: Thu, 30 Apr 2026 11:05:35 +0500 Subject: [PATCH 11/15] fixes little inconsistencies --- scripts/upgrade_2026_04_30_hoodi_srv3_cmv2.py | 2 +- tests/test_2026_04_30_hoodi_srv3_cmv2.py | 41 +++---------------- 2 files changed, 6 insertions(+), 37 deletions(-) diff --git a/scripts/upgrade_2026_04_30_hoodi_srv3_cmv2.py b/scripts/upgrade_2026_04_30_hoodi_srv3_cmv2.py index de3794fa..d022f5e6 100644 --- a/scripts/upgrade_2026_04_30_hoodi_srv3_cmv2.py +++ b/scripts/upgrade_2026_04_30_hoodi_srv3_cmv2.py @@ -107,7 +107,7 @@ 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, identified DVT cluster setup, and triggerable withdrawals support. Items 1.19-1.52. +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. diff --git a/tests/test_2026_04_30_hoodi_srv3_cmv2.py b/tests/test_2026_04_30_hoodi_srv3_cmv2.py index 4948e89e..39fde5b2 100644 --- a/tests/test_2026_04_30_hoodi_srv3_cmv2.py +++ b/tests/test_2026_04_30_hoodi_srv3_cmv2.py @@ -110,6 +110,7 @@ def _selector(signature: str) -> str: TW_EXITS_PER_FRAME = 1 TW_FRAME_DURATION_IN_SEC = 240 CURATED_MODULE_ID = 5 +# TODO update CURATED_INITIAL_EPOCH = 47480 CURATED_EPOCHS_PER_FRAME = 1575 IDVT_BOND_CURVE = [[1, 1500000000000000000], [2, 500000000000000000]] @@ -221,34 +222,6 @@ def _group_agent_dg_events_from_receipt(receipt: TransactionReceipt, timelock: s return [EventDict(group) for group in groups] -def _group_raw_agent_dg_events_from_receipt(receipt: TransactionReceipt, timelock: str, agent: str) -> list[list[dict]]: - events = tx_events_from_receipt(receipt) - - assert len(events) >= 1, "Unexpected raw DG events count" - assert ( - convert.to_address(events[-1]["address"]) == convert.to_address(timelock) - and events[-1]["name"] == "ProposalExecuted" - ), "Unexpected raw DG 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 raw DG events chain" - current_group.append(event) - - return groups - - def validate_proxy_upgrade_event( event: EventDict, implementation: str, @@ -511,6 +484,7 @@ def runtime_upgrade_context(): "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"], @@ -818,6 +792,7 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g # ======================= Execute DG Proposal ============================= # ========================================================================= if expected_dg_proposal_id is not None: + 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"]: if details["status"] == PROPOSAL_STATUS["submitted"]: @@ -839,15 +814,9 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g timelock=EMERGENCY_PROTECTED_TIMELOCK, agent=agent.address, ) - raw_dg_events = _group_raw_agent_dg_events_from_receipt( - dg_tx, - timelock=EMERGENCY_PROTECTED_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 - assert len(raw_dg_events) == expected_dg_events_count # === DG EXECUTION EVENTS VALIDATION === @@ -1135,8 +1104,8 @@ def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger, dual_g ) validate_consensus_version_set_event( dg_events[20], - 4, - 3, + ctx["cs_fee_oracle_consensus_version"], + initial_cs_fee_oracle_consensus_version, emitted_by=ctx["cs_fee_oracle"], events_chain=["LogScriptCall", "Upgraded", "ConsensusVersionSet", "ContractVersionSet"], ) From ccd7bd99ba2f48e2dd2ba72136a00596f63db44b Mon Sep 17 00:00:00 2001 From: skhomuti Date: Thu, 30 Apr 2026 13:52:38 +0500 Subject: [PATCH 12/15] adjust expected initial epoch for CMv2 --- tests/test_2026_04_30_hoodi_srv3_cmv2.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/test_2026_04_30_hoodi_srv3_cmv2.py b/tests/test_2026_04_30_hoodi_srv3_cmv2.py index 39fde5b2..fa35f9f1 100644 --- a/tests/test_2026_04_30_hoodi_srv3_cmv2.py +++ b/tests/test_2026_04_30_hoodi_srv3_cmv2.py @@ -110,8 +110,7 @@ def _selector(signature: str) -> str: TW_EXITS_PER_FRAME = 1 TW_FRAME_DURATION_IN_SEC = 240 CURATED_MODULE_ID = 5 -# TODO update -CURATED_INITIAL_EPOCH = 47480 +CURATED_INITIAL_EPOCH = 93833 CURATED_EPOCHS_PER_FRAME = 1575 IDVT_BOND_CURVE = [[1, 1500000000000000000], [2, 500000000000000000]] IDVT_KEY_REMOVAL_CHARGE = 10000000000000000 From 276aa8b73e6d340d047813bed1af5c49cd7ada44 Mon Sep 17 00:00:00 2001 From: Eddort Date: Thu, 30 Apr 2026 16:01:06 +0200 Subject: [PATCH 13/15] fix: update VALIDATORS_EXIT_BUS_MAX_EXIT_BALANCE_ETH to correct value --- tests/test_2026_04_30_hoodi_srv3_cmv2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_2026_04_30_hoodi_srv3_cmv2.py b/tests/test_2026_04_30_hoodi_srv3_cmv2.py index 39fde5b2..884caf45 100644 --- a/tests/test_2026_04_30_hoodi_srv3_cmv2.py +++ b/tests/test_2026_04_30_hoodi_srv3_cmv2.py @@ -101,7 +101,7 @@ def _selector(signature: str) -> str: VEBO_CONSENSUS_VERSION = 5 VEBO_PREV_CONSENSUS_VERSION = 4 VEBO_MAX_VALIDATORS_PER_REPORT = 600 -VALIDATORS_EXIT_BUS_MAX_EXIT_BALANCE_ETH = 416000 +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 From ab832520019dbdc8b81f478fcdcaa01ed8f42666 Mon Sep 17 00:00:00 2001 From: Eddort Date: Thu, 30 Apr 2026 16:09:21 +0200 Subject: [PATCH 14/15] feat: add address --- scripts/upgrade_2026_04_30_hoodi_srv3_cmv2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/upgrade_2026_04_30_hoodi_srv3_cmv2.py b/scripts/upgrade_2026_04_30_hoodi_srv3_cmv2.py index d022f5e6..da9f45c2 100644 --- a/scripts/upgrade_2026_04_30_hoodi_srv3_cmv2.py +++ b/scripts/upgrade_2026_04_30_hoodi_srv3_cmv2.py @@ -99,7 +99,7 @@ # ============================== Addresses =================================== -UPGRADE_VOTE_SCRIPT = "TODO: set deployed UpgradeVoteScript address" +UPGRADE_VOTE_SCRIPT = "0x256c4eece96b79584A705D8dbFBf29cC876b41b6" # ============================= Description ================================== From e91e87ecd4df3c37ae087a218b898b9ec1f5f75f Mon Sep 17 00:00:00 2001 From: skhomuti Date: Thu, 30 Apr 2026 19:10:34 +0500 Subject: [PATCH 15/15] set correct address for UPGRADE_VOTE_SCRIPT --- scripts/upgrade_2026_04_30_hoodi_srv3_cmv2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/upgrade_2026_04_30_hoodi_srv3_cmv2.py b/scripts/upgrade_2026_04_30_hoodi_srv3_cmv2.py index da9f45c2..912a61db 100644 --- a/scripts/upgrade_2026_04_30_hoodi_srv3_cmv2.py +++ b/scripts/upgrade_2026_04_30_hoodi_srv3_cmv2.py @@ -99,7 +99,7 @@ # ============================== Addresses =================================== -UPGRADE_VOTE_SCRIPT = "0x256c4eece96b79584A705D8dbFBf29cC876b41b6" +UPGRADE_VOTE_SCRIPT = "0xaC83987948dB29c54b91B9a3Bd7a5cA99fA7F1D1" # ============================= Description ==================================