# Wrong implementation of TurboSafe.sol#less() may cause boosted record value in TurboMaster bigger than actual lead to BoostCapForVault and BoostCapForCollateral to be permanently occupied

TurboSafe.less() passes capped feiDebt to onSafeLess instead of actual withdrawn amount, desyncing TurboMaster boost accounting and permanently occupying boost caps.

- Payout: Audit contest
- Severity: medium
- Program: Tribe
- Found by: WatchPug
- Disclosed: 2022-04-19
- Write-up quality: 7/10
- Original: https://github.com/code-423n4/2022-02-tribe-turbo-findings/issues/55
- Library page: https://bugbountylibrary.com/r/c4%3A2022-02-tribe-turbo%3AM-02
- Tags: domain:web3 impact:dos kind:contest platform:code4rena sev:medium tech:solidity technique:source-review vuln:accounting-error vuln:business-logic

**Target:** TurboSafe.sol less() / TurboMaster accounting
**Root cause:** less() caps feiAmount to feiDebt before calling master.onSafeLess, so the hook records the debt-capped amount rather than the actual Fei withdrawn from the vault, leaving getTotalBoostedForVault inflated relative to the Safe's real boost.
**Steps:**
1. Deploy scenario: 1 WBTC=100k, collateralFactor 0.6, boost caps 300k for WBTC and vault0.
2. Alice deposits 10 WBTC and boosts 300k Fei to vault0; Safe debt=300k, vault Fei=300k, master totals=300k.
3. WBTC price drops to 50k; Turbo Gibber impounds 2 WBTC, mints 100k Fei, repays debt; Safe debt=200k, vault Fei=300k.
4. Alice calls `less(vault0, 300000)`; contract repays 200k debt but calls `master.onSafeLess(WBTC, vault0, 200000)`.
5. Master decrements totals by 200k only: getTotalBoostedForVault[vault0]=100k, getTotalBoostedAgainstCollateral[WBTC]=100k, while Safe's totalFeiBoosted=0.
6. Alice attempts to deposit 20 WBTC and boost 300k Fei; reverts with `BOOSTER_REJECTED` because caps remain occupied.
**How found:** Code review of less(): noticed feiAmount is reassigned to feiDebt before master.onSafeLess is invoked, so the hook receives the capped repay amount instead of the withdrawn amount, desyncing master accounting from Safe state.
**Exploitation:** Precondition: Gibber impounds collateral and repays debt so Safe debt < vault Fei balance. Attacker (or any Safe owner) calls less() withdrawing full vault Fei; the hook reports only the debt-capped amount, leaving stale boost totals in TurboMaster that permanently consume BoostCapForVault and BoostCapForCollateral, blocking new boosts/borrows.
**Insight:** When a function mutates a variable (capping to debt) before calling an accounting hook, the hook records the wrong quantity; check ordering of state-sync callbacks relative to value clamping, especially where external liquidation can make debt < balance.
