# Liquidation path skips close invariant

Check every exit path (liquidation, force-close, self-liquidate) re-enforces the invariant normal close enforces

_Area: DeFi oracles, liquidations and flash loans. Seen in 2 disclosed reports; latest 2024-05-09. Updated 2026-10-25._

## How it works
A protocol enforces a safety invariant on the normal exit path — a health check, an open-interest cap, a penalty calculation — and assumes that is enough. But liquidation, self-liquidation and force-close are separate code paths that mutate the same state. If they skip the check, an actor can reach a state the normal path forbids by routing through liquidation instead. The broken assumption is "all exits go through the guarded function."

## Where it shows up
- A modifier or require on `close`/`closeMakeFor` with no equivalent in `liquidate`/`closeAll`/force-close [E2](https://bugbountylibrary.com/r/sherlock%3A2023-05-perennial%3AM-10.md)
- Two-step order flows (request, then keeper execute) where health is checked at request time but not at fill time [E1](https://bugbountylibrary.com/r/sherlock%3A2024-05-elfi-protocol%3AH-1.md)
- Share price or NAV read from an external pool's instantaneous liquidity that a permissionless actor can move [E3](https://bugbountylibrary.com/r/sherlock%3A2022-09-sherlock%3AM-4.md)
- Self-liquidation reachable by the position owner, not just third-party keepers [E2](https://bugbountylibrary.com/r/sherlock%3A2023-05-perennial%3AM-10.md)

## How to review
Enumerate every function that mutates position or account state (normal close, liquidation, self-liquidation, admin force-close, order fill). For each invariant enforced on one path, confirm it is enforced on all others, or that the path is provably unreachable by the party who benefits. For order fills, confirm health is re-validated at execution price, not just at request. For NAV, confirm the price source cannot be transiently moved by a borrower or LP within one transaction.

## Variants seen
- Missing post-open liquidation check on keeper execution, producing instantly-underwater positions [E1](https://bugbountylibrary.com/r/sherlock%3A2024-05-elfi-protocol%3AH-1.md)
- Self-liquidation bypassing a global open-interest invariant to spike funding [E2](https://bugbountylibrary.com/r/sherlock%3A2023-05-perennial%3AM-10.md)
- Borrow/repay sandwich around a withdrawal to inflate an exit penalty via external liquidity [E3](https://bugbountylibrary.com/r/sherlock%3A2022-09-sherlock%3AM-4.md)

## Impact and severity
Outcomes ranged from protocol insolvency risk [E1](https://bugbountylibrary.com/r/sherlock%3A2024-05-elfi-protocol%3AH-1.md) to economic penalties shifted onto other users [E2](https://bugbountylibrary.com/r/sherlock%3A2023-05-perennial%3AM-10.md)[E3](https://bugbountylibrary.com/r/sherlock%3A2022-09-sherlock%3AM-4.md). Severity rises when the bypass is permissionless, repeatable, and profitable within a single transaction; it falls when it needs privileged roles or only griefs the attacker.

## Evidence
- E1: https://bugbountylibrary.com/r/sherlock%3A2024-05-elfi-protocol%3AH-1.md
- E2: https://bugbountylibrary.com/r/sherlock%3A2023-05-perennial%3AM-10.md
- E3: https://bugbountylibrary.com/r/sherlock%3A2022-09-sherlock%3AM-4.md
