# Reentrancy from matchOneToManyOrders

matchOneToManyOrders sets the maker order nonce after transferring tokens, letting a malicious seller re-enter via takeOrders and double-fill a buyer's signed order.

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

**Target:** InfinityExchange.sol matchOneToManyOrders / takeOrders
**Root cause:** matchOneToManyOrders violates Checks-Effects-Interactions: it transfers NFTs/payment before marking isUserOrderNonceExecutedOrCancelled, and unlike takeOrders it lacks nonReentrant.
**Steps:**
1. Alice signs a buy order for 2 WolfNFT paying in AMP (ERC-777).
2. Bob lists 2 WolfNFT for sale and deploys a receiver contract that, on receiving AMP, calls `takeOrders(AliceOrder, 2 other WolfNFTs)`.
3. MATCH_EXECUTOR calls `matchOneToManyOrders(BobOrder, [AliceOrder])`; `_matchOneMakerSellToManyMakerBuys` transfers tokens, triggering Bob's hook.
4. Reentrant `takeOrders` matches Alice's still-unexecuted order with Bob's NFTs and sets her nonce true.
5. Outer call resumes and sets the nonce true again; Alice has bought 4 NFTs against a 2-NFT order.
**How found:** Code reading of matchOneToManyOrders showed nonce update placed after external token transfers, and noted takeOrders is nonReentrant while matchOneToManyOrders is not, enabling cross-function reentrancy.
**Exploitation:** Malicious seller contract hooks ERC-777 (or ERC721 onERC721Received) token receipt to re-enter takeOrders with the victim's signed order before the outer match marks its nonce, forcing the victim to purchase extra NFTs.
**Insight:** When one entrypoint is nonReentrant but a sibling entrypoint sharing the same order state is not, check whether the guarded function can be re-entered through the unguarded one via token callbacks before nonce/state is committed.

