Try   HackMD

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

Triggerable Withdrawals

EIP-7002 fixes the principal-agent problem in delegated staking—where stakers must trust validator node operators to pre-sign exit messages, or honor future exit requests—by introducing a new voluntary exit operation that can be triggered with a validator’s withdrawal credential. This empowers stakers to withdraw staked ETH without relying on the entity holding the validator’s signing key (i.e., the staking service in a delegated staking setup) to process withdrawals.

Table of Content

General

Motivation

There are four main reasons Lido protocol should support Triggerable Withdrawals (TW):

  • Minimize trusted entities (Node Operators voluntary validator exits);
  • Unlock "truly" permissionless Staking Modules. A malicious node operator can't take the ETH hostage;
  • Fallback safety option for all node operator that lost their validator's secret key;
  • Unlock DualGov by allowing stETH holders to withdraw their funds permissionlessly;

Abstractly about eip-7002 and eip-7685

EIP-7685 describes general framework for storing contract-triggered requests. When developing a Withdrawal Credentials contract, it is important to consider that other types of requests may appear in the future (like consolidation in EIP-7251).

EIP-7002 key feature is the introduction of a stateful validator exit precompile that maintains a queue of validator exit messages originating from the execution layer.

Exit messages are regular Ethereum transactions with the validator precompile address as the target and indicate intent to exit a validator (identified by its public key). A validator exit message is valid if (a) it is signed by the Ethereum address referenced in the validator’s execution-layer (0x01) withdrawal credential (b) the validator to be exited is active on the Beacon Chain. These checks are executed by the consensus layer after the exit message makes its way to the Beacon Chain; the validator exit precompile only confirms if an exit transaction pays enough fee at the time the exit precompile is called by a withdrawal credential address.

Lido specific requirements

⚖ DualGov

Dual Governance allows stETH holders, in the worst case, to delay any proposed changes to the Lido protocol until they have fully exited (withdrawn their ETH from the protocol). Currently, the withdrawal process depends on the AO report (finalizing withdrawal requests), VEBO (requesting to exit a sufficient number of validators), and NOs (sending the exit message). By making the triggerable flow permissionless, we can eliminate the influence of VEBO and NOs, making withdrawals more secure and trustless.

Summary

  • Reduce trust assumptions on Oracles and NOs;
  • The protocol should allow Dual Governance to generate exit events in VEBO, enabling permissionless ejection from the EL side;

DualGov overview.

🌍 CSM (and other permissionless Staking Modules)

CSM is a permissionless module that compensates for reduced trust assumptions in delegated staking via bonds. There are several cases when CSM might require usage of the EL triggerable exits:

  • To trigger exits for validators that were requested to exit by VEBO but were not exited in time;
  • To trigger exits for validators demonstrating unacceptable performance for a long period of time;
  • To allow CSM Node Operators to trigger exits for their own validators in a case when validators' private keys were lost;

Summary

  • The protocol should allow CSM to request exits for any validator in the staking module;
  • The protocol should manage exit triggering for validators that were not exited voluntarily after the request.
  • The protocol component responsible for exit triggering should inform CSM about triggered exits.

CSM V2 EIP-7002 expectations

👔 DAO Gov

Lido governance should be able to do anything, unless it doesn't break DualGov assumptions.

Summury

  • The protocol should allow the Lido DAO Governance to eject any validators from the protocol, considering rational limits;

🧰 Technical part

To understand the following section, it is recommended to familiarize yourself with the operation of VEBO Oracles, particularly the process of submitting and unpacking hashes (Oracle phases).

Globally, the scope of changes will be as follows:

  • New trusted entities will be able to submit reports to VEB and thereby emit exit events.
  • Reports from these entities will be processed within the VEBO Oracle frame and will be limited by current sanity checks. Oracles reporting at the end of the frame will only be able to use the remaining frame's exit quota (exit limits).
  • TW in the protocol will allow anyone to provide proof of a validator's exit request and trigger the exit through the EL using the TW precompiled contract.
  • Anyone can prepare proof and deliver validator's state from CL to the VEB to notify Staking Modules about exit status.
  • The Accounting Oracle will no longer be responsible for reporting stuck keys (Accounting extra data details). This responsibility will now be handled by a dedicated bot that uses permissionless methods in VEB to deliver proofs that the validator was delinquent.
  • Update Staking Module interface and implement bonds in Curated Modules to correctly TW actions.

Affected protocol parts

The following parts will be affected:

New concepts

VEB - Validator Exit Bus Contract. Contains the following logic:

  • Submitting and storing report hashes;
  • Emitting validator exit events;
  • Triggering validator exits on the EL through the WC contract;
  • Reporting delinquent keys;

VEBO - Validator Exit Bus Oracle Contract. Contains next logic:

  • Storing frame's report hash.
  • Contains Oracles specific submit and unpack report hashes.

Delinqued key/validator - a key/validator that was unable to exit on time. Delinquent keys do not lose their status even if they are eventually exited afterward.

VEB specification

Emiting exit events

Events emiting in VEBO takes two steps:

  • First phase - Submit Report Hash
    Trusted entities build a report, calculate the report hash, and send it (e.g., Lido Oracles, Dual Governance, Governance, Staking Modules). Report hashes are saved to the VEB.
  • Second phase - Deliver Report Data
    Submit report data and emit exit events, taking exit limits into account.

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

First Phase - Submit report hash

The first phase involves submitting and saving the hash in the contract.

Lido Oracles

The first phase of the Oracle process won't change. Oracles deliver report hashes to the Hash Consensus contract. When a quorum is reached, the report hash is delivered to VEBO via submitReport method. The report hash from Oracles can only be used to emit events by the Oracles themselves.

function submitReport(uint256 slot, bytes32 report, uint256 consensusVersion) external;

Trusted entities

Trusted entities submit a report hash to the VEB contract via the submitReportHash method. This hash is instantly saved to the VEB (in the reportHashes mapping) and can be used by anyone to deliver report data during the second phase.

function submitReportHash(bytes32 reportHash) external;

reportHashes mapping will have next signature:

struct DeliverHistory { // Block number of deliver transaction uint32 blockNumber; // Last index of the key for which the exit event was emitted uint32 lastDeliveredKeyIndex; }; struct ReportStatus { // Total items count in report (on creation 0) uint32 totalItemsCount; // Total processed items in report (by default 0) uint32 deliveredItemsCount; // Contract version on the moment of creation uint32 contractVersion; // Data delivery history DeliveryHistory[] deliverHistory; }; mapping (bytes32 => ReportStatus) public reportHashes;

Invalidating report hashes

The ReportStatus structure includes a contractVersion field, indicating the contract version at the time the hash was submitted. This field is required to prevent the delivery of report data if the report hash was submitted under a previous contract version, thereby avoiding unpredictable behavior in the VEB.

Schema

Triggerable Withdrawals (2)

Second Phase - Deliver report data and Emit exit events

Oracles flow

// contract VEBO function submitReportData(ReportData calldata data, uint256 contractVersion)

The Oracle unpacks the full report and emits events for all items in the report. Oracle exit limits are calculated dynamically and depend on the number of events emitted in the reference frame (details). During this phase, the ReportStatus record is added to the reportHashes mapping.

Triggerable Withdrawals (3)

Trustless flow

function emitExitEvents(ReportData calldata data, uint256 contractVersion)

Anyone can emit exit events by providing report data, the hash of which is stored in the VEB. If reportsHashes.totalItemsCount is 0 update and save the report length. Starting from deliveredItemsCount index, emit events for keys from the report. Once all keys are processed or the number of exits in the current frame reaches the exit limits from the OracleSanityCheck contract, stop emitting events and save last proceed key index + 1 into deliveredItemsCount.

Assumptions:

  • An actor cannot deliver specific keys; all events are emitted for keys one by one in the order specified in the report data;
  • An actor cannot choose how many keys to emit events for; exit events are emitted up to the exit limit or until the key list ends;
  • An actor cannot emit events for a report hash that was submitted with an outdated contractVersion;

image

Exit limits

For security reasons, the Lido protocol cannot create more exit requests in a single frame than specified in the OracleReportSanityChecker contract. This means that keys presented in the report but lacking an exit event should not be used as indicators to exit a validator and cannot be used to exit it via a TW.

Each frame has an exit quota that cannot be exceeded. Therefore, the sum of emitted exit events in a frame and the Oracle's report for that frame must not exceed this quota.

The Offchain Oracle's report is considered the final report for the frame it is based on, even if the transaction is included in the next frame.

Examples

For next examples assume that:

  • A report frame consists of 4 epochs;
  • The exit limit for one frame is 10 validators;

In the next example, Frame 2 contains two deliver report transactions:

  • 5 exit events were emitted for the report #1, so #1 was fully delivered (5 exit quota left);
  • 5 exit events were emitted for the report #2, it were partially delivered, because was limited by exit quota (0 exit quota left);
  • The Oracle report will contain no validators, as the entire exit quota was used;

Triggerable Withdrawals (18)

In Frame 3, exit events were emitted for all remaining keys from report #2. The Oracle can report up to 5 keys for exit.

Triggerable Withdrawals (14)

Validator's exit flow

The main operations involving validators are as follows:

image

Once a validator is marked for exit in the VEB, the Node Operator (NO) should send an exit message on the CL. Simultaneously, anyone can trigger the withdrawal on the EL.

Anyone can provide proof that a validator did not exit on time, and this information will be relayed to the Staking Module. All further decisions regarding penalties are made by the Staking Module.

Classic CL exit

Exits using voluntary messages on the CL remain our primary method for withdrawing validators. NO hosts validator ejector that sending exit message as soon as it sees event in VEB contract.

Triggerable exits in VEB

The following function verifies that the hash of the provided report data exists in the mapping and that events for the keys have been emitted. It then triggers exits on the EL via the Withdrawal Vault contract.

function triggerExits(ReportData calldata data, uint32[] keyIndexes,)

This function contains next steps:

  • Verifies that the provided data hash exists in the reportHash mapping;
  • Confirms that events were emitted for the provided key indexes beforehand;
  • Sends a request to the Withdrawal Vault contract to trigger exits for the provided keys;
  • Sends notification to Staking Router contract with keys data that were triggered to exit.

Triggerable Withdrawals (5)

Delinquent keys report

Delinquent keys are keys for which validators did not start exiting before the end of the voluntary exit period. Delinquent keys can be permissionlessly reported to the VEB contract with corresponding proof that the required time has passed.

Those keys should be penalized by Staking Modules. Our current penalties concept is specific for permissionfull staking modules.

Anyone can deliver proof that validator was delayed:

function submitProofOfDelinquent(ReportData calldata data, Witness[] witness, BeaconBlock beconBlock) external;

This method will support batch proof delivery to optimize gas costs.

Triggerable Withdrawals (6)

Delinquent hook to module

After receiving and verifying the proof, the VEB notifies the Staking Router about the delinquent validators. This data is then provided to the Staking Modules.

Essentially, the module notification consists of the validator's identifier within the Lido protocol, the time when its exit was requested, and the time it remained active. Staking modules use the time difference between the exit event and the timestamp when the validator was not in an exiting status to determine whether the node operator should be penalized.

Staking Modules should take into account that some validators could be not able to exit because of CL restrictions.

struct DelinquentStatus { // Validators indetification uint32 stakingModuleId; uint32 nodeOperatorId; uint32 keyIndex; // Timestamp when validator was activated uint32 activatedTs; // Timestamp when exit event was emited uint32 exitedTs; // Timestamp of block on which validator were still active uint32 activeTs; }

Direct Triggerable Exit

Trusted entities will be able to directly emit exit events and request validators through the TW to exit them without delivering hashes and any proving.

This type of TW should also comply with the sanity report limits.

function triggerExitsDirectly(ValidatorsData calldata data) external;

The flow is as follows:

  • Verify that the provided validator count fits within the limits;
  • Provide the validator list to the Withdrawal Vault TW method;

Triggerable Withdrawals (7)

Offchain tooling

Lido Oracles

AO

Since stuck keys are deprecated, all functionality related to this feature should be removed from AO.

VEBO

  • Remove the delayed predicate;
  • Remove the weight predicate;
  • Restructure VEBO limits so that all entities share common limits for a frame;
  • Remove the last NO exited index;

Oralce will fetch exit events only for the last 28 days to track which validators have already been requested for exit. If this period has already passed, it is possible that the same validator might be requested to exit again. However, this scenario is unlikely because in case of stuck validators they will be exited using TW.

Delinquent Deliver bot / CLI

A bot that will generate proof that a validator was delinquent and deliver it to the protocol.

An analog of the CSM Prover tool.

Exit Trigger bot

The Exit Trigger bot should be accessible for anyone to use to exit validators. It should feature a straightforward interface that allows for flexible exiting of any validators.

Goals:

  • Develop a trigger exit policy;
  • Create a bot capable of delivering WE proofs with various fee strategies;
  • Make this an open-source project and include a CLI within the bot to facilitate the creation of selected Triggerable Withdrawal requests;

Ejector allowlist

Purpose of protection

Generally, what is this protection for:
If a Node Operator (NO) relies on third-party providers for the ejector, these providers could potentially return falsified data, such as fake events. To address this security risk, the ejector verifies that the signatures associated with these events were created using Oracle accounts.

For example, if a malicious provider generates 10 fake events, they will be ignored by the ejector because they would be signed with a non-Oracle private key.

After TW implementation

After TE, emitting exit events can be performed by anyone since it is permissionless, and transaction signature verification cannot be done.

To mitigate this security issue, all Node Operators (NOs) should run their ejectors on their own local nodes.

Useful links