# Penalty and slash base errors

Penalty or slash math using the wrong base: full duration, config threshold, or one reward stream

_Area: DeFi accounting and math bugs. Seen in 4 disclosed reports; latest 2024-06-25. Updated 2026-10-23._

## How it works
A penalty or slash is meant to recover a specific shortfall or offset a specific gain. The bug is that the amount is computed from a base that does not match the obligation: a config cap instead of the real shortfall, a user-chosen duration instead of the internal reward epoch, one reward stream instead of the combined balance, or a per-item delta that can be replayed. The assumption that breaks is that the formula's inputs represent the true loss. When they don't, the penalty is either too small to cover the shortfall or too large for the operator.

## Where it shows up
- A slash/recovery function that caps by a config value (e.g. `minThreshold`) while the caller already knows the true shortfall [E2](https://bugbountylibrary.com/r/c4%3A2023-06-stader%3AM-06.md)
- Penalty formulas multiplying a rate by a user-supplied duration, when rewards accrue in fixed internal cycles [E3](https://bugbountylibrary.com/r/c4%3A2022-12-gogopool%3AH-03.md)
- Penalty decisions that read one balance/vault while the penalty references rewards held elsewhere [E4](https://bugbountylibrary.com/r/c4%3A2023-06-stader%3AM-12.md)
- Per-call penalty computed from a fixed proof value versus a per-item value, with no ordering constraint between items [E1](https://bugbountylibrary.com/r/c4%3A2024-03-dittoeth%3AM-08.md)
- Any `min(...)`, threshold, or epoch constant sitting between the computed loss and the slashed amount

## How to review
Trace the penalty from the obligation to the charged amount and confirm the base equals the actual loss:
- Does the function receive or recompute the true shortfall, or does it substitute a threshold? The invariant: slashed amount should equal the remaining penalty, capped only by available balance.
- Does every duration in the formula match the epoch in which rewards are actually distributed? [E3](https://bugbountylibrary.com/r/c4%3A2022-12-gogopool%3AH-03.md)
- Are all reward streams the penalty references aggregated before deciding to slash? [E4](https://bugbountylibrary.com/r/c4%3A2023-06-stader%3AM-12.md)
- For per-item penalties, is there a constraint preventing the same proof from being replayed against each item to sum a larger delta? [E1](https://bugbountylibrary.com/r/c4%3A2024-03-dittoeth%3AM-08.md)

## Variants seen
- Cap-by-threshold: slash limited to `minThreshold` instead of remaining penalty, under-covering auctions [E2](https://bugbountylibrary.com/r/c4%3A2023-06-stader%3AM-06.md)
- Duration mismatch: full staking duration used where 14-day cycles apply, over-slashing up to 26x [E3](https://bugbountylibrary.com/r/c4%3A2022-12-gogopool%3AH-03.md)
- Partial balance: only CL earnings counted, EL rewards in another vault ignored, so solvent operators still slashed [E4](https://bugbountylibrary.com/r/c4%3A2023-06-stader%3AM-12.md)
- Replayable per-item delta: one redemption split into N-1 disputes, each recomputed against a higher CR [E1](https://bugbountylibrary.com/r/c4%3A2024-03-dittoeth%3AM-08.md)

## Impact and severity
Medium to high. Outcomes ranged from under-recovery of operator shortfalls (auctions too small) [E2](https://bugbountylibrary.com/r/c4%3A2023-06-stader%3AM-06.md) to over-slashing operators many times the missed yield [E3](https://bugbountylibrary.com/r/c4%3A2022-12-gogopool%3AH-03.md) and slashing operators who had sufficient combined balance [E4](https://bugbountylibrary.com/r/c4%3A2023-06-stader%3AM-12.md). Severity rises when the wrong base is systematic (every slash) rather than edge-case, and when the penalty drives collateral or auction sizing.

## Why fixes fail
Evidence shows fixes that address one input but not the base: capping by threshold still ignores the true shortfall [E2](https://bugbountylibrary.com/r/c4%3A2023-06-stader%3AM-06.md); counting one vault still misses the other [E4](https://bugbountylibrary.com/r/c4%3A2023-06-stader%3AM-12.md). Fixes must recompute from the actual obligation, not patch the constant.

## Evidence
- E1: https://bugbountylibrary.com/r/c4%3A2024-03-dittoeth%3AM-08.md
- E2: https://bugbountylibrary.com/r/c4%3A2023-06-stader%3AM-06.md
- E3: https://bugbountylibrary.com/r/c4%3A2022-12-gogopool%3AH-03.md
- E4: https://bugbountylibrary.com/r/c4%3A2023-06-stader%3AM-12.md
