# Maker buy order with no specified NFT tokenIds may get fulfilled in matchOneToManyOrders without receiving any NFT

Infinity's matchOneToManyOrders counted empty-tokenId floor-sweep buy orders toward quantity but transferred zero NFTs to them, so buyers paid WETH and received nothing.

- Payout: Audit contest
- Severity: high
- Program: Infinity NFT Marketplace
- Found by: WatchPug
- Disclosed: 2022-08-16
- Write-up quality: 7/10
- Original: https://github.com/code-423n4/2022-06-infinity-findings/issues/254
- Library page: https://bugbountylibrary.com/r/c4%3A2022-06-infinity%3AH-01
- Tags: area:web3 domain:web3 impact:funds-loss kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:source-review vuln:accounting-error vuln:business-logic

**Target:** InfinityExchange.matchOneToManyOrders / InfinityOrderBookComplication.canExecMatchOneToMany
**Root cause:** canExecMatchOneToMany validates total specified tokenIds against the sell order quantity but does not require each matched buy order to specify tokenIds; empty-tokenId buy orders pass doItemsIntersect and are counted, yet _transferERC721s iterates buy.nfts tokens (empty) and transfers nothing.
**Steps:**
1. Alice signs maker buy #1: 2 Punks, 2 WETH, tokenIds=[1,2].
2. Bob signs maker buy #2: 1 Punk, 1 WETH, tokenIds=[] (floor sweep).
3. Charlie signs maker sell #3: 2 Punks, 3 WETH, tokenIds=[1,2].
4. Executor calls `matchOneToManyOrders()` with sell #3 against buys #1 and #2.
5. canExecMatchOneToMany returns true (numItems==2==constraints[0], prices sum 3>=3).
6. _execMatchOneMakerSellToManyBuys calls `_execMatchOneToManyOrders(sell.signer, buy.signer, buy.nfts, ...)`; for Bob buy.nfts.tokens is empty so `_transferERC721s` performs 0 transfers.
7. Result: Alice gets 2 Punks, Charlie gets 3 WETH, Bob pays 1 WETH and receives nothing.
**How found:** Code review of the matching validation: noticed empty tokenIds are treated as wildcard (doItemsIntersect always true) and that numItems only sums specified tokens, so empty orders contribute 0 to the count yet still pass; traced the transfer path to confirm buy.nfts drives _transferERC721s and yields zero transfers.
**Exploitation:** A floor-sweep buyer (empty tokenIds) gets bundled into a multi-buy match by the executor; the order passes validation and pays full price but the NFT transfer loop is empty, so the buyer loses funds with no asset received.
**Insight:** When a wildcard/empty-list order is allowed as a matching primitive, check whether the same list is later used as the transfer source; validation that counts only specified items can let zero-item orders satisfy quantity checks while transferring nothing.

