Links:
The diagram below illustrates the deposit processes in Lido:
A user submits ether to the Lido
contract in return for a share of the total Lido stETH pool. Before being deposited, user-submitted funds accumulate on the Lido
contract’s balance. In technical terms, we refer to this ether as buffered or in the deposit buffer.
Lido, however, does not perform the deposit as soon as the buffer reaches 32 ether. This would be prohibitively expensive. Instead, a special off-chain bot monitors the network gas price and performs a batch deposit in a single transaction paid for by the protocol whenever the buffer reaches the size that justifies the cost of the transaction.
On the protocol level, Lido interacts with node operators via NodeOperatorsRegistry
. This contract manages the list of node operators, stores their signing keys, and decides which keys will be used for the next batch deposit based on which node operators have the least active validators. Once voted in, the node operator is added to NodeOperatorsRegistry
. Then, the operator can add signing keys to the same contract. When the keys are submitted to DepositContract
, the respective validators are placed in the activation queue. Once activated, they start participating in the consensus.
Each deposit to DepositContract
must come with withdrawal credentials (WC), allowing the sender to withdraw the funds and potential rewards in the future, once withdrawals are enabled. All Lido deposits are submitted with the Lido-approved WC to ensure that only Lido can withdraw user funds.
In October 2021, a critical vulnerability was reported to the Lido bug bounty program. Because DepositContract
associates the validator’s key with the first valid deposit, this exploit allowed a node operator to pre-submit a minimal deposit of 1 ether with their own WC, thus, making any subsequent deposits with the same key withdrawable only with the initial WC.
As per LIP-5: Mitigations for deposit front-running vulnerability, a deposit security scheme was introduced. Before submitting a batch deposit, the guardian committee ensures there were no malicious pre-deposits and signs a message containing the deposit parameters:
depositRoot
from DepositContract
, the Merkle root of all deposits;keyOpsIndex
from NodeOperatorsRegistry
, a nonce of key operations;