# Withdrawing from the vault may lead to a loss if the order balances are less than the total amount withdrawn

Vault withdrawAssets burns XT/FT from an immature order but never transfers that amount to the user, silently losing funds when order balance is below withdrawal amount.

- Payout: Contest reward
- Severity: high
- Program: Term Structure
- Credited: Nyksx10
- Disclosed: 2025-03-20
- Write-up quality: 7/10
- Original: https://cdn.cantina.xyz/reports/cantina_competition_term_structure_february2025.pdf#3.1.5
- Library page: https://bugbountylibrary.com/r/cantina%3Aterm_structure_february2025%3A3.1.5
- Tags: domain:web3 impact:funds-loss kind:contest platform:cantina sev:high tech:solidity technique:source-review vuln:accounting-error vuln:business-logic

**Target:** Vault withdrawAssets / _burnFromOrder redemption logic
**Root cause:** In the maxWithdraw < amountLeft branch, _burnFromOrder is called and amountLeft decremented, but no asset.safeTransfer(recipient, maxWithdraw) occurs before moving to the next order.
**Steps:**
1. Deposit as LP into vault, curator creates order on market2 and sets supply queue.
2. Warp past deposit, taker swaps debt->XT so order's XT balance is less than LP's withdrawal amount.
3. LP calls `vault.redeem(shares, lper2, lper2)`.
4. Observe shares burned 1e12 but only 1e11 debt tokens received; the maxWithdraw portion burned from order is never transferred.
**How found:** Code review of withdrawAssets branching: noticed _burnFromOrder in the partial branch lacked a corresponding safeTransfer, unlike the else branch.
**Exploitation:** Any LP redeeming while an immature order holds less XT/FT than the requested amount loses the burned-but-untransferred portion; no attacker needed, loss occurs on normal withdrawal.
**Insight:** In multi-order redemption loops, audit every branch that mutates accounting (burn/decrement) for a matching value transfer; partial-fill branches are where the transfer is most often forgotten.
