# Auction can potentially sell more contracts than it has collateral for.

Auction withdrawal recomputes totalContractsSold from zero after earlier orders are removed, letting later bidders be filled beyond total collateral.

- Payout: Contest reward
- Severity: high
- Program: Knox
- Credited: yixxas
- Disclosed: 2022-09-21
- Write-up quality: 7/10
- Original: https://github.com/sherlock-audit/2022-09-knox-judging/issues/80
- Library page: https://bugbountylibrary.com/r/sherlock%3A2022-09-knox%3AH-3
- Tags: domain:web3 impact:funds-loss kind:contest platform:sherlock sev:high tech:solidity technique:source-review vuln:accounting-error vuln:business-logic

**Target:** Auction contract _previewWithdraw order book traversal
**Root cause:** totalContractsSold is a local variable reset to 0 each _previewWithdraw call, but filled orders are removed from the order book on withdrawal, so subsequent withdrawals no longer count previously sold contracts against auction.totalContracts.
**Steps:**
1. Set auction.totalContracts = 10.
2. Alice addLimitOrder(price=10, size=10); Bob addLimitOrder(price=10, size=1).
3. processOrder() sets clearing price 10, all 10 contracts sold to Alice.
4. Alice withdraws: fill=10, refund=0; her order removed from order book.
5. Bob withdraws: totalContractsSold starts at 0, check `totalContractsSold + data.size >= auction.totalContracts` (0+1>=10) fails, so else branch does `fill += data.size`, selling Bob an extra contract beyond collateral.
**How found:** Code reading of _previewWithdraw: noticed totalContractsSold is a fresh local each call while orders are deleted on withdrawal, breaking the running-total invariant used to cap fills.
**Exploitation:** Any bidder at or above clearing price who withdraws after higher-priority orders were removed gets filled again, minting naked option contracts beyond collateral backing.
**Insight:** When a function both mutates state (removing orders) and recomputes a running total locally, check whether the total must persist across calls; deletion of already-counted entries silently resets the cap.
