Skip to content

Validator Balance Tracker Silent Underflow During Penalty Exceeding Balance #24

Description

@JamesEjembi

Problem Statement / Feature Objective

The validator balance tracker deducts penalties (slashing, inactivity leaks) as score = balance - penalty. When the penalty exceeds the current balance (e.g., a validator with 1 ETH balance receives a slashable offense penalty of 1.5 ETH), the subtraction underflows using saturating arithmetic that silently clamps to zero without recording the excess as a debt. This allows the validator to re-activate after the epoch boundary with a zero balance, bypassing the ejection threshold check.

Technical Invariants & Bounds

  • Effective balance: 1 ETH = 1e9 Gwei (u64).
  • Slashing penalty: 1/32 of effective balance (whistleblower) + 1/32 (correlation).
  • Inactivity leak penalty: proportional to (epochs_since_finality)^2.
  • u64 saturating sub: balance.saturating_sub(penalty) => 0 if penalty > balance.
  • Ejection threshold: 16 ETH minimum; validators below this are ejected.
  • A validator with underflow to 0 can remain active for one more epoch.

Codebase Navigation Guide

  • src/validator/balance-tracker.rs - apply_penalty() and apply_reward().
  • src/validator/validator-set.rs - update_effective_balances() and eject_validators().
  • src/slashing/penalty-calculator.rs - compute_slashing_penalty() and compute_inactivity_penalty().
  • tests/validator/balance_underflow_test.rs - penalty edge case tests.

Implementation Blueprint

  1. In src/validator/balance-tracker.rs, change apply_penalty() from saturating_sub to checked_sub. If penalty > balance, return an InsufficientBalance error instead of silently clamping.
  2. When InsufficientBalance is returned, the slashing engine should mark the validator for forced ejection and record a debt in a separate Debts mapping.
  3. In eject_validators(), treat any validator with an outstanding debt as eligible for immediate ejection regardless of effective balance.
  4. Add a test: validator with 1 ETH balance receives a 1.5 ETH penalty; assert the validator is ejected in the same epoch.
  5. Add a property test that randomizes balances and penalties and asserts effective_balance never exceeds MAX_EFFECTIVE_BALANCE after processing.

Metadata

Metadata

Assignees

Labels

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions