# liquidate() doesn't mark off bad debt, leading to a 'last lender to withdraw loses' scenario

Frax lending pair's liquidate() leaves bad debt in totalAssets, letting early redeemers exit whole while later lenders absorb the loss.

- Payout: Contest reward
- Severity: high
- Program: Frax Finance
- Credited: 0xA5DF
- Disclosed: 2023-01-13
- Write-up quality: 7/10
- Original: https://github.com/code-423n4/2022-08-frax-findings/issues/141
- Library page: https://bugbountylibrary.com/r/c4%3A2022-08-frax%3AH-02
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:high tech:solidity technique:source-review vuln:accounting-error vuln:liquidation

**Target:** Frax lending pair liquidate()/liquidateClean() accounting
**Root cause:** liquidate() does not write off remaining bad debt when collateral is exhausted, so totalAssets.amount stays inflated above the solvent asset value.
**Steps:**
1. Create pair with 10 lenders depositing 1K each (10K total).
2. Borrower takes 10K; collateral price drops to 7K.
3. Liquidator calls `liquidate()`; totalAssets.amount remains 10K+interest while real assets <7K.
4. Early lenders call redeem and receive full principal+interest.
5. Later redeemers and remaining lenders absorb the shortfall.
**How found:** Reasoned about accounting invariant: totalAssets should reflect solvent assets, noticed liquidate() path never subtracts bad debt unlike liquidateClean().
**Exploitation:** Lenders who notice the unmarked bad debt redeem first, extracting full value from the inflated totalAssets; the loss is socialized onto the last redeemers.
**Insight:** When a protocol has two liquidation paths, check whether each path updates the same accounting state; a path that skips bad-debt write-off creates a first-exit advantage for depositors.
