# Liquidation griefing via cheap state reset

Dust repayments, cooldown resets or mutable loan state that block repayment or liquidation and force bad debt

_Area: DeFi oracles, liquidations and flash loans. Seen in 3 disclosed reports; latest 2025-08-11. Updated 2026-11-06._

## How it works
Liquidation and repayment depend on state that the borrower, or anyone, can rewrite cheaply. The assumption that breaks is that the state a liquidation or repayment reads is stable between the moment it is checked and the moment it is used. Three shapes appear: a cooldown timer that any new call resets, even with 1 wei [E2](https://bugbountylibrary.com/r/cantina%3Ajigsaw_june2025%3A3.1.9.md); a stored loan entry that a permissionless function deletes and rewrites, so a repayment validated against the old hash reverts [E3](https://bugbountylibrary.com/r/c4%3A2024-04-gondi%3AH-10.md); and a peripheral contract that recomputes a protocol invariant with different loop bounds than the canonical check, so its liquidation path reverts on an edge case [E1](https://bugbountylibrary.com/r/sherlock%3A2023-10-perennial%3AM-9.md). In each case the attacker pays dust or nothing to keep the position unliquidatable or the debt unrepayable.

## Where it shows up
- Strategies requiring a user-initiated cooldown before withdrawal, where the cooldown call is permissionless or accepts any amount [E2](https://bugbountylibrary.com/r/cantina%3Ajigsaw_june2025%3A3.1.9.md)
- Functions that validate a caller-supplied struct by hash-equality against a mutable mapping entry [E3](https://bugbountylibrary.com/r/c4%3A2024-04-gondi%3AH-10.md)
- Any other function that deletes or rewrites that same mapping entry (merge, add tranche) [E3](https://bugbountylibrary.com/r/c4%3A2024-04-gondi%3AH-10.md)
- Peripheral contracts (invokers, vaults, libraries) that reimplement a core contract's closable/liquidation math [E1](https://bugbountylibrary.com/r/sherlock%3A2023-10-perennial%3AM-9.md)
- Loop bounds that include the current in-flight position (`id <= currentId`) where the core uses `id < currentId` [E1](https://bugbountylibrary.com/r/sherlock%3A2023-10-perennial%3AM-9.md)

## How to review
For each liquidation or repayment path, list every piece of state it reads and ask who can change it and at what cost. The invariant: no party other than the position owner's own solvency change can make a liquidation or repayment revert, and no dust-sized action can extend a blocking window. Concretely: can a cooldown timer be reset by a third party or with 1 wei [E2](https://bugbountylibrary.com/r/cantina%3Ajigsaw_june2025%3A3.1.9.md)? Does any permissionless function rewrite the entry that repayment validates against [E3](https://bugbountylibrary.com/r/c4%3A2024-04-gondi%3AH-10.md)? Does the peripheral closable calculation mirror the core's exact loop bounds and ordering, including whether the current pending position counts [E1](https://bugbountylibrary.com/r/sherlock%3A2023-10-perennial%3AM-9.md)?

## How finders spotted it
- Compared the core Market's closable loop (`id < currentId`) against the peripheral loops (`id <= currentId`) and reasoned through the case where the current pending position changes within the active oracle version [E1](https://bugbountylibrary.com/r/sherlock%3A2023-10-perennial%3AM-9.md)
- Compared Elixir's two-step cooldown withdrawal against other staking strategies, noticed the timer resets on any new cooldown call, reasoned that liquidation must withdraw from the strategy, and tested poking with 1 wei [E2](https://bugbountylibrary.com/r/cantina%3Ajigsaw_june2025%3A3.1.9.md)
- Read `repayLoan`'s hash check against the mutable `_loans` mapping and noticed `mergeTranches` deletes and rewrites that entry [E3](https://bugbountylibrary.com/r/c4%3A2024-04-gondi%3AH-10.md)

## Variants seen
- Cooldown reset by dust deposit blocking collateral withdrawal for liquidation [E2](https://bugbountylibrary.com/r/cantina%3Ajigsaw_june2025%3A3.1.9.md)
- Front-run state rewrite making borrower repayment revert, forcing foreclosure [E3](https://bugbountylibrary.com/r/c4%3A2024-04-gondi%3AH-10.md)
- Off-by-one loop bound in a peripheral reimplementation making liquidation revert [E1](https://bugbountylibrary.com/r/sherlock%3A2023-10-perennial%3AM-9.md)

## Impact and severity
Blocked liquidation leaves bad debt [E2](https://bugbountylibrary.com/r/cantina%3Ajigsaw_june2025%3A3.1.9.md); blocked repayment forces NFT collateral foreclosure, and merging tranches to length 1 lets the lender claim the NFT directly [E3](https://bugbountylibrary.com/r/c4%3A2024-04-gondi%3AH-10.md); reverting liquidations in the peripheral path [E1](https://bugbountylibrary.com/r/sherlock%3A2023-10-perennial%3AM-9.md). Severity rises when the griefing action is dust-cheap and permissionless [E2](https://bugbountylibrary.com/r/cantina%3Ajigsaw_june2025%3A3.1.9.md) and when it chains into a second weakness that pays the attacker [E3](https://bugbountylibrary.com/r/c4%3A2024-04-gondi%3AH-10.md).

## Evidence
- E1: https://bugbountylibrary.com/r/sherlock%3A2023-10-perennial%3AM-9.md
- E2: https://bugbountylibrary.com/r/cantina%3Ajigsaw_june2025%3A3.1.9.md
- E3: https://bugbountylibrary.com/r/c4%3A2024-04-gondi%3AH-10.md
