# Short positions can be burned while holding collateral

ShortToken.adjustPosition burns a position when shortAmount hits 0 without checking collateral, permanently locking remaining collateral in the burned token.

- Payout: Contest reward
- Severity: high
- Program: Polynomial Protocol
- Credited: MiloTruck
- Disclosed: 2023-08-01
- Write-up quality: 7/10
- Original: https://github.com/code-423n4/2023-03-polynomial-findings/issues/206
- Library page: https://bugbountylibrary.com/r/c4%3A2023-03-polynomial%3AH-03
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:chained technique:source-review vuln:accounting-error vuln:business-logic

**Target:** ShortToken / Exchange short position lifecycle (ERC721)
**Root cause:** adjustPosition() burns the position whenever shortAmount == 0, without requiring collateralAmount == 0, so residual collateral stays in a token with no owner.
**Steps:**
1. Open short via `exchange.openTrade` with amount=1e18, collateralAmount=1e15 sUSD.
2. Call `exchange.closeTrade` with params.amount=1e18, params.collateralAmount=0.
3. adjustPosition sets shortAmount=0 and burns positionId while collateralAmount=1e15 remains.
4. `shortToken.ownerOf(positionId)` reverts NOT_MINTED; collateral is stuck.
**How found:** Code reading of adjustPosition()'s burn branch, noticing the missing collateralAmount==0 guard, then enumerating closeTrade/liquidate paths that zero shortAmount while collateral remains.
**Exploitation:** Attacker frontruns a victim's partial closeTrade() with liquidate() repaying enough debt that the victim's subsequent closeTrade() drives shortAmount to 0, burning the position and stranding the victim's remaining collateral. Also occurs via full liquidation leaving residual collateral.
**Escalation:** Frontrunning a partial close with a partial liquidation to force shortAmount to zero on the victim's own transaction.
**Insight:** When a burn/delete condition keys off one field reaching zero, check whether sibling balance fields can be nonzero at that moment; liquidation and partial-close paths are prime ways to zero one field while leaving value behind.
