# Holding owners can hide portion of their collateral from bad debt liquidation

Jigsaw holding owners can donate tokens directly to their holding and invest via StrategyManager, keeping collateral unaccounted so liquidateBadDebt seizes less, leaving funds recoverable.

- Payout: Contest reward
- Severity: medium
- Program: Jigsaw
- Credited: Chinmay Farkya
- Disclosed: 2025-08-11
- Write-up quality: 7/10
- Original: https://cdn.cantina.xyz/reports/cantina_competition_jigsaw_june2025.pdf#3.2.11
- Library page: https://bugbountylibrary.com/r/cantina%3Ajigsaw_june2025%3A3.2.11
- Tags: domain:web3 impact:funds-loss impact:integrity kind:contest platform:cantina sev:medium technique:source-review vuln:business-logic vuln:liquidation vuln:oracle-manipulation

**Target:** HoldingManager/StrategyManager
**Root cause:** Strategies pull funds directly from the holding contract without checking accounted collateral[holding], so donated balances invested into strategies are tracked in investedAmount but never added to collateral accounting.
**Steps:**
1. Deposit 1 WETH collateral via HoldingManager; collateral[holding]==1 WETH.
2. Borrow 1875 JUSD at 0.75 LTV.
3. Invest the 1 WETH into strategy1 via HoldingManager (still accounted).
4. Donate 0.1 WETH directly to the holding and call StrategyManager to deposit it into strategy2; AaveV3StrategyV2.deposit pulls from holding and records investedAmount=0.1 WETH but collateral[holding] stays 1 WETH.
5. Crash WETH price to 1870 USD; strategy1 loses 0.1 WETH.
6. Call `liquidateBadDebt()` with strategies data; `_retrieveCollateral` withdraws totalCollateral==1 WETH, collateral[holding] drops to 0.9 WETH.
7. Bad-debt check passes (0.9 WETH < 1875 JUSD debt); only 0.9 WETH transferred to liquidator, 0.1 WETH from strategy2 remains in holding.
8. User withdraws the leftover 0.1 WETH after debt is zeroed.
**How found:** Code reading of AaveV3StrategyV2.deposit() showing it pulls funds from the holding without validating against collateral[holding], combined with tracing liquidateBadDebt()'s _retrieveCollateral and post-withdrawal collateral accounting.
**Exploitation:** User self-hides collateral by donating tokens to their own holding and routing them into a strategy outside HoldingManager accounting; on bad-debt liquidation the protocol seizes only accounted collateral while the unaccounted strategy withdrawal stays in the holding, recoverable by the user post-liquidation.
**Insight:** When a strategy deposit pulls tokens from a shared balance rather than the accounted collateral variable, any tokens sitting in that contract (donations, stray transfers) become invisible collateral; check whether liquidation math uses the accounting variable while the actual token balance is larger.
