# Slashed valid party via stale or default flags

Flags compared against zeroed structs or default mappings, so valid parties get slashed

_Area: DeFi accounting and math bugs. Seen in 3 disclosed reports; latest 2024-12-09. Updated 2026-10-29._

## How it works
Slashing and challenge logic trusts a per-party flag or timestamp to decide whether a party is at fault. The bug is that this flag is read from a freshly declared memory struct or a mapping entry that was never written, so it holds the default zero. A comparison like `storedLoss > userLoss` or a guard like `!challenge.finished` then evaluates against zero instead of the party's real history. The assumption that breaks: that the flag reflects this party's actual state. When it does not, a valid party is treated as already-failed and is slashed or has its stake forfeited.

## Where it shows up
- A comparison against a struct field before that struct is loaded from storage [E1](https://bugbountylibrary.com/r/c4%3A2023-12-ethereumcreditguild%3AH-04.md)
- `!mapping[key].boolField` guards where the key may not exist, so default `false` makes `!field` true [E3](https://bugbountylibrary.com/r/sherlock%3A2024-08-morphl2%3AM-11.md)
- Future events or penalties queued at creation time without being gated on the intermediate state transition actually happening [E2](https://bugbountylibrary.com/r/sherlock%3A2024-12-babylon%3AH-3.md)
- Asymmetric scheduling: one outcome is conditional, the penalty is not [E2](https://bugbountylibrary.com/r/sherlock%3A2024-12-babylon%3AH-3.md)
- Cleanup or pause paths that reset a flag for entries that were never set [E3](https://bugbountylibrary.com/r/sherlock%3A2024-08-morphl2%3AM-11.md)

## How to review
For each slash/challenge decision, trace where the deciding flag is written and confirm it is read from storage for the same party before any comparison. The invariant: a party is penalized only if its own recorded state says so; default zero must never satisfy a penalty condition. Check ordering of storage load vs. comparison [E1](https://bugbountylibrary.com/r/c4%3A2023-12-ethereumcreditguild%3AH-04.md), and check that every queued penalty is conditioned on the state transition that justifies it [E2](https://bugbountylibrary.com/r/sherlock%3A2024-12-babylon%3AH-3.md). For boolean guards, ask what the default value means for a nonexistent entry [E3](https://bugbountylibrary.com/r/sherlock%3A2024-08-morphl2%3AM-11.md).

## Variants seen
- Memory struct zeroed before assignment, compared against historical loss [E1](https://bugbountylibrary.com/r/c4%3A2023-12-ethereumcreditguild%3AH-04.md)
- Expired-event penalty fires though the delegation never became active [E2](https://bugbountylibrary.com/r/sherlock%3A2024-12-babylon%3AH-3.md)
- `!finished` true for empty challenge struct, resetting `inChallenge` and slashing a valid prover [E3](https://bugbountylibrary.com/r/sherlock%3A2024-08-morphl2%3AM-11.md)

## Impact and severity
Valid stakers or provers lose funds or stake; in E1 new stakers are slashed immediately on entry. Severity is high because the loss is direct and hits honest parties. It worsens when the bad state persists across many parties (E1: every new staker into an affected gauge) or when a pause path triggers it broadly [E3](https://bugbountylibrary.com/r/sherlock%3A2024-08-morphl2%3AM-11.md).

## Why fixes fail
Evidence does not show incomplete fixes.

## Evidence
- E1: https://bugbountylibrary.com/r/c4%3A2023-12-ethereumcreditguild%3AH-04.md
- E2: https://bugbountylibrary.com/r/sherlock%3A2024-12-babylon%3AH-3.md
- E3: https://bugbountylibrary.com/r/sherlock%3A2024-08-morphl2%3AM-11.md
