How to check the Lido DAO on-chain vote #206

What the vote is about

This document outlines methods to verify all the calls embedded in the Lido DAO on-chain vote #206.

The vote covers the following changes:

  1. Activate the Community Staking Module for 0x02 withdrawal credentials, as per Snapshot decision. Audits: CSMv3 and CMv2 — Statemind, Certora; Easy Track factories — MixBytes | Deployment verification — MixBytes: 0x02 CSM, 0x02 CSM Easy Track factories
    • Restrict proposal execution to 14:00-23:00 UTC. Item 1.1.
    • Register, enable and configure 0x02 CSM with an initial stake share limit of 0.01% and top-up queue limit of 32. Items 1.2 - 1.8, 1.17 - 1.19.
    • Register 0x02 CSM Module, Accounting, FeeOracle, Verifier and Ejector on CircuitBreaker with the CSM Committee as pauser. Items 1.9 - 1.13.
    • Add 0x02 CSM Easy Track factories to report withdrawals for slashed validators, settle delayed penalties, and update share limit. Items 2 - 4.
  2. Set CMv1 stake share limit and priority exit share threshold to 0, as per Snapshot decision. Item 1.14
  3. Set Consensys target validators limit to 0 in CMv1 and CMv2 (soft mode), as proposed on the forum. Items 1.15 - 1.16.
  4. Add LOL LDO Easy Track factory for top-ups with a limit of 7.5M LDO per 12-month period, under the Snapshot-approved liquidity mandate. Item 5.

Resources for the Proposal Validation

The resources listed in this section are considered trustworthy and reliable.

  • Lido Docs - use this to verify contract addresses
  • Blockchain Explorer Etherscan (or alternatives such as Blockscout) - use this to review contract functionality/inspect methods, and check the current state of contracts
  • Lido Research Forum - use this to access original proposals, review details of proposed changes, and validate modification parameters
  • Snapshot - use this to review pre-approvals for on-chain proposals

Direct links to relevant sources will be provided for each item in the vote, ensuring easy access to the associated information.

Vote Items and Verification Details

How to verify: open the vote at dao.lido.fi/vote/206 and compare its calls with this guide. Each target links to its Lido Docs entry, and each method link opens the exact function on Etherscan.

1.Submit a Dual Governance proposal for 0x02 CSM activation and Curated Module changes

The call target is Dual Governance. The exact canonical signature is submitProposal((address,uint96,bytes)[],string).
submitProposal(
The submitProposal method exists on the contract.
[1] tuple[] calls
See 19 parsed calls at 1.1–1.19
Contains the 19 calls shown in items 1.1–1.19; every call's ETH value is 0. Item 1.1 calls its target directly; items 1.2–1.19 are executed by the Aragon Agent through forward(bytes).
[2] string metadata
Activate CSM 0x02, set CMv1 stake share limit and priority exit share threshold to 0, and set Consensys target limits to 0 in CMv1 and CMv2
The exact metadata string in the call data. It summarises the activation and Curated Module changes.
)

1.1.Restrict proposal execution to 14:00–23:00 UTC

On [Dual Governance Time Constraints]
The call target is Dual Governance Time Constraints. The call reverts outside the encoded daily window, so the proposal can only be executed between 14:00 and 23:00 UTC.
checkTimeWithinDayTimeAndEmit(
The checkTimeWithinDayTimeAndEmit method exists on the contract.
[1] uint32 startDayTime
50400
50400 seconds after UTC midnight = 14:00 UTC, the window start in the activation post.
[2] uint32 endDayTime
82800
82800 seconds after UTC midnight = 23:00 UTC, the window end in the activation post.
)

1.2.Register Community Staking 0x02 on StakingRouter

The call target is StakingRouter. The exact canonical signature is addStakingModule(string,address,(uint256,uint256,uint256,uint256,uint256,uint256,uint256)), consistent with the published type definition.
addStakingModule(
The addStakingModule method exists on the contract.
[1] string _name
Community Staking 0x02
Module name Community Staking 0x02, per the activation table.
[2] address _stakingModuleAddress
[3.1] uint256 _stakingModuleConfig.stakeShareLimit
1
Stake share limit 1 BP, i.e. 0.01%, per the activation table.
[3.2] uint256 _stakingModuleConfig.priorityExitShareThreshold
240
Priority exit share threshold 240 BP, i.e. 2.4%, per the activation table.
[3.3] uint256 _stakingModuleConfig.stakingModuleFee
200
Module fee 200 BP, i.e. 2%, per the activation table.
[3.4] uint256 _stakingModuleConfig.treasuryFee
800
Treasury fee 800 BP, i.e. 8%, per the activation table.
[3.5] uint256 _stakingModuleConfig.maxDepositsPerBlock
30
Maximum 30 deposits per block, per the activation table.
[3.6] uint256 _stakingModuleConfig.minDepositBlockDistance
25
Minimum distance 25 blocks, per the activation table.
[3.7] uint256 _stakingModuleConfig.withdrawalCredentialsType
2
Withdrawal credentials type 2 (0x02), per the activation table.
)

Role items (1.3–1.5, 1.7, 1.17, 1.19): check the target, the 32-byte role and the account. Open the pre-filled Keccak link next to each role and compare its result with the role value.

1.3.Grant the stETH burning-request role to 0x02 CSM Accounting

The call target is Burner.
grantRole(
The grantRole method exists on the contract.
[1] bytes32 role
0x28186f938b759084eea36948ef1cd8b40ec8790a98d5f1a09b70879fe054e5cc
keccak256("REQUEST_BURN_MY_STETH_ROLE") equals this role value.
0x02 CSM Accounting receives this role under the activation plan.
)

1.4.Grant the full-withdrawal-request role to 0x02 CSM Ejector

On [Triggerable Withdrawals Gateway]
grantRole(
The grantRole method exists on the contract.
[1] bytes32 role
0x15fac8ba7fe8dd5344b88c1915452ce66976f270d1cd793c3b0ab579cecd33c0
keccak256("ADD_FULL_WITHDRAWAL_REQUEST_ROLE") equals this role value.
0x02 CSM Ejector receives this role under the activation plan.
)

Temporary roles: 1.5 grants the Aragon Agent a role, 1.6 uses it and 1.7 revokes it. Items 1.17–1.19 follow the same pattern for the top-up queue limit.

1.5.Grant Aragon Agent the 0x02 CSM resume role

The call target is CSModule (0x02 CSM).
grantRole(
The grantRole method exists on the contract.
[1] bytes32 role
0x2fc10cc8ae19568712f7a176fb4978616a610650813c9d05326c34abb62749c7
keccak256("RESUME_ROLE") equals this role value.
Aragon Agent receives this role under the activation plan.
)

CircuitBreaker (1.9–1.13): in registerPauser, [1] is the contract that can be paused and [2] is its pauser. These items assign the CSM Committee to all five 0x02 CSM contracts.

1.9.Register the CSM Committee as pauser for 0x02 CSM CSModule

The call target is CircuitBreaker.
registerPauser(
The registerPauser method exists on the contract.
CSModule (0x02 CSM), one of the five contracts listed for pauser registration in the activation post.
CSM Committee, assigned as pauser for all five contracts in the activation post.
)

1.10.Register the CSM Committee as pauser for 0x02 CSM Accounting

The call target is CircuitBreaker.
registerPauser(
The registerPauser method exists on the contract.
0x02 CSM Accounting, one of the five contracts listed for pauser registration in the activation post.
CSM Committee, assigned as pauser for all five contracts in the activation post.
)

1.11.Register the CSM Committee as pauser for 0x02 CSM FeeOracle

The call target is CircuitBreaker.
registerPauser(
The registerPauser method exists on the contract.
0x02 CSM FeeOracle, one of the five contracts listed for pauser registration in the activation post.
CSM Committee, assigned as pauser for all five contracts in the activation post.
)

1.12.Register the CSM Committee as pauser for 0x02 CSM Verifier

The call target is CircuitBreaker.
registerPauser(
The registerPauser method exists on the contract.
0x02 CSM Verifier, one of the five contracts listed for pauser registration in the activation post.
CSM Committee, assigned as pauser for all five contracts in the activation post.
)

1.13.Register the CSM Committee as pauser for 0x02 CSM Ejector

The call target is CircuitBreaker.
registerPauser(
The registerPauser method exists on the contract.
0x02 CSM Ejector, one of the five contracts listed for pauser registration in the activation post.
CSM Committee, assigned as pauser for all five contracts in the activation post.
)

StakingRouter (1.14–1.16): check each module ID with getStakingModuleStateConfig(uint256) and deposit limits with getStakingModuleStateDeposits(uint256) on StakingRouter's Read as Proxy tab.

1.14.Set CMv1 stake share limit and priority exit share threshold to zero

The call target is StakingRouter.
updateStakingModule(
The updateStakingModule method exists on the contract.
[1] uint256 _stakingModuleId
1
[2] uint256 _stakeShareLimit
0
0 BP, i.e. 0%, the CMv1 stake share limit requested in post 45.
[3] uint256 _priorityExitShareThreshold
0
0 BP, i.e. 0%, the priority exit share threshold encoded in this call. Its meaning is described in StakingRouter’s parameter documentation.
[4] uint256 _stakingModuleFee
350
Module fee 350 BP, i.e. 3.5%, unchanged: equals the current CMv1 value from getStakingModuleStateConfig(1).
[5] uint256 _treasuryFee
650
Treasury fee 650 BP, i.e. 6.5%, unchanged: equals the current CMv1 value from getStakingModuleStateConfig(1).
[6] uint256 _maxDepositsPerBlock
150
Maximum 150 deposits per block, unchanged: equals the current CMv1 value from getStakingModuleStateDeposits(1).
[7] uint256 _minDepositBlockDistance
25
Minimum deposit block distance 25, unchanged: equals the current CMv1 value from getStakingModuleStateDeposits(1).
)

1.15.Set the CMv1 MetaMask Staking target-validator limit to zero in soft mode

The call target is StakingRouter.
updateTargetValidatorsLimits(
The updateTargetValidatorsLimits method exists on the contract.
[1] uint256 _stakingModuleId
1
[2] uint256 _nodeOperatorId
21
Operator ID 21 is MetaMask Staking (formerly Consensys Staking) in this module, per the forum proposal.
[3] uint256 _targetLimitMode
1
Mode 1 is soft mode, as requested in the forum proposal.
[4] uint256 _targetLimit
0
Target limit 0, as requested in the forum proposal.
)

1.16.Set the CMv2 MetaMask Staking target-validator limit to zero in soft mode

The call target is StakingRouter.
updateTargetValidatorsLimits(
The updateTargetValidatorsLimits method exists on the contract.
[1] uint256 _stakingModuleId
4
[2] uint256 _nodeOperatorId
6
Operator ID 6 is MetaMask Staking (formerly Consensys Staking) in this module, per the forum proposal.
[3] uint256 _targetLimitMode
1
Mode 1 is soft mode, as requested in the forum proposal.
[4] uint256 _targetLimit
0
Target limit 0, as requested in the forum proposal.
)

2–5. Register four Easy Track factories

Easy Track factories (2–5): compare each factory and its full permission string, then split the string into address and selector pairs as in the worked example below. If an explorer cannot show a tuple signature, use the verified ABI or Blockscout with the Keccak link.

On [Easy Track]
addEVMScriptFactory(address,bytes)
The addEVMScriptFactory method exists on the contract.
Item[1] Factory[2] Permissions · address + selector
2
ReportWithdrawalsForSlashedValidators
3
SettleGeneralDelayedPenalty
4
UpdateStakingModuleShareLimits
5
LOL LDO TopUpAllowedRecipients

How to Verify Permission Hashes — worked example: item 4

  1. Take exact call data [2] from item 4.
  2. Split after the initial 0x into consecutive 20-byte target addresses (40 hexadecimal characters) and 4-byte selectors (8 hexadecimal characters).
  3. Confirm the target contract address from the linked deployment sources.
  4. Hash the full canonical function signature using Ethereum Keccak-256 and take the first 4 bytes.
  5. Compare the computed selector, target address and complete reassembled raw permission value against call data [2].

validateParams((uint16,uint16,uint16,uint16)) → 0x5adcee90; updateModuleShares(uint256,uint16,uint16) → 0x13976a06