# All troves can be redeemed, including the one Bima team maintains

Bima's redeemCollateral lacks Liquity's last-trove guard, letting anyone redeem the team's sentinel trove and break liquidatability of all troves.

- Payout: Contest reward
- Severity: medium
- Program: Bima
- Credited: pkqs90
- Disclosed: 2025-02-05
- Write-up quality: 6/10
- Original: https://cdn.cantina.xyz/reports/cantina_competition_bima_december2024.pdf#3.2.16
- Library page: https://bugbountylibrary.com/r/cantina%3Abima_december2024%3A3.2.16
- Tags: domain:web3 impact:dos kind:contest platform:cantina sev:medium tech:evm tech:solidity technique:regression technique:source-review vuln:business-logic vuln:liquidation

**Target:** TroveManager.redeemCollateral / _resetState in a Liquity-style CDP protocol
**Root cause:** Bima removed LiquityV1's _requireMoreThanOneTroveInSystem check from _closeTrove and _resetState, so redeemCollateral can close the final trove at any time instead of only during collateral sunset.
**Steps:**
1. Note Bima maintains one sentinel trove per TroveManager with minimal debt and highest CR to keep others liquidatable.
2. Call `redeemCollateral(_debtAmount, _firstRedemptionHint, _upperPartialRedemptionHint, _lowerPartialRedemptionHint, _partialRedemptionHintNICR, _maxIterations, _maxFeePercentage)` with enough debtTokens to fully redeem the sentinel trove's debt.
3. Redemption closes the last trove; `_resetState()` runs with `TroveOwners.length == 0`, wiping global state.
4. TroveManager now has zero or one borrower, so liquidation of remaining borrowers is impossible.
**How found:** Compared Bima's _closeTrove and _resetState against LiquityV1, noticing the missing _requireMoreThanOneTroveInSystem guard and that _resetState's sunset-only comment is unenforced.
**Exploitation:** Any holder of sufficient debtTokens calls redeemCollateral targeting the sentinel trove's debt, fully redeeming it and triggering _resetState, leaving the TroveManager without the high-CR trove needed to keep borrowers liquidatable.
**Insight:** When a fork strips a guard from a reference implementation, check every caller of the now-unguarded path; here the sentinel-trove invariant from the audit report is only as strong as the last-trove check that was deleted.
