Vulnerability: Bidders' funds may become locked due to inconsistent price order checks in MaxPriorityQueue and the _claimBid function.
Severity: high

Description:
In the `MaxPriorityQueue`, `bids` are ordered by decreasing `price`. We calculate the `marginal price`, `marginal bid ID`, and determine the `auction winners`. When a `bidder` wants to claim, we verify that the `bid price` of this `bidder` exceeds the `marginal price`. However, there's minor inconsistency: certain `bids` may have `marginal price` and a smaller `bid ID` than `marginal bid ID` and they are not actually `winners`. As a result, the `auction winners` and these `bidders` can receive `base` tokens. However, there is a finite supply of `base` tokens for `auction winners`. Early `bidders` who claim can receive `base` tokens, but the last `bidders` can not.\\nThe comparison for the order of `bids` in the `MaxPriorityQueue` is as follow: if `q1 * b2 < q2 * b1` then `bid (q2, b2)` takes precedence over `bid (q1, b1)`.\\n```\\nfunction _isLess(Queue storage self, uint256 i, uint256 j) private view returns (bool) {\\n    uint64 iId = self.bidIdList[i];\\n    uint64 jId = self.bidIdList[j];\\n    Bid memory bidI = self.idToBidMap[iId];\\n    Bid memory bidJ = self.idToBidMap[jId];\\n    uint256 relI = uint256(bidI.amountIn) * uint256(bidJ.minAmountOut);\\n    uint256 relJ = uint256(bidJ.amountIn) * uint256(bidI.minAmountOut);\\n    if (relI == relJ) {\\n        return iId > jId;\\n    }\\n    return relI < relJ;\\n}\\n```\\n\\nAnd in the `_calimBid` function, the `price` is checked directly as follow: if q * 10 ** baseDecimal / b >= marginal `price`, then this `bid` can be claimed.\\n```\\nfunction _claimBid(\\n    uint96 lotId_,\\n    uint64 bidId_\\n) internal returns (BidClaim memory bidClaim, bytes memory auctionOutput_) {\\n    uint96 price = uint96(\\n        bidData.minAmountOut == 0\\n            ? 0 // TODO technically minAmountOut == 0 should be an infinite price, but need to check that later. Need to be careful we don't introduce a way to claim a bid when we set marginalPrice to type(uint96).max when it cannot be settled.\\n            : Math.mulDivUp(uint256(bidData.amount), baseScale, uint256(bidData.minAmountOut))\\n    );\\n    uint96 marginalPrice = auctionData[lotId_].marginalPrice;\\n    if (\\n        price > marginalPrice\\n            || (price == marginalPrice && bidId_ <= auctionData[lotId_].marginalBidId)\\n    ) { }\\n}\\n```\\n\\nThe issue is that a `bid` with the `marginal price` might being placed after marginal `bid` in the `MaxPriorityQueue` due to rounding.\\n```\\nq1 * b2 < q2 * b1, but mulDivUp(q1, 10 ** baseDecimal, b1) = mulDivUp(q2, 10 ** baseDecimal, b2)\\n```\\n\\nLet me take an example. The `capacity` is `10e18` and there are `6 bids` ((4e18 + 1, 2e18) for first `bidder`, `(4e18 + 2, 2e18)` for the other `bidders`. The order in the `MaxPriorityQueue` is `(2, 3, 4, 5, `6`, 1)`. The `marginal bid ID` is `6`. The `marginal price` is `2e18` + 1. The `auction winners` are `(2, 3, 4, 5, 6)`. However, `bidder` 1 can also claim because it's `price` matches the `marginal price` and it has the smallest `bid ID`. There are only `10e18` `base` tokens, but all `6 bidders` require `2e18` `base` tokens. As a result, at least one `bidder` won't be able to claim `base` tokens, and his `quote` tokens will remain locked in the `auction house`.\\nThe Log is\\n```\\nmarginal price     ==>   2000000000000000001\\nmarginal bid id    ==>   6\\n\\npaid to bid  1       ==>   4000000000000000001\\npayout to bid  1     ==>   1999999999999999999\\n*****\\npaid to bid  2       ==>   4000000000000000002\\npayout to bid  2     ==>   2000000000000000000\\n*****\\npaid to bid  3       ==>   4000000000000000002\\npayout to bid  3     ==>   2000000000000000000\\n*****\\npaid to bid  4       ==>   4000000000000000002\\npayout to bid  4     ==>   2000000000000000000\\n*****\\npaid to bid  5       ==>   4000000000000000002\\npayout to bid  5     ==>   2000000000000000000\\n*****\\npaid to bid  6       ==>   4000000000000000002\\npayout to bid  6     ==>   2000000000000000000\\n```\\n\\nPlease add below test to the `test/modules/auctions/EMPA/claimBids.t.sol`\\n```\\nfunction test_claim_nonClaimable_bid()\\n    external\\n    givenLotIsCreated\\n    givenLotHasStarted\\n    givenBidIsCreated(4e18 + 1, 2e18)           // bidId = 1\\n    givenBidIsCreated(4e18 + 2, 2e18)           // bidId = 2\\n    givenBidIsCreated(4e18 + 2, 2e18)           // bidId = 3\\n    givenBidIsCreated(4e18 + 2, 2e18)           // bidId = 4\\n    givenBidIsCreated(4e18 + 2, 2e18)           // bidId = 5\\n    givenBidIsCreated(4e18 + 2, 2e18)           // bidId = 6\\n    givenLotHasConcluded\\n    givenPrivateKeyIsSubmitted\\n    givenLotIsDecrypted\\n    givenLotIsSettled\\n{\\n    EncryptedMarginalPriceAuctionModule.AuctionData memory auctionData = _getAuctionData(_lotId);\\n\\n    console2.log('marginal price     ==>  ', auctionData.marginalPrice);\\n    console2.log('marginal bid id    ==>  ', auctionData.marginalBidId);\\n    console2.log('');\\n\\n    for (uint64 i; i < 6; i ++) {\\n        uint64[] memory bidIds = new uint64[](1);\\n        bidIds[0] = i + 1;\\n        vm.prank(address(_auctionHouse));\\n        (Auction.BidClaim[] memory bidClaims,) = _module.claimBids(_lotId, bidIds);\\n        Auction.BidClaim memory bidClaim = bidClaims[0];\\n        if (i > 0) {\\n            console2.log('*****');\\n        }\\n        console2.log('paid to bid ', i + 1, '      ==>  ', bidClaim.paid);\\n        console2.log('payout to bid ', i + 1, '    ==>  ', bidClaim.payout);\\n    }\\n}\\n```\\n

Impact:

Recommended mitigation:
In the `MaxPriorityQueue`, we should check the price: `Math.mulDivUp(q, 10 ** baseDecimal, b)`.