CuratedModule
CuratedModule is the core staking module contract. It stores Node Operator and validator deposit data, handles interactions with the Staking Router, and provides flows for key and operator-address management, rewards, penalties, validator balances, and validator exits. Bond operations are delegated to Accounting, while exit-related obligations are recorded by ExitPenalties.
For initial deposits and subsequent 0x02 validator top-ups, CuratedModule uses the effective allocation weights and external stake supplied by MetaRegistry. This weighted strategy moves eligible Node Operators toward their target shares instead of allocating stake through a FIFO queue.
State Variables​
META_REGISTRY​
IMetaRegistry public immutable META_REGISTRY
STAKING_ROUTER_ROLE​
bytes32 public constant STAKING_ROUTER_ROLE = keccak256("STAKING_ROUTER_ROLE")
REPORT_GENERAL_DELAYED_PENALTY_ROLE​
bytes32 public constant REPORT_GENERAL_DELAYED_PENALTY_ROLE = keccak256("REPORT_GENERAL_DELAYED_PENALTY_ROLE")
SETTLE_GENERAL_DELAYED_PENALTY_ROLE​
bytes32 public constant SETTLE_GENERAL_DELAYED_PENALTY_ROLE = keccak256("SETTLE_GENERAL_DELAYED_PENALTY_ROLE")
VERIFIER_ROLE​
bytes32 public constant VERIFIER_ROLE = keccak256("VERIFIER_ROLE")
REPORT_REGULAR_WITHDRAWN_VALIDATORS_ROLE​
bytes32 public constant REPORT_REGULAR_WITHDRAWN_VALIDATORS_ROLE =
keccak256("REPORT_REGULAR_WITHDRAWN_VALIDATORS_ROLE")
REPORT_SLASHED_WITHDRAWN_VALIDATORS_ROLE​
bytes32 public constant REPORT_SLASHED_WITHDRAWN_VALIDATORS_ROLE =
keccak256("REPORT_SLASHED_WITHDRAWN_VALIDATORS_ROLE")
CREATE_NODE_OPERATOR_ROLE​
bytes32 public constant CREATE_NODE_OPERATOR_ROLE = keccak256("CREATE_NODE_OPERATOR_ROLE")
OPERATOR_ADDRESSES_ADMIN_ROLE​
bytes32 public constant OPERATOR_ADDRESSES_ADMIN_ROLE = keccak256("OPERATOR_ADDRESSES_ADMIN_ROLE")
LIDO_LOCATOR​
ILidoLocator public immutable LIDO_LOCATOR
STETH​
IStETH public immutable STETH
PARAMETERS_REGISTRY​
IParametersRegistry public immutable PARAMETERS_REGISTRY
ACCOUNTING​
IAccounting public immutable ACCOUNTING
EXIT_PENALTIES​
IExitPenalties public immutable EXIT_PENALTIES
FEE_DISTRIBUTOR​
address public immutable FEE_DISTRIBUTOR
MODULE_TYPE​
bytes32 internal immutable MODULE_TYPE
Functions​
constructor​
constructor(
bytes32 moduleType,
address lidoLocator,
address parametersRegistry,
address accounting,
address exitPenalties,
address metaRegistry
) BaseModule(moduleType, lidoLocator, parametersRegistry, accounting, exitPenalties);
initialize​
Initialize contract from scratch. In case of a method call frontrun, the contract instance should be discarded. It is recommended to call this method in the same transaction as the deployment transaction and perform extensive deployment verification before using the contract instance.
function initialize(address admin) external override initializer;
obtainDepositData​
Obtains deposit data to be used by StakingRouter to deposit to the Ethereum Deposit contract
function obtainDepositData(
uint256 depositsCount,
bytes calldata depositCalldata // solhint-disable-line no-unused-vars
)
external
returns (bytes memory publicKeys, bytes memory signatures);
Parameters
| Name | Type | Description |
|---|---|---|
depositsCount | uint256 | Number of deposits to be done |
depositCalldata | bytes | Staking module defined data encoded as bytes. IMPORTANT: depositCalldata MUST NOT modify the deposit data set of the staking module |
Returns
| Name | Type | Description |
|---|---|---|
publicKeys | bytes | Batch of the concatenated public validators keys |
signatures | bytes | Batch of the concatenated deposit signatures for returned public keys |
allocateDeposits​
Validates that provided keys belong to the corresponding operators in the module and calculates deposit allocations for top-up
Reverts if any key doesn't belong to the module or data is invalid
function allocateDeposits(
uint256 maxDepositAmount,
bytes[] calldata pubkeys,
uint256[] calldata keyIndices,
uint256[] calldata operatorIds,
uint256[] calldata topUpLimits
) external returns (uint256[] memory allocations);
Parameters
| Name | Type | Description |
|---|---|---|
maxDepositAmount | uint256 | Total ether amount available for top-up (must be multiple of 1 gwei) |
pubkeys | bytes[] | List of validator public keys to top up |
keyIndices | uint256[] | Indices of keys within their respective operators |
operatorIds | uint256[] | Node operator IDs that own the keys |
topUpLimits | uint256[] | Maximum amount that can be deposited per key based on CL data and SR internal logic. |
Returns
| Name | Type | Description |
|---|---|---|
allocations | uint256[] | Amount to deposit to each key |
notifyNodeOperatorWeightChange​
Notifies the module about the weight change of a node operator.
function notifyNodeOperatorWeightChange(uint256 nodeOperatorId, uint256 oldWeight, uint256 newWeight) external;
Parameters
| Name | Type | Description |
|---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
oldWeight | uint256 | The old weight of the node operator. |
newWeight | uint256 | The new weight of the node operator. |
getOperatorWeights​
Returns operator weights used for operator-level allocations in the module.
Provides weights from the on-chain allocation strategy used by the module.
function getOperatorWeights(uint256[] calldata operatorIds)
external
view
returns (uint256[] memory operatorWeights);
Parameters
| Name | Type | Description |
|---|---|---|
operatorIds | uint256[] | Node operator IDs to query. |
Returns
| Name | Type | Description |
|---|---|---|
operatorWeights | uint256[] | Weights aligned with operatorIds. |
getNodeOperatorWeightAndExternalStake​
Returns effective weight and external stake for a node operator.
Reverts until the module deposit info cache is fully refreshed.
function getNodeOperatorWeightAndExternalStake(uint256 nodeOperatorId)
external
view
returns (uint256 weight, uint256 externalStake);
Parameters
| Name | Type | Description |
|---|---|---|
nodeOperatorId | uint256 | Node operator ID to query. |
Returns
| Name | Type | Description |
|---|---|---|
weight | uint256 | Effective allocation weight. |
externalStake | uint256 | External stake amount in wei. |
getDepositAllocationTargets​
Returns current deposit allocation targets for all operators.
Target = totalCurrent * operatorWeight / totalWeight (in validator count). Includes operators regardless of depositable capacity for informational purposes. Actual allocation recalculates shares only across operators with usable capacity, so real per-operator amounts may differ from the targets shown here. Arrays are indexed by operator id; zero-weight operators have zero values.
function getDepositAllocationTargets()
external
view
returns (uint256[] memory currentValidators, uint256[] memory targetValidators);
Returns
| Name | Type | Description |
|---|---|---|
currentValidators | uint256[] | Current active validator count per operator. |
targetValidators | uint256[] | Target validator count per operator. |
getTopUpAllocationTargets​
Returns current top-up allocation targets for all operators.
target = totalCurrent * operatorWeight / totalWeight (in wei).
Includes operators regardless of top-up capacity for informational purposes.
Actual allocation recalculates shares only across operators with usable capacity,
so real per-operator amounts may differ from the targets shown here.
Arrays are indexed by operator id; zero-weight operators have zero values.
function getTopUpAllocationTargets()
external
view
returns (uint256[] memory currentAllocations, uint256[] memory targetAllocations);
Returns
| Name | Type | Description |
|---|---|---|
currentAllocations | uint256[] | Current operator stake in wei. |
targetAllocations | uint256[] | Target operator stake in wei. |
getDepositsAllocation​
Method to get list of operators and amount of Eth that can be topped up to operator from depositAmount
function getDepositsAllocation(uint256 maxDepositAmount)
external
view
returns (uint256 allocated, uint256[] memory operatorIds, uint256[] memory allocations);
Parameters
| Name | Type | Description |
|---|---|---|
maxDepositAmount | uint256 |
createNodeOperator​
Permissioned method to add a new Node Operator
Should be called by *Gate.sol contracts. See PermissionlessGate.sol and VettedGate.sol for examples
function createNodeOperator(
address from,
NodeOperatorManagementProperties calldata managementProperties,
address /* referrer */
)
public
virtual
whenResumed
returns (uint256 nodeOperatorId);
Parameters
| Name | Type | Description |
|---|---|---|
from | address | Sender address. Initial sender address to be used as a default manager and reward addresses. Gates must pass the correct address in order to specify which address should be the owner of the Node Operator. |
managementProperties | NodeOperatorManagementProperties | Optional. Management properties to be used for the Node Operator. managerAddress: Used as managerAddress for the Node Operator. If not passed from will be used. rewardAddress: Used as rewardAddress for the Node Operator. If not passed from will be used. extendedManagerPermissions: Flag indicating that managerAddress will be able to change rewardAddress. If set to true resetNodeOperatorManagerAddress method will be disabled |
<none> | address |
addValidatorKeysETH​
Add new keys to the existing Node Operator using ETH as a bond
Any excess msg.value will be sent to the bond and can be claimed from there. This behaviour is intentional and protects users from key upload transaction front runs rendering the user transaction invalid due to changes in the required bond amount.
function addValidatorKeysETH(
address from,
uint256 nodeOperatorId,
uint256 keysCount,
bytes calldata publicKeys,
bytes calldata signatures
) external payable whenResumed;
Parameters
| Name | Type | Description |
|---|---|---|
from | address | Sender address. Commonly equals to msg.sender except for the case of Node Operator creation by *Gate.sol contracts |
nodeOperatorId | uint256 | ID of the Node Operator |
keysCount | uint256 | Signing keys count |
publicKeys | bytes | Public keys to submit |
signatures | bytes | Signatures of (deposit_message_root, domain) tuples https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/phase0/beacon-chain.md#signingdata |
addValidatorKeysStETH​
Add new keys to the existing Node Operator using stETH as a bond
function addValidatorKeysStETH(
address from,
uint256 nodeOperatorId,
uint256 keysCount,
bytes calldata publicKeys,
bytes calldata signatures,
IAccounting.PermitInput calldata permit
) external whenResumed;
Parameters
| Name | Type | Description |
|---|---|---|
from | address | Sender address. Commonly equals to msg.sender except for the case of Node Operator creation by *Gate.sol contracts |
nodeOperatorId | uint256 | ID of the Node Operator |
keysCount | uint256 | Signing keys count |
publicKeys | bytes | Public keys to submit |
signatures | bytes | Signatures of (deposit_message_root, domain) tuples https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/phase0/beacon-chain.md#signingdata |
permit | IAccounting.PermitInput | Optional. Permit to use stETH as bond |
addValidatorKeysWstETH​
Add new keys to the existing Node Operator using wstETH as a bond
function addValidatorKeysWstETH(
address from,
uint256 nodeOperatorId,
uint256 keysCount,
bytes calldata publicKeys,
bytes calldata signatures,
IAccounting.PermitInput calldata permit
) external whenResumed;
Parameters
| Name | Type | Description |
|---|---|---|
from | address | Sender address. Commonly equals to msg.sender except for the case of Node Operator creation by *Gate.sol contracts |
nodeOperatorId | uint256 | ID of the Node Operator |
keysCount | uint256 | Signing keys count |
publicKeys | bytes | Public keys to submit |
signatures | bytes | Signatures of (deposit_message_root, domain) tuples https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/phase0/beacon-chain.md#signingdata |
permit | IAccounting.PermitInput | Optional. Permit to use wstETH as bond |
proposeNodeOperatorManagerAddressChange​
Propose a new manager address for the Node Operator.
Passing address(0) clears the pending proposal without changing the current manager address.
function proposeNodeOperatorManagerAddressChange(uint256 nodeOperatorId, address proposedAddress) external;
Parameters
| Name | Type | Description |
|---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
proposedAddress | address | Proposed manager address, or address(0) to cancel the current proposal |
confirmNodeOperatorManagerAddressChange​
Confirm a new manager address for the Node Operator. Should be called from the currently proposed address
function confirmNodeOperatorManagerAddressChange(uint256 nodeOperatorId) external;
Parameters
| Name | Type | Description |
|---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
proposeNodeOperatorRewardAddressChange​
Propose a new reward address for the Node Operator.
Passing address(0) clears the pending proposal without changing the current reward address.
function proposeNodeOperatorRewardAddressChange(uint256 nodeOperatorId, address proposedAddress) external;
Parameters
| Name | Type | Description |
|---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
proposedAddress | address | Proposed reward address, or address(0) to cancel the current proposal |
confirmNodeOperatorRewardAddressChange​
Confirm a new reward address for the Node Operator. Should be called from the currently proposed address
function confirmNodeOperatorRewardAddressChange(uint256 nodeOperatorId) external;
Parameters
| Name | Type | Description |
|---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
resetNodeOperatorManagerAddress​
Reset the manager address to the reward address. Should be called from the reward address
function resetNodeOperatorManagerAddress(uint256 nodeOperatorId) external;
Parameters
| Name | Type | Description |
|---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
changeNodeOperatorRewardAddress​
Change rewardAddress if extendedManagerPermissions is enabled for the Node Operator
function changeNodeOperatorRewardAddress(uint256 nodeOperatorId, address newAddress) external;
Parameters
| Name | Type | Description |
|---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
newAddress | address | Proposed reward address |
changeNodeOperatorAddresses​
Change both reward and manager addresses of a node operator. An emergency method.
Only privileged role member can call this method if the role is assigned.
function changeNodeOperatorAddresses(uint256 nodeOperatorId, address newManagerAddress, address newRewardAddress)
external;
Parameters
| Name | Type | Description |
|---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
newManagerAddress | address | New manager address |
newRewardAddress | address | New reward address |
onRewardsMinted​
Called by StakingRouter to signal that stETH rewards were minted for this module.
Passes through the minted stETH shares to the fee distributor
function onRewardsMinted(uint256 totalShares) external;
Parameters
| Name | Type | Description |
|---|---|---|
totalShares | uint256 | Amount of stETH shares that were minted to reward all node operators. |
updateExitedValidatorsCount​
Updates the number of the validators in the EXITED state for node operator with given id
exitedValidatorsCount is not used inside the module, but SR still expects this data to be stored and returned. The method should be removed once there are no legacy modules in the Lido protocol and SR no longer calls this method.
function updateExitedValidatorsCount(bytes calldata nodeOperatorIds, bytes calldata exitedValidatorsCounts)
external;
Parameters
| Name | Type | Description |
|---|---|---|
nodeOperatorIds | bytes | Packed array of the node operators id |
exitedValidatorsCounts | bytes | Packed array of the new number of EXITED validators for the node operators |
unsafeUpdateValidatorsCount​
Unsafely updates the number of validators in the EXITED/STUCK states for node operator with given id 'unsafely' means that this method can both increase and decrease exited and stuck counters
exitedValidatorsCount is not used inside the module, but SR still expects this data to be stored and returned. The method should be removed once there are no legacy modules in the Lido protocol and SR no longer calls this method.
function unsafeUpdateValidatorsCount(uint256 nodeOperatorId, uint256 exitedValidatorsCount) external;
Parameters
| Name | Type | Description |
|---|---|---|
nodeOperatorId | uint256 | |
exitedValidatorsCount | uint256 |
updateTargetValidatorsLimits​
Updates the limit of the validators that can be used for deposit
function updateTargetValidatorsLimits(uint256 nodeOperatorId, uint256 targetLimitMode, uint256 targetLimit)
external;
Parameters
| Name | Type | Description |
|---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
targetLimitMode | uint256 | Target limit mode for the Node Operator (see https://hackmd.io/@lido/BJXRTxMRp) 0 - disabled 1 - soft mode 2 - forced mode |
targetLimit | uint256 | Target limit of validators |
decreaseVettedSigningKeysCount​
Called by StakingRouter to decrease the number of vetted keys for Node Operators with given ids
function decreaseVettedSigningKeysCount(bytes calldata nodeOperatorIds, bytes calldata vettedSigningKeysCounts)
external;
Parameters
| Name | Type | Description |
|---|---|---|
nodeOperatorIds | bytes | Bytes packed array of the Node Operator ids |
vettedSigningKeysCounts | bytes | Bytes packed array of the new numbers of vetted keys for the Node Operators |
removeKeys​
Remove keys for the Node Operator. Charging is module-specific (e.g., CSM applies a per-key fee).
This method is a part of the Optimistic Vetting scheme. After key deletion totalVettedKeys
is set equal to totalAddedKeys. If invalid keys are not removed, the unvetting process will be repeated
and decreaseVettedSigningKeysCount will be called by StakingRouter.
function removeKeys(uint256 nodeOperatorId, uint256 startIndex, uint256 keysCount) external virtual;
Parameters
| Name | Type | Description |
|---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
startIndex | uint256 | Index of the first key |
keysCount | uint256 | Keys count to delete |
updateDepositableValidatorsCount​
Update depositable validators data for the given Node Operator.
The following rules are applied:
- Unbonded keys can not be depositable
- Unvetted keys can not be depositable
- Depositable keys count should respect targetLimit value
function updateDepositableValidatorsCount(uint256 nodeOperatorId) external;
Parameters
| Name | Type | Description |
|---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
reportGeneralDelayedPenalty​
Report general delayed penalty for the given Node Operator
function reportGeneralDelayedPenalty(
uint256 nodeOperatorId,
bytes32 penaltyType,
uint256 amount,
string calldata details
) external;
Parameters
| Name | Type | Description |
|---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
penaltyType | bytes32 | Type of the penalty |
amount | uint256 | Penalty amount in ETH |
details | string | Additional details about the penalty |
cancelGeneralDelayedPenalty​
Cancel previously reported and not settled general delayed penalty for the given Node Operator
function cancelGeneralDelayedPenalty(uint256 nodeOperatorId, uint256 amount) external;
Parameters
| Name | Type | Description |
|---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
amount | uint256 | Amount of penalty to cancel |
settleGeneralDelayedPenalty​
Settles locked bond for eligible Node Operators
SETTLE_GENERAL_DELAYED_PENALTY_ROLE role is expected to be assigned to Easy Track
function settleGeneralDelayedPenalty(uint256[] calldata nodeOperatorIds, uint256[] calldata bondLockNonces)
external;
Parameters
| Name | Type | Description |
|---|---|---|
nodeOperatorIds | uint256[] | IDs of the Node Operators |
bondLockNonces | uint256[] | Bond lock nonces for each Node Operator |
compensateGeneralDelayedPenalty​
Compensate general delayed penalty (locked bond) for the given Node Operator from Node Operator's bond
Can only be called by the Node Operator manager
function compensateGeneralDelayedPenalty(uint256 nodeOperatorId) external;
Parameters
| Name | Type | Description |
|---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
reportValidatorSlashing​
Report Node Operator's key as slashed.
function reportValidatorSlashing(uint256 nodeOperatorId, uint256 keyIndex) external;
Parameters
| Name | Type | Description |
|---|---|---|
nodeOperatorId | uint256 | The ID of the Node Operator |
keyIndex | uint256 | Index of the key in the Node Operator's keys storage |
reportValidatorBalance​
Update verified on-chain balance for a key.
The function stores balance relative to MIN_ACTIVATION_BALANCE.
function reportValidatorBalance(uint256 nodeOperatorId, uint256 keyIndex, uint256 currentBalanceWei)
public
virtual;
Parameters
| Name | Type | Description |
|---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
keyIndex | uint256 | Index of the key in the Node Operator's keys storage |
currentBalanceWei | uint256 | Proven current validator balance in wei |
reportSlashedWithdrawnValidators​
Report withdrawn validators that have been slashed.
function reportSlashedWithdrawnValidators(WithdrawnValidatorInfo[] calldata validatorInfos) external;
Parameters
| Name | Type | Description |
|---|---|---|
validatorInfos | WithdrawnValidatorInfo[] | An array of WithdrawnValidatorInfo structs |
reportRegularWithdrawnValidators​
Report Node Operator's keys as withdrawn and charge penalties associated with exit if any. A validator is considered withdrawn in the following cases:
- if it's an exit of a non-slashed validator, when a withdrawal of the validator is included in a beacon block;
- if it's an exit of a slashed validator, when the committee reports such a validator as withdrawn; note that it can happen earlier than the actual withdrawal is included on the beacon chain if the committee decides it can account for all penalties in advance;
- if it's a consolidated validator, when the corresponding pending consolidation is processed and the balance of the validator has been moved to another validator.
function reportRegularWithdrawnValidators(WithdrawnValidatorInfo[] calldata validatorInfos) external;
Parameters
| Name | Type | Description |
|---|---|---|
validatorInfos | WithdrawnValidatorInfo[] | An array of WithdrawnValidatorInfo structs |
reportValidatorExitDelay​
Handles tracking and penalization logic for a validator that remains active beyond its eligible exit window.
This function is called by the StakingRouter to report the current exit-related status of a validator belonging to a specific node operator. It accepts a validator's public key, associated with the duration (in seconds) it was eligible to exit but has not exited. This data could be used to trigger penalties for the node operator if the validator has exceeded the allowed exit window.
function reportValidatorExitDelay(
uint256 nodeOperatorId,
uint256 proofSlotTimestamp, // solhint-disable-line no-unused-vars
bytes calldata publicKey,
uint256 eligibleToExitInSec
) external;
Parameters
| Name | Type | Description |
|---|---|---|
nodeOperatorId | uint256 | |
proofSlotTimestamp | uint256 | |
publicKey | bytes | |
eligibleToExitInSec | uint256 |
onValidatorExitTriggered​
Handles the triggerable exit event for a validator belonging to a specific node operator.
This function is called by the StakingRouter when a validator is exited using the triggerable exit request on the Execution Layer (EL).
function onValidatorExitTriggered(
uint256 nodeOperatorId,
bytes calldata publicKey,
uint256 elWithdrawalRequestFeePaid,
uint256 exitType
) external;
Parameters
| Name | Type | Description |
|---|---|---|
nodeOperatorId | uint256 | |
publicKey | bytes | |
elWithdrawalRequestFeePaid | uint256 | |
exitType | uint256 |
updateDepositInfo​
Update deposit info for the given Node Operator.
function updateDepositInfo(uint256 nodeOperatorId) external;
Parameters
| Name | Type | Description |
|---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
requestFullDepositInfoUpdate​
Request a full update of deposit info for all node operators. Should be called after external changes that can affect deposit info such as bond curve change or parameters update.
function requestFullDepositInfoUpdate() external;
batchDepositInfoUpdate​
Request a batch update of deposit info for node operators.
If requestFullDepositInfoUpdate was called before, the update will start from the first operator.
Otherwise, it will continue from the next operator after the last updated one.
function batchDepositInfoUpdate(uint256 maxCount) external returns (uint256 operatorsLeft);
Parameters
| Name | Type | Description |
|---|---|---|
maxCount | uint256 | Maximum number of operators to update in this batch |
Returns
| Name | Type | Description |
|---|---|---|
operatorsLeft | uint256 | Number of operators left to update |
onExitedAndStuckValidatorsCountsUpdated​
Called by StakingRouter after it finishes updating exited and stuck validators counts for this module's node operators. Guaranteed to be called after an oracle report is applied, regardless of whether any node operator in this module has actually received any updated counts as a result of the report but given that the total number of exited validators returned from getStakingModuleSummary is the same as StakingRouter expects based on the total count received from the oracle.
This method is not used in the module since rewards are distributed by a performance oracle, hence it does nothing
function onExitedAndStuckValidatorsCountsUpdated() external view;
getStakingModuleSummary​
Returns all-validators summary in the staking module
function getStakingModuleSummary()
external
view
virtual
returns (uint256 totalExitedValidators, uint256 totalDepositedValidators, uint256 depositableValidatorsCount);
Returns
| Name | Type | Description |
|---|---|---|
totalExitedValidators | uint256 | Total number of validators in the EXITED state on the Consensus Layer. This value can't decrease in normal conditions |
totalDepositedValidators | uint256 | Total number of validators deposited via the official Deposit Contract. This value is a cumulative counter: even when the validator goes into EXITED state this counter is not decreasing |
depositableValidatorsCount | uint256 | Number of validators in the set available for deposit |
onWithdrawalCredentialsChanged​
Called by StakingRouter when withdrawal credentials are changed.
Changing the WC means that the current deposit data in the queue is not valid anymore and can't be deposited. If there are depositable validators in the queue, the method should revert to prevent deposits with invalid withdrawal credentials.
function onWithdrawalCredentialsChanged() external view;
getInitializedVersion​
Returns the initialized version of the contract
function getInitializedVersion() external view returns (uint64);
isValidatorSlashed​
Checks if a validator was reported as slashed
function isValidatorSlashed(uint256 nodeOperatorId, uint256 keyIndex) external view returns (bool);
Parameters
| Name | Type | Description |
|---|---|---|
nodeOperatorId | uint256 | The ID of the node operator |
keyIndex | uint256 | Index of the key in the Node Operator's keys storage |
Returns
| Name | Type | Description |
|---|---|---|
<none> | bool | True if a validator was reported as slashed |
isValidatorWithdrawn​
Check if the given Node Operator's key is reported as withdrawn
function isValidatorWithdrawn(uint256 nodeOperatorId, uint256 keyIndex) external view returns (bool);
Parameters
| Name | Type | Description |
|---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
keyIndex | uint256 | Index of the key in the Node Operator's keys storage |
Returns
| Name | Type | Description |
|---|---|---|
<none> | bool | Is validator reported as withdrawn or not |
getType​
Returns the type of the staking module
function getType() external view returns (bytes32);
Returns
| Name | Type | Description |
|---|---|---|
<none> | bytes32 | Module type |
getNodeOperator​
Get Node Operator info
function getNodeOperator(uint256 nodeOperatorId) external view returns (NodeOperator memory);
Parameters
| Name | Type | Description |
|---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
Returns
| Name | Type | Description |
|---|---|---|
<none> | NodeOperator | Node Operator info |
getNodeOperatorManagementProperties​
Get Node Operator management properties
function getNodeOperatorManagementProperties(uint256 nodeOperatorId)
external
view
returns (NodeOperatorManagementProperties memory);
Parameters
| Name | Type | Description |
|---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
Returns
| Name | Type | Description |
|---|---|---|
<none> | NodeOperatorManagementProperties | Node Operator management properties |
getNodeOperatorOwner​
Get Node Operator owner. Owner is manager address if extendedManagerPermissions is enabled and reward address otherwise
function getNodeOperatorOwner(uint256 nodeOperatorId) external view returns (address);
Parameters
| Name | Type | Description |
|---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
Returns
| Name | Type | Description |
|---|---|---|
<none> | address | Node Operator owner |
getNodeOperatorNonWithdrawnKeys​
Get Node Operator non-withdrawn keys
function getNodeOperatorNonWithdrawnKeys(uint256 nodeOperatorId) external view returns (uint256);
Parameters
| Name | Type | Description |
|---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
Returns
| Name | Type | Description |
|---|---|---|
<none> | uint256 | Non-withdrawn keys count |
getNodeOperatorBalance​
Returns tracked operator balance (active validator base stake plus tracked extra).
The tracked extra is intentionally monotonic for active validators and is reduced on withdrawal reporting, not on intermediate balance decreases, so the value serves both top-up allocation and withdrawal penalty accounting.
function getNodeOperatorBalance(uint256 nodeOperatorId) external view returns (uint256);
Parameters
| Name | Type | Description |
|---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
getNodeOperatorSummary​
depositableValidatorsCount depends on:
- totalVettedKeys
- totalDepositedKeys
- totalExitedKeys
- targetLimitMode
- targetValidatorsCount
- totalUnbondedKeys
function getNodeOperatorSummary(uint256 nodeOperatorId)
external
view
returns (
uint256 targetLimitMode,
uint256 targetValidatorsCount,
uint256 stuckValidatorsCount,
uint256 refundedValidatorsCount,
uint256 stuckPenaltyEndTimestamp,
uint256 totalExitedValidators,
uint256 totalDepositedValidators,
uint256 depositableValidatorsCount
);
Parameters
| Name | Type | Description |
|---|---|---|
nodeOperatorId | uint256 | id of the operator to return report for |
Returns
| Name | Type | Description |
|---|---|---|
targetLimitMode | uint256 | shows whether the current target limit applied to the node operator (1 = soft mode, 2 = forced mode) |
targetValidatorsCount | uint256 | relative target active validators limit for operator |
stuckValidatorsCount | uint256 | number of validators with an expired request to exit time |
refundedValidatorsCount | uint256 | number of validators that can't be withdrawn, but deposit costs were compensated to the Lido by the node operator |
stuckPenaltyEndTimestamp | uint256 | time when the penalty for stuck validators stops applying to node operator rewards |
totalExitedValidators | uint256 | total number of validators in the EXITED state on the Consensus Layer. This value can't decrease in normal conditions |
totalDepositedValidators | uint256 | total number of validators deposited via the official Deposit Contract. This value is a cumulative counter: even when the validator goes into EXITED state this counter is not decreasing |
depositableValidatorsCount | uint256 | number of validators in the set available for deposit |
getSigningKeys​
Get Node Operator signing keys
function getSigningKeys(uint256 nodeOperatorId, uint256 startIndex, uint256 keysCount)
external
view
returns (bytes memory keys);
Parameters
| Name | Type | Description |
|---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
startIndex | uint256 | Index of the first key |
keysCount | uint256 | Count of keys to get |
Returns
| Name | Type | Description |
|---|---|---|
keys | bytes | Signing keys |
getSigningKeysWithSignatures​
Get Node Operator signing keys with signatures
function getSigningKeysWithSignatures(uint256 nodeOperatorId, uint256 startIndex, uint256 keysCount)
external
view
returns (bytes memory keys, bytes memory signatures);
Parameters
| Name | Type | Description |
|---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
startIndex | uint256 | Index of the first key |
keysCount | uint256 | Count of keys to get |
Returns
| Name | Type | Description |
|---|---|---|
keys | bytes | Signing keys |
signatures | bytes | Signatures of (deposit_message_root, domain) tuples https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/phase0/beacon-chain.md#signingdata |
getNonce​
Returns a counter that MUST change its value whenever the deposit data set changes. Below is the typical list of actions that requires an update of the nonce:
- a node operator's deposit data is added
- a node operator's deposit data is removed
- a node operator's ready-to-deposit data size is changed
- a node operator was activated/deactivated
- a node operator's deposit data is used for the deposit Note: Depending on the StakingModule implementation above list might be extended
In some scenarios, it's allowed to update nonce without actual change of the deposit data subset, but it MUST NOT lead to the DOS of the staking module via continuous update of the nonce by the malicious actor
function getNonce() external view returns (uint256);
getNodeOperatorsCount​
Returns total number of node operators
function getNodeOperatorsCount() external view returns (uint256);
getActiveNodeOperatorsCount​
Returns number of active node operators
The module has no inactive Node Operator state, so active operators are all existing operators.
function getActiveNodeOperatorsCount() external view returns (uint256);
getNodeOperatorIsActive​
Returns if the node operator with given id is active
The module has no inactive Node Operator state, so active means existing.
function getNodeOperatorIsActive(uint256 nodeOperatorId) external view returns (bool);
Parameters
| Name | Type | Description |
|---|---|---|
nodeOperatorId | uint256 | Id of the node operator |
getNodeOperatorIds​
Returns up to limit node operator ids starting from the offset. The order of
the returned ids is not defined and might change between calls.
This view must not revert in case of invalid data passed. When offset exceeds the
total node operators count or when limit is equal to 0 MUST be returned empty array.
function getNodeOperatorIds(uint256 offset, uint256 limit)
external
view
returns (uint256[] memory nodeOperatorIds);
isValidatorExitDelayPenaltyApplicable​
Determines whether a validator's exit status should be updated and will have an effect on the Node Operator.
function isValidatorExitDelayPenaltyApplicable(
uint256 nodeOperatorId,
uint256 proofSlotTimestamp, // solhint-disable-line no-unused-vars
bytes calldata publicKey,
uint256 eligibleToExitInSec
) external view returns (bool);
Parameters
| Name | Type | Description |
|---|---|---|
nodeOperatorId | uint256 | |
proofSlotTimestamp | uint256 | |
publicKey | bytes | |
eligibleToExitInSec | uint256 |
Returns
| Name | Type | Description |
|---|---|---|
<none> | bool | Returns true if the contract should receive the updated status of the validator. |
exitDeadlineThreshold​
Returns the number of seconds after which a validator is considered late.
function exitDeadlineThreshold(uint256 nodeOperatorId) external view returns (uint256);
Parameters
| Name | Type | Description |
|---|---|---|
nodeOperatorId | uint256 |
Returns
| Name | Type | Description |
|---|---|---|
<none> | uint256 | The exit deadline threshold in seconds. |
getKeyAllocatedBalances​
Get cumulative top-up amounts allocated to Node Operator keys (above MIN_ACTIVATION_BALANCE)
function getKeyAllocatedBalances(uint256 nodeOperatorId, uint256 startIndex, uint256 keysCount)
external
view
returns (uint256[] memory balances);
Parameters
| Name | Type | Description |
|---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
startIndex | uint256 | Index of the first key |
keysCount | uint256 | Count of keys to get |
Returns
| Name | Type | Description |
|---|---|---|
balances | uint256[] | Allocated balances above MIN_ACTIVATION_BALANCE (wei) |
getKeyConfirmedBalances​
Get verifier-confirmed balances for Node Operator keys (above MIN_ACTIVATION_BALANCE)
function getKeyConfirmedBalances(uint256 nodeOperatorId, uint256 startIndex, uint256 keysCount)
external
view
returns (uint256[] memory balances);
Parameters
| Name | Type | Description |
|---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
startIndex | uint256 | Index of the first key |
keysCount | uint256 | Count of keys to get |
Returns
| Name | Type | Description |
|---|---|---|
balances | uint256[] | Confirmed balances above MIN_ACTIVATION_BALANCE (wei) |
getTotalModuleStake​
Returns the total tracked stake of the module in wei.
This is the sum of the activation base for active validators and tracked extra stake. The tracked extra is intentionally reduced on withdrawal reporting rather than on intermediate validator balance decreases.
function getTotalModuleStake() public view override returns (uint256);
getNodeOperatorDepositInfoToUpdateCount​
Get the number of Node Operators with outdated deposit info that requires update.
function getNodeOperatorDepositInfoToUpdateCount() external view returns (uint256 count);
_updateDepositInfo​
function _updateDepositInfo(uint256 nodeOperatorId) internal override;
_applyDepositableValidatorsCount​
function _applyDepositableValidatorsCount(
NodeOperator storage no,
uint256 nodeOperatorId,
uint256 newCount,
bool incrementNonceIfUpdated
) internal override returns (bool depositableChanged);
_allocateTopUps​
function _allocateTopUps(
uint256 maxDepositAmount,
uint256[] calldata operatorIds,
uint256[] calldata keyIndices,
uint256[] memory topUpLimits
) internal returns (uint256[] memory allocations);
_validateTopUpPublicKeys​
function _validateTopUpPublicKeys(
bytes[] calldata pubkeys,
uint256[] calldata keyIndices,
uint256[] calldata operatorIds
) internal view;
_metaRegistry​
function _metaRegistry() internal view returns (IMetaRegistry);
_canRequestDepositInfoUpdate​
function _canRequestDepositInfoUpdate() internal view override;
__BaseModule_init​
function __BaseModule_init(address admin) internal onlyInitializing;
_reportWithdrawnValidators​
function _reportWithdrawnValidators(WithdrawnValidatorInfo[] calldata validatorInfos, bool slashed) internal;
_incrementModuleNonce​
function _incrementModuleNonce() internal;
_addKeysAndUpdateDepositableValidatorsCount​
function _addKeysAndUpdateDepositableValidatorsCount(
uint256 nodeOperatorId,
uint256 keysCount,
bytes calldata publicKeys,
bytes calldata signatures
) internal virtual;
_updateDepositableValidatorsCount​
function _updateDepositableValidatorsCount(uint256 nodeOperatorId, bool incrementNonceIfUpdated)
internal
returns (bool changed);
_removeKeys​
function _removeKeys(uint256 nodeOperatorId, uint256 startIndex, uint256 keysCount, bool useKeyRemovalCharge)
internal
virtual;
_checkCanAddKeys​
function _checkCanAddKeys(uint256 nodeOperatorId, address who) internal view virtual;
_onlyNodeOperatorManager​
function _onlyNodeOperatorManager(uint256 nodeOperatorId, address from) internal view;
_nodeOperatorExists​
function _nodeOperatorExists(uint256 nodeOperatorId) internal view returns (bool);
_onlyExistingNodeOperator​
function _onlyExistingNodeOperator(uint256 nodeOperatorId) internal view;
_onlyValidIndexRange​
NOTE: The function does not revert when startIndex is equal to totalAddedKeys and keysCount is zero. The
method might be fixed later once we're sure all off-chain tooling will handle the updated behaviour.
function _onlyValidIndexRange(uint256 nodeOperatorId, uint256 startIndex, uint256 keysCount) internal view;
_onlyValidKeyIndex​
function _onlyValidKeyIndex(uint256 nodeOperatorId, uint256 keyIndex) internal view;
_getBondCurveId​
function _getBondCurveId(uint256 nodeOperatorId) internal view returns (uint256);
_getRequiredBondForNextKeys​
function _getRequiredBondForNextKeys(IAccounting accounting, uint256 nodeOperatorId, uint256 keysCount)
internal
view
returns (uint256 amount);
_checkStakingRouterRole​
function _checkStakingRouterRole() internal view;
_checkReportGeneralDelayedPenaltyRole​
function _checkReportGeneralDelayedPenaltyRole() internal view;
_checkVerifierRole​
function _checkVerifierRole() internal view;
_checkCreateNodeOperatorRole​
function _checkCreateNodeOperatorRole() internal view;
_accounting​
This function is used to get the accounting contract from immutables to save bytecode.
function _accounting() internal view returns (IAccounting);
_exitPenalties​
This function is used to get the exit penalties contract from immutables to save bytecode.
function _exitPenalties() internal view returns (IExitPenalties);
_parametersRegistry​
This function is used to get the parameters registry contract from immutables to save bytecode.
function _parametersRegistry() internal view returns (IParametersRegistry);
_requireDepositInfoUpToDate​
function _requireDepositInfoUpToDate() internal view;
_onlyRecoverer​
function _onlyRecoverer() internal view override;
__checkRole​
function __checkRole(bytes32 role) internal view override;