# Loss of funds in matchOneToManyOrders() and takeOrders() and matchOrders() because code don't check that different ids in one collection are different, so it's possible to sell one id multiple time instead of selling multiple id one time in one collection of order (lack of checks in doTokenIdsIntersect() especially for ERC1155 tokens)

Infinity NFT marketplace's doTokenIdsIntersect() failed to reject duplicate tokenIds, letting an attacker fill a 3-NFT buy order with three copies of one cheap ERC1155 id and steal the price difference.

- Payout: Audit contest
- Severity: high
- Program: Infinity NFT Marketplace
- Found by: unforgiven
- Disclosed: 2022-08-16
- Write-up quality: 7/10
- Original: https://github.com/code-423n4/2022-06-infinity-findings/issues/135
- Library page: https://bugbountylibrary.com/r/c4%3A2022-06-infinity%3AH-02
- 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 / InfinityOrderBookComplication order-matching (takeOrders, matchOrders, matchOneToManyOrders)
**Root cause:** doTokenIdsIntersect() only checks that each taker tokenId exists somewhere in the maker's token list and that total counts match; it never enforces uniqueness of tokenIds within a collection, so a taker can repeat one cheap id to satisfy a multi-id buy order.
**Steps:**
1. Victim signs maker buy order A: BUY 3 ERC1155 tokens with ids [(1,1),(2,1),(3,1)] for 15 ETH.
2. Attacker holds 3 copies of cheap id=1 (fair 1 ETH) while ids 2 and 3 are worth 2 and 12 ETH.
3. Attacker builds takerItems B = [(1,1),(1,1),(1,1)].
4. Call `takeOrders(makerOrder=A, takerItems=B)`; areTakerNumItemsValid passes (3==3) and doTokenIdsIntersect passes since id 1 matches.
5. Exchange transfers 15 ETH to attacker for three id=1 tokens; victim receives only id=1 tokens, never ids 2/3.
**How found:** Code review of the order-validation path: traced canExecTakeOrder -> areTakerNumItemsValid (counts only) and doTokenIdsIntersect (membership only), noticing neither enforces distinct tokenIds within a collection, then constructed a repeated-id taker list against a multi-id buy order.
**Exploitation:** Attacker needs only to hold multiple copies of the cheapest ERC1155 tokenId in the victim's signed multi-id buy order. By submitting a takerItems list that repeats that id to match the order's total token count, the intersection check passes and the exchange pays the full order price while delivering only the cheap duplicates, capturing the price difference. No matching-engine cooperation required; anyone can call takeOrders directly.
**Escalation:** Same flaw applies to matchOneToManyOrders() and matchOrders(); for ERC721 it requires seller==buyer or auto-selling receiver contracts.
**Insight:** When auditing NFT order matching, check whether set-intersection helpers enforce uniqueness, not just membership and cardinality; repeated ids in a taker list can satisfy a multi-id maker order and underfill it, especially with ERC1155 where one id has many copies.

