Skip to content

Commit 986ff00

Browse files
authored
Merge pull request #623 from lidofinance/master
Update feat/next-vote with master
2 parents 724ee6c + 41178e6 commit 986ff00

2 files changed

Lines changed: 1755 additions & 0 deletions

File tree

Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
"""
2+
Vote 2026_04_30
3+
4+
1. Submit a Dual Governance proposal to activate Staking Router v3 + Curated Module v2 + Community Staking Module v3
5+
# ======================== Core ========================
6+
1.1. Call UpgradeTemplate.startUpgrade
7+
1.2. Upgrade LidoLocator implementation
8+
1.3. Upgrade and finalize StakingRouter
9+
1.4. Upgrade and finalize AccountingOracle
10+
1.5. Upgrade and finalize ValidatorsExitBusOracle
11+
1.6. Upgrade Accounting implementation
12+
1.7. Upgrade WithdrawalVault implementation
13+
1.8. Grant Aragon APP_MANAGER_ROLE to the AGENT
14+
1.9. Set Lido implementation in Kernel
15+
1.10. Revoke Aragon APP_MANAGER_ROLE from the AGENT
16+
1.11. Create and grant Aragon BUFFER_RESERVE_MANAGER_ROLE to the AGENT
17+
1.12. Call finalizeUpgrade_v4 on Lido
18+
1.13. Grant STAKING_MODULE_SHARE_MANAGE_ROLE to EasyTrack executor
19+
1.14. Revoke STAKING_MODULE_UNVETTING_ROLE from old DSM
20+
1.15. Grant STAKING_MODULE_UNVETTING_ROLE to new DSM
21+
1.16. Grant TW_EXIT_LIMIT_MANAGER_ROLE to Agent on TWGateway
22+
1.17. Set TWGateway exit request limits
23+
1.18. Register CircuitBreaker pauser for ConsolidationGateway
24+
# ======================== CSM ========================
25+
1.19. Upgrade and finalize CSM v3
26+
1.20. Upgrade and finalize ParametersRegistry v3
27+
1.21. Upgrade and finalize FeeOracle v3
28+
1.22. Upgrade CSVettedGate implementation
29+
1.23. Upgrade and finalize Accounting v3
30+
1.24. Upgrade and finalize FeeDistributor v3
31+
1.25. Upgrade ExitPenalties implementation
32+
1.26. Upgrade ValidatorStrikes implementation
33+
1.27. Point ValidatorStrikes to the new Ejector
34+
1.28. Revoke REPORT_EL_REWARDS_STEALING_PENALTY_ROLE
35+
1.29. Grant REPORT_GENERAL_DELAYED_PENALTY_ROLE
36+
1.30. Revoke SETTLE_EL_REWARDS_STEALING_PENALTY_ROLE
37+
1.31. Grant SETTLE_GENERAL_DELAYED_PENALTY_ROLE
38+
1.32. Revoke VERIFIER_ROLE from old verifier
39+
1.33. Grant VERIFIER_ROLE to new verifier
40+
1.34. Grant REPORT_REGULAR_WITHDRAWN_VALIDATORS_ROLE to VerifierV3
41+
1.35. Grant REPORT_SLASHED_WITHDRAWN_VALIDATORS_ROLE to Easy Track
42+
1.36. Revoke CREATE_NODE_OPERATOR_ROLE from old PermissionlessGate
43+
1.37. Grant CREATE_NODE_OPERATOR_ROLE to new PermissionlessGate
44+
1.38. Revoke START_REFERRAL_SEASON_ROLE
45+
1.39. Revoke END_REFERRAL_SEASON_ROLE
46+
1.40. Register CircuitBreaker pauser for CSM new verifier
47+
1.41. Register CircuitBreaker pauser for CSM Ejector
48+
1.42. Register CircuitBreaker pauser for CSM identified DVT cluster gate
49+
1.43. Grant CREATE_NODE_OPERATOR_ROLE to identified DVT cluster gate
50+
1.44. Grant SET_BOND_CURVE_ROLE to identified DVT cluster gate
51+
1.45. Grant MANAGE_BOND_CURVES_ROLE to identified DVT cluster curve setup
52+
1.46. Grant MANAGE_CURVE_PARAMETERS_ROLE to identified DVT cluster curve setup
53+
1.47. Execute identified DVT cluster curve setup
54+
1.48. Grant MANAGE_GENERAL_PENALTIES_AND_CHARGES_ROLE to CSM Committee
55+
1.49. Revoke REQUEST_BURN_SHARES_ROLE from CSM Accounting
56+
1.50. Grant REQUEST_BURN_MY_STETH_ROLE to CSM Accounting
57+
1.51. Revoke TWG full-withdrawal role from old Ejector
58+
1.52. Grant TWG full-withdrawal role to new Ejector
59+
# ======================== Curated Module ========================
60+
1.53. Add Curated module to StakingRouter
61+
1.54. Grant REQUEST_BURN_MY_STETH_ROLE to Curated Accounting
62+
1.55. Grant TWG full-withdrawal role to Curated Ejector
63+
1.56. Grant RESUME_ROLE to agent on Curated module
64+
1.57. Resume Curated module
65+
1.58. Revoke RESUME_ROLE from agent on Curated module
66+
1.59. Update Curated HashConsensus frame config
67+
1.60. Register CircuitBreaker pauser for Curated module
68+
1.61. Register CircuitBreaker pauser for Curated Accounting
69+
1.62. Register CircuitBreaker pauser for Curated FeeOracle
70+
1.63. Register CircuitBreaker pauser for Curated Verifier
71+
1.64. Register CircuitBreaker pauser for Curated Ejector
72+
# ======================== Finish Upgrade ========================
73+
1.65. Call UpgradeTemplate.finishUpgrade
74+
75+
# ======================== EasyTrack ========================
76+
2. Remove CSMSettleElStealingPenalty ET factory
77+
3. Remove CSMSetVettedGateTree ET factory
78+
4. Add UpdateStakingModuleShareLimits ET factory
79+
5. Add AllowConsolidationPair ET factory
80+
6. Add SetMerkleGateTree CSM ET factory
81+
7. Add ReportWithdrawalsForSlashedValidators CSM ET factory
82+
8. Add SettleGeneralDelayedPenalty CSM ET factory
83+
9. Add SetMerkleGateTree CM ET factory
84+
10. Add ReportWithdrawalsForSlashedValidators CM ET factory
85+
11. Add SettleGeneralDelayedPenalty CM ET factory
86+
12. Add CreateOrUpdateOperatorGroup CM ET factory
87+
88+
Vote passed & executed on Apr-30-2026 02:04:12 PM +UTC, block 2721709.
89+
90+
"""
91+
92+
from typing import Dict, List, Optional, Tuple
93+
94+
from brownie import interface
95+
96+
from utils.config import get_deployer_account, get_is_live, get_priority_fee
97+
from utils.dual_governance import submit_proposals
98+
from utils.ipfs import calculate_vote_ipfs_description, upload_vote_ipfs_description
99+
from utils.mainnet_fork import pass_and_exec_dao_vote
100+
from utils.voting import bake_vote_items, confirm_vote_script, create_vote
101+
102+
103+
# ============================== Addresses ===================================
104+
UPGRADE_VOTE_SCRIPT = "0xaC83987948dB29c54b91B9a3Bd7a5cA99fA7F1D1"
105+
106+
107+
# ============================= Description ==================================
108+
DG_PROPOSAL_METADATA = "Activate Staking Router v3 + Curated Module v2 + Community Staking Module v3"
109+
DG_SUBMISSION_DESCRIPTION = "1. Submit a Dual Governance proposal to activate Staking Router v3 + Curated Module v2 + Community Staking Module v3"
110+
IPFS_DESCRIPTION = """
111+
1. **Activate Staking Router v3**, including protocol contract upgrades and Dual Governance execution setup. Items 1.1-1.18.
112+
2. **Upgrade Community Staking Module to v3**, including CSM contract upgrades, role updates and identified DVT cluster setup. Items 1.19-1.52.
113+
3. **Add and configure Curated Module v2**. Items 1.53-1.64.
114+
4. **Finalize the protocol upgrade**. Item 1.65.
115+
5. **Update Easy Track factories for CSM v3 and Curated Module v2 operations**. Items 2-12.
116+
"""
117+
118+
119+
def is_placeholder_vote_script_address(value: str) -> bool:
120+
normalized = value.strip().lower()
121+
return normalized in ("", "0x0000000000000000000000000000000000000000") or normalized.startswith("todo")
122+
123+
124+
def get_dg_items(upgrade_vote_script: Optional[str] = None) -> List[Tuple[str, str]]:
125+
vote_script_address = (upgrade_vote_script or UPGRADE_VOTE_SCRIPT).strip()
126+
if is_placeholder_vote_script_address(vote_script_address):
127+
raise ValueError(
128+
"UpgradeVoteScript address is not configured. "
129+
"Pass upgrade_vote_script explicitly or set UPGRADE_VOTE_SCRIPT at the top of this file."
130+
)
131+
132+
omnibus = interface.UpgradeVoteScript(vote_script_address)
133+
dg_items: List[Tuple[str, str]] = []
134+
135+
for _, call_script in omnibus.getVoteItems():
136+
dg_items.append((call_script[0], call_script[1].hex()))
137+
138+
return dg_items
139+
140+
141+
def get_vote_items(
142+
upgrade_vote_script: Optional[str] = None,
143+
) -> Tuple[List[str], List[Tuple[str, str]]]:
144+
vote_script_address = (upgrade_vote_script or UPGRADE_VOTE_SCRIPT).strip()
145+
if is_placeholder_vote_script_address(vote_script_address):
146+
raise ValueError(
147+
"UpgradeVoteScript address is not configured. "
148+
"Pass upgrade_vote_script explicitly or set UPGRADE_VOTE_SCRIPT at the top of this file."
149+
)
150+
151+
omnibus = interface.UpgradeVoteScript(vote_script_address)
152+
153+
vote_desc_items: List[str] = []
154+
call_script_items: List[Tuple[str, str]] = []
155+
156+
dg_items = get_dg_items(upgrade_vote_script)
157+
158+
dg_call_script = submit_proposals([(dg_items, DG_PROPOSAL_METADATA)])
159+
vote_desc_items.append(DG_SUBMISSION_DESCRIPTION)
160+
call_script_items.append(dg_call_script[0])
161+
162+
voting_items = omnibus.getVotingVoteItems()
163+
for desc, call_script in voting_items:
164+
vote_desc_items.append(desc)
165+
call_script_items.append((call_script[0], call_script[1].hex()))
166+
167+
return vote_desc_items, call_script_items
168+
169+
170+
def start_vote(
171+
tx_params: Dict[str, str],
172+
silent: bool = False,
173+
upgrade_vote_script: Optional[str] = None,
174+
):
175+
vote_desc_items, call_script_items = get_vote_items(
176+
upgrade_vote_script=upgrade_vote_script,
177+
)
178+
vote_items = bake_vote_items(list(vote_desc_items), list(call_script_items))
179+
desc_ipfs = (
180+
calculate_vote_ipfs_description(IPFS_DESCRIPTION)
181+
if silent
182+
else upload_vote_ipfs_description(IPFS_DESCRIPTION)
183+
)
184+
185+
vote_id, tx = confirm_vote_script(vote_items, silent, desc_ipfs) and list(
186+
create_vote(vote_items, tx_params, desc_ipfs=desc_ipfs)
187+
)
188+
189+
vote_script_address = (upgrade_vote_script or UPGRADE_VOTE_SCRIPT).strip()
190+
assert interface.UpgradeVoteScript(vote_script_address).isValidVoteScript(
191+
vote_id,
192+
DG_PROPOSAL_METADATA,
193+
)
194+
195+
return vote_id, tx
196+
197+
198+
def main(upgrade_vote_script: Optional[str] = None):
199+
tx_params: Dict[str, str] = {"from": get_deployer_account().address}
200+
if get_is_live():
201+
tx_params["priority_fee"] = get_priority_fee()
202+
203+
vote_id, _ = start_vote(
204+
tx_params=tx_params,
205+
silent=False,
206+
upgrade_vote_script=upgrade_vote_script,
207+
)
208+
vote_id >= 0 and print(f"Vote created: {vote_id}.")
209+
210+
211+
def start_and_execute_vote_on_fork_manual(upgrade_vote_script: Optional[str] = None):
212+
if get_is_live():
213+
raise Exception("This script is for local testing only.")
214+
215+
tx_params = {"from": get_deployer_account()}
216+
vote_id, _ = start_vote(
217+
tx_params=tx_params,
218+
silent=True,
219+
upgrade_vote_script=upgrade_vote_script,
220+
)
221+
print(f"Vote created: {vote_id}.")
222+
pass_and_exec_dao_vote(int(vote_id), step_by_step=True)

0 commit comments

Comments
 (0)