Adverary can DOS contract by making a large number of deposits/withdraws then removing them all
When a user dequeues a withdraw or deposit it leaves a blank entry in the withdraw/deposit. This entry must be read from memory and skipped when processing the withdraws/deposits which uses gas for each blank entry. An adversary could exploit this to DOS the contract. By making a large number of these blank deposits they could make it impossible to process any auction.\\n```\\n    while (_quantity > 0) {\\n        Receipt memory deposit = deposits[i];\\n        if (deposit.amount == 0) {\\n            i++;\\n            continue;\\n        }\\n        if (deposit.amount <= _quantity) {\\n            // deposit amount is lesser than quantity use it fully\\n            _quantity = _quantity - deposit.amount;\\n            usdBalance[deposit.sender] -= deposit.amount;\\n            amountToSend = (deposit.amount * 1e18) / _price;\\n            IERC20(crab).transfer(deposit.sender, amountToSend);\\n            emit USDCDeposited(deposit.sender, deposit.amount, amountToSend, i, 0);\\n            delete deposits[i];\\n            i++;\\n        } else {\\n            // deposit amount is greater than quantity; use it partially\\n            deposits[i].amount = deposit.amount - _quantity;\\n            usdBalance[deposit.sender] -= _quantity;\\n            amountToSend = (_quantity * 1e18) / _price;\\n            IERC20(crab).transfer(deposit.sender, amountToSend);\\n            emit USDCDeposited(deposit.sender, _quantity, amountToSend, i, 0);\\n            _quantity = 0;\\n        }\\n    }\\n```\\n\\nThe code above processes deposits in the order they are submitted. An adversary can exploit this by withdrawing/depositing a large number of times then dequeuing them to create a larger number of blank deposits. Since these are all zero, it creates a fill or kill scenario. Either all of them are skipped or none. If the adversary makes the list long enough then it will be impossible to fill without going over block gas limit.
Two potential solutions. The first would be to limit the number of deposits/withdraws that can be processed in a single netting. The second would be to allow the owner to manually skip withdraws/deposits by calling an function that increments depositsIndex and withdrawsIndex.
Contract can be permanently DOS'd
```\\n    while (_quantity > 0) {\\n        Receipt memory deposit = deposits[i];\\n        if (deposit.amount == 0) {\\n            i++;\\n            continue;\\n        }\\n        if (deposit.amount <= _quantity) {\\n            // deposit amount is lesser than quantity use it fully\\n            _quantity = _quantity - deposit.amount;\\n            usdBalance[deposit.sender] -= deposit.amount;\\n            amountToSend = (deposit.amount * 1e18) / _price;\\n            IERC20(crab).transfer(deposit.sender, amountToSend);\\n            emit USDCDeposited(deposit.sender, deposit.amount, amountToSend, i, 0);\\n            delete deposits[i];\\n            i++;\\n        } else {\\n            // deposit amount is greater than quantity; use it partially\\n            deposits[i].amount = deposit.amount - _quantity;\\n            usdBalance[deposit.sender] -= _quantity;\\n            amountToSend = (_quantity * 1e18) / _price;\\n            IERC20(crab).transfer(deposit.sender, amountToSend);\\n            emit USDCDeposited(deposit.sender, _quantity, amountToSend, i, 0);\\n            _quantity = 0;\\n        }\\n    }\\n```\\n