# Wrong solvency threshold in guards

Paths that change position health enforcing liquidation threshold instead of the stricter max LTV

_Area: DeFi accounting and math bugs. Seen in 3 disclosed reports; latest 2026-02-05. Updated 2026-10-24._

## How it works
A protocol has two risk limits: a stricter one (max LTV, opening margin) that gates new risk, and a looser one (liquidation threshold, solvency) that defines when a position can be liquidated. The assumption that breaks is that every path changing a position's health enforces the stricter limit. When one path (withdraw, redeem, leverage change, debt transfer) checks only the looser limit, users reach the liquidation boundary without ever passing the intended cap. The bookkeeping then reports a position as healthy while it sits at the edge of liquidation.

## Where it shows up
- Withdraw/redeem calling a solvency check against LT while borrow() enforces max LTV [E1](https://bugbountylibrary.com/r/cantina%3Asilo%3A3.2.3.md).
- A leverage-change path validating only min-open-margin, not the post-withdrawal margin formula used by removeMargin() [E2](https://bugbountylibrary.com/r/c4%3A2025-08-gte-perps-and-launchpad%3AM-04.md).
- A debt-token transfer hook calling `isSolvent` but not `isBelowMaxLtv` [E3](https://bugbountylibrary.com/r/cantina%3Asilo%3A3.2.11.md).
- Any guard named `isSolvent`/`_checkSolvency` used where `isBelowMaxLtv`/`_checkLTV` is intended.

## How to review
Enumerate every function that can reduce collateral, increase debt, or move debt between accounts. For each, identify which threshold it enforces and confirm it is the stricter one (max LTV / opening margin), not the liquidation threshold. The invariant: after any state-changing action, the position must satisfy max LTV, not merely solvency. Diff the validation functions across sibling paths; a missing or weaker call is the bug.

## Variants seen
- Withdraw/redeem checks LT instead of LTV, bypassing the borrow cap [E1](https://bugbountylibrary.com/r/cantina%3Asilo%3A3.2.3.md).
- Leverage increase skips the post-withdrawal margin check that removeMargin() applies [E2](https://bugbountylibrary.com/r/c4%3A2025-08-gte-perps-and-launchpad%3AM-04.md).
- Debt-token transfer checks solvency only, allowing consolidation past max LTV [E3](https://bugbountylibrary.com/r/cantina%3Asilo%3A3.2.11.md).

## Why fixes fail
Evidence shows inconsistent limits across paths persisting: fixing one entry point (borrow) leaves withdraw/redeem [E1](https://bugbountylibrary.com/r/cantina%3Asilo%3A3.2.3.md), leverage [E2](https://bugbountylibrary.com/r/c4%3A2025-08-gte-perps-and-launchpad%3AM-04.md), and transfer [E3](https://bugbountylibrary.com/r/cantina%3Asilo%3A3.2.11.md) on the weaker check. A fix must apply the stricter threshold to every path that changes the ratio.

## Impact and severity
Positions reach the liquidation threshold, raising bad-debt risk and letting users exceed intended leverage. Severity is high where the gap enables borrowing or extraction beyond the cap; worse when the looser check is the only gate on a frequently used path.

## Evidence
- E1: https://bugbountylibrary.com/r/cantina%3Asilo%3A3.2.3.md
- E2: https://bugbountylibrary.com/r/c4%3A2025-08-gte-perps-and-launchpad%3AM-04.md
- E3: https://bugbountylibrary.com/r/cantina%3Asilo%3A3.2.11.md
