# NFT owner can create multiple auctions

Foundation NFT reserve auction allowed an owner to create a second auction for the same token, then cancel both to permanently lock the last bidder's escrowed funds.

- Payout: Audit contest
- Severity: high
- Program: Foundation
- Found by: 0xliumin
- Disclosed: 2022-05-19
- Write-up quality: 7/10
- Original: https://github.com/code-423n4/2022-02-foundation-findings/issues/23
- Library page: https://bugbountylibrary.com/r/c4%3A2022-02-foundation%3AH-01
- Tags: 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:** NFTMarketReserveAuction.sol reserve auction contract
**Root cause:** _transferToEscrow does not revert when an auction already exists for the token, so createReserveAuction can be called repeatedly and overwrites nftContractToTokenIdToAuctionId with the new auction id.
**Steps:**
1. Alice calls `createReserveAuction` for tokenId, creating auction id 1.
2. Before any bid, Alice calls `createReserveAuction` again for the same tokenId; `_transferToEscrow` does not revert, creating auction id 2 and overwriting the mapping to id 2.
3. Bidders see auction id 2 as canonical and place bids, funds held in escrow.
4. Alice cancels auction id 1, then cancels auction id 2, leaving the last bidder's funds locked forever.
**How found:** Code review of createReserveAuction/_transferToEscrow noticing the escrow transfer lacks a check that an auction already exists for the tokenId, and that the auction-id mapping is simply overwritten.
**Exploitation:** Attacker (NFT owner) deploys a contract to guarantee the second createReserveAuction lands before any bid, creates two auctions for one token, lets bidders fund auction id 2, then cancels both auctions so escrowed bidder funds become unrecoverable without a contract upgrade.
**Escalation:** Also lets seller stop the clock or back out of an auction after a bid by creating and cancelling a fresh auction, violating the no-cancel-after-bid guarantee.
**Insight:** When a create/list function writes an id into a tokenId->id mapping, check whether re-invocation overwrites the pointer while old escrow state persists; duplicate listings can orphan escrowed funds and bypass cancel-after-bid guards.
