Underflow in ```_previewWithdraw``` could prevent withdrawals
An underflow in the `_previewWithdraw` function in `AuctionInternal.sol` due to totalContractsSold exceeding auction.totalContracts could prevent users from withdrawing options.\\nThe `_previewWithdraw` function returns the fill and refund amounts for a buyer by looping over all orders. A totalContractsSold variable is used to track the amount of contracts sold as the loop iterates over all orders. If the current order's size + totalContractsSold exceeds the auction's totalContracts then the order will only be filled partially. The calculation for the partial fill (remainder) is given on line 318. This will lead to an underflow if totalContractsSold > the auction's totalContracts which would happen if there are multiple orders that cause the totalContractsSold variable to exceed totalContracts.\\nThe totalContractsSold variable in `_previewWithdraw` could exceed the auction.totalContracts due to the contracts sold before the start of an auction through limit orders not being limited. When an order is added, `_finalizeAuction` is only called if the auction has started. The `_finalizeAuction` function will call the `_processOrders` function which will return true if the auction has reached 100% utilization. Since limit orders can be made before the start of an auction, `_finalizeAuction` is not called and any amount of new orders may be made.\\nExample: The buyer makes a limit order with size > auction.totalContracts. They then make another order with size of anything. These orders are made before the start of the auction so `_processOrders` is not called for every new order and totalContractsSold can exceed totalContracts. When `_previewWithdraw` is called, after the buyer's first order is processed, totalContractsSold > auction.totalContracts so the condition on line 313 passes. Since totalContractsSold > auction.totalContracts the calculation on line 318 underflows and the transaction reverts. The `_previewWithdraw` function and thus the `_withdraw` function is uncallable.\\nTest code added to `Auction.behaviour.ts`, under the `#addLimitOrder(uint64,int128,uint256)` section:\\n```\\n it("previewWithdraw reverts if buyer has too many contracts", async () => {\\n          assert.isEmpty(await auction.getEpochsByBuyer(addresses.buyer1));\\n\\n          await asset\\n            .connect(signers.buyer1)\\n            .approve(addresses.auction, ethers.constants.MaxUint256);\\n\\n          const totalContracts = await auction.getTotalContracts(epoch);\\n          await auction.addLimitOrder(\\n            epoch,\\n            fixedFromFloat(params.price.max),\\n            totalContracts.mul(2)\\n          );\\n\\n          await auction.addLimitOrder(\\n            epoch,\\n            fixedFromFloat(params.price.max),\\n            totalContracts.div(2)\\n          );\\n\\n          const epochByBuyer = await auction.getEpochsByBuyer(addresses.buyer1);\\n\\n          assert.equal(epochByBuyer.length, 1);\\n          assert.bnEqual(epochByBuyer[0], epoch);\\n          \\n          await expect(auction.callStatic[\\n            "previewWithdraw(uint64)"\\n          ](epoch)).to.be.reverted;\\n        });\\n```\\n\\nThe test code above shows a buyer is able to add an order with size auction.totalContracts*2 and a subsequent order with size auction.totalContracts/2. The `previewWithdraw` function reverts when called.
The loop in `_previewWithdraw` should check if the current totalContractsSold is >= totalContracts. If it is then the remainder should be set to 0 which would allow the current order to be fully refunded.\\nAdditionally, the orders for an auction should be checked before the auction starts. In `_addOrder`, consider adding a condition that will call `_processOrders` if the auction has not started yet. If `_processOrders` returns true then do not allow the order to be added. Or just allow the auction to be finalized before it starts if the total contracts sold has reached the auction's totalContracts.
Users would be unable to withdraw from the Auction contract.
```\\n it("previewWithdraw reverts if buyer has too many contracts", async () => {\\n          assert.isEmpty(await auction.getEpochsByBuyer(addresses.buyer1));\\n\\n          await asset\\n            .connect(signers.buyer1)\\n            .approve(addresses.auction, ethers.constants.MaxUint256);\\n\\n          const totalContracts = await auction.getTotalContracts(epoch);\\n          await auction.addLimitOrder(\\n            epoch,\\n            fixedFromFloat(params.price.max),\\n            totalContracts.mul(2)\\n          );\\n\\n          await auction.addLimitOrder(\\n            epoch,\\n            fixedFromFloat(params.price.max),\\n            totalContracts.div(2)\\n          );\\n\\n          const epochByBuyer = await auction.getEpochsByBuyer(addresses.buyer1);\\n\\n          assert.equal(epochByBuyer.length, 1);\\n          assert.bnEqual(epochByBuyer[0], epoch);\\n          \\n          await expect(auction.callStatic[\\n            "previewWithdraw(uint64)"\\n          ](epoch)).to.be.reverted;\\n        });\\n```\\n