# Underflow in ```_previewWithdraw``` could prevent withdrawals

Limit orders placed before auction start bypass totalContractsSold cap, causing underflow in _previewWithdraw and blocking all withdrawals.

- 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/106
- Library page: https://bugbountylibrary.com/r/sherlock%3A2022-09-knox%3AH-1
- Tags: domain:web3 impact:dos kind:contest platform:sherlock sev:high tech:solidity technique:source-review vuln:accounting-error vuln:dos

**Target:** Auction contract's _previewWithdraw function
**Root cause:** Limit orders added before auction start skip _finalizeAuction, allowing totalContractsSold to exceed auction.totalContracts; _previewWithdraw then underflows when computing remainder.
**Steps:**
1. Buyer approves auction contract for asset.
2. Call `addLimitOrder(epoch, price, totalContracts*2)` before auction start.
3. Call `addLimitOrder(epoch, price, totalContracts/2)` before auction start.
4. Call `previewWithdraw(epoch)`; transaction reverts due to underflow at `auction.totalContracts - totalContractsSold`.
**How found:** Code review of _previewWithdraw and _addOrder revealed that limit orders before auction start bypass _finalizeAuction, allowing totalContractsSold to exceed totalContracts and trigger underflow.
**Exploitation:** Attacker (buyer) places oversized limit orders before auction start, causing totalContractsSold to exceed totalContracts. When any buyer calls withdraw, _previewWithdraw underflows and reverts, locking all funds in the auction contract.
**Insight:** In auction contracts, check invariants (total sold <= total available) at order insertion time, not just during finalization; pre-auction limit orders can bypass checks.
