User Stories for RPIP-73: rETH Protection From Underperforming Nodes¶
RPIP-73 introduces a permissionless, optimistic on-chain challenge mechanism to exit significantly underperforming or abandoned Rocket Pool validators. The mechanism is designed to protect rETH yield from being dragged down by offline validators while utilising a high economic bond to deter griefing and false challenges.
Challenge Lifecycle Diagram¶
The diagram below illustrates the lifecycle of a performance challenge under RPIP-73:
flowchart TD
Start([One or more validators underperform]) --> Challenge[Challenger submits challenge against a list of validators]
Challenge --> LockBond[100 RPL Bond locked]
LockBond --> Period{24-Hour Challenge Period}
Period -- Defender proves participation in >=1 epoch for a listed validator --> Defeat[Entire list Defeated]
Period -- Defender proves a listed validator's activation_epoch > start_epoch --> Defeat
Defeat --> Slash[Challenger's 100 RPL sent to Defender]
Slash --> EndDefeated([Challenge Cancelled])
Period -- 24 hours pass uncontested --> Finalise[Challenger/anyone finalises exit]
Finalise --> Queue[Validators queued for Exit RPIP-80]
Queue --> Refund[100 RPL Bond refunded to Challenger]
Refund --> EndExited([Validator Exits Initiated])
Actors¶
- Challenger: A Node operator with RPL staked and governance locking approved, monitors validator performance. They initiate challenges against a list of one or more underperforming validators by locking a bond.
- Defender: A Node operator with RPL staked and governance locking approved, attempts to either find a single valid epoch for a listed validator, or prove a listed validator wasn't yet active, to defeat the entire challenge and claim the challenger's bond.
- pDAO / Security Council: The governance bodies responsible for enabling/disabling the mechanism and tuning the protocol parameters.
- rETH Holders: The beneficiaries of the proposal, whose yield is protected by the removal of non-performing validators.
Protocol Parameters¶
| Parameter | Type | Initial Value | Description |
|---|---|---|---|
performance_exits_enabled* |
bool |
true |
Emergency pause/unpause for the challenge mechanism. |
performance_period |
Epochs |
44032 (~200 days) |
The rolling window used to evaluate validator performance. |
proof_buffer |
Epochs |
225 (Guardrail: > 10) |
Extra time after performance_period during which a challenge's start_epoch is still valid, giving challengers time to detect underperformance and generate proofs. |
performance_threshold |
pct |
94 |
The minimum performance percentage required to avoid challenges. |
performance_challenge_period |
Hours |
24 |
The time window allowed for anyone to defeat a challenge. |
performance_challenge_bond |
RPL |
100 (Guardrail: > 20) |
The amount of RPL that a challenger must lock. |
*Modifiable by the Security Council without delay.
Epic 1: Parameter Management¶
1.1: Emergency Enable/Disable¶
As a Security Council Member,
I want to toggle performance_exits_enabled on or off,
So that I can pause the challenge mechanism during consensus bugs, network splits, or security incidents.
- Acceptance Criteria:
- Only Security Council proposal can toggle the setting.
- When disabled:
- New challenges cannot be created.
- Active challenges can still be defeated by defenders (to prevent challengers from being trapped if a pause occurs during their challenge window).
- Active challenges cannot be finalised/exited.
- Toggling emits an event.
1.2: Parameter Tuning¶
As the pDAO,
I want to adjust the performance thresholds, periods, and bonds via on-chain governance voting,
So that the protocol can adapt to changes in network performance expectations.
- Acceptance Criteria:
- Updates to
performance_period,proof_buffer,performance_threshold,performance_challenge_period, andperformance_challenge_bondcan only be initiated by pDAO proposal. - The update proposal reverts with a clear error when attempting to set
proof_bufferto a value less than or equal to 10 epochs. - The update proposal executes only when setting
performance_challenge_bondto any value greater than or equal to 20 RPL, emitting a event. - The update proposal reverts with a clear error when attempting to set
performance_challenge_bondto a value less than 20 RPL. - Parameter updates do not retroactively alter the rules or bonds of active challenges.
- Updates to
Epic 2: Challenging Validator Performance¶
2.1: Challenge a List of Validators¶
As a Challenger,
I want to submit a performance challenge on-chain for a list of underperforming validators by providing the start epoch, the list of missed epochs, and locking a single required RPL bond,
So that I can exit the underperforming validators in one transaction.
- Acceptance Criteria:
- The challenger must call
proposeValidatorExitproviding:validatorIndicesof the target validators (one or more).startEpoch, which must be greater thancurrentEpoch - performance_period - proof_buffer.- A representation of the
performance_period * (1 - performance_threshold)epochs (e.g. 2,642 epochs) where the listed validators supposedly missed target attestations.
- The contract locks a single
performance_challenge_bondRPL from the challenger node operator stake, covering the whole list. - The transaction reverts if:
performance_exits_enabledis false.- Any validator in the list is already in an active challenge.
- Any validator in the list is already queued for exit.
- The number of epochs provided is less than
performance_period * (1 - performance_threshold). startEpochis not greater thancurrentEpoch - performance_period - proof_buffer.- Any provided epoch lies outside the
[startEpoch, min(currentEpoch, startEpoch + performance_period)]range.
- Emits an event.
- The challenger must call
2.2: Defeat an Invalid Challenge¶
As a Defender
I want to submit proof of either a single successful timely target attestation for one of the challenged epochs, or that a listed validator was not yet active when the challenge claims it missed attestations,
So that I can cancel the exit process for the entire list and claim the challenger's locked RPL bond.
- Acceptance Criteria:
- The defender must call
defeatChallengeproviding one of the following proofs for at least one validator in the challenged list:- Attestation proof:
challengeIdorvalidatorIndexof the active challenge.- The specific epoch number being proven.
- Proof that this epoch was included in the challenger's dataset.
- A proof verifying that
previous_epoch_participationin the Beacon State for that epoch contains a timely target attestation.
- Activation proof:
challengeIdorvalidatorIndexof the active challenge.- A proof that the validator's
activation_epochis greater than the challenge'sstartEpoch.
- Attestation proof:
- The contract verifies the proof using the on-chain Beacon block root history (e.g. EIP-4788).
- If either proof is verified for any validator in the list:
- The entire challenge (covering all listed validators) is marked as defeated
- The locked
performance_challenge_bondRPL is sent to the defender, minus a burn amount. - Emits an event.
- The transaction reverts if proof is unverified, or the
performance_challenge_periodhas expired, or the challenge was already finalised/defeated.
- The defender must call
2.3: Finalise Uncontested Challenge¶
As a Challenger,
I want to finalise a challenge once the performance_challenge_period has elapsed without being defeated,
So that all the validators in my list are exited and my locked RPL bond is returned.
- Acceptance Criteria:
- Anyone can call
finalizeChallengeafterperformance_challenge_period(24 hours) from the challenge submission. - The transaction reverts if:
- The challenge was defeated.
- The 24-hour period has not yet elapsed.
- If successful:
- All validators in the challenged list are registered as "requested to exit" in the protocol (initiating RPIP-80 exit flow).
- The locked RPL bond is returned to the challenger.
- The challenge is marked as finalised and removed from active storage.
- Emits an event.
- Anyone can call
Epic 3: Monitoring & Tooling¶
3.1: Smart Node Alerting¶
As a Rocket Pool Node Operator,
I want to see on my Grafana dashboard if any of my validators are challenged,
So that I am aware of the challenge
- Acceptance Criteria:
- The alert displays whether any of my validators are challenged
3.2: Community Monitoring¶
As the Rocket Pool community, I want to see what nodes/validators have been challenged, So that we can see the system exiting under-performing nodes
- Acceptance Criteria:
- Website feature that displays summary of challenges
Questions¶
- ~~Support multiple challenges in single transaction?~~ Resolved: yes — RPIPs PR #384 introduces list-based challenges covering one or more validators under a single bond.
- Should we enforce a max concurrent challenges?
- Should owner have the opportunity to defeat first? (prevent pile on and provides NO with bond)
- Burn on defeat? for the RPL transfer issue - not an issue with megapool but is for minipool
- Do we use merkle tree submission? or call data?
- There is currently no profit motive to challenge... I guess there is if there is a queue