# An offer made after auction end can be stolen by an auction winner

A post-auction offer on an NFT can be accepted by the auction winner, who receives both the NFT and the offer funds, stealing from the offerer.

- Payout: Audit contest
- Severity: high
- Program: Foundation
- Found by: hyh
- Disclosed: 2022-05-19
- Write-up quality: 8/10
- Original: https://github.com/code-423n4/2022-02-foundation-findings/issues/49
- Library page: https://bugbountylibrary.com/r/c4%3A2022-02-foundation%3AH-03
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:high tech:solidity technique:chained technique:source-review vuln:access-control vuln:business-logic

**Target:** NFTMarket offer/auction escrow transfer logic (Solidity)
**Root cause:** _acceptOffer calls _transferFromEscrow, which falls through to NFTMarketReserveAuction._transferFromEscrow and finalizes the auction, sending the NFT to auction.bidder instead of the offer recipient, while the offer payment still settles.
**Steps:**
1. Auction ends without winner claiming NFT (endTime < block.timestamp).
2. Attacker (auction winner) or any user calls `makeOffer` on the NFT; `_isInActiveAuction` returns false so offer is accepted.
3. Auction winner calls `acceptOffer` (or `setBuyPrice` -> `_autoAcceptOffer` -> `_acceptOffer`).
4. Direct transfer fails since NFT is in escrow; `_transferFromEscrow` is invoked.
5. NFTMarketOffer._transferFromEscrow calls super (offer deleted); NFTMarketBuyPrice._transferFromEscrow calls super (no buy price); NFTMarketReserveAuction._transferFromEscrow calls `_finalizeReserveAuction(auctionId, false)` sending NFT to auction.bidder.
6. Offer payment is taken from offerer; winner keeps NFT and receives offer funds minus fees.
**How found:** Code-reading of the multiple-inheritance _transferFromEscrow override chain: noticed that after auction end but before pickup, the offer path falls through to reserve-auction finalization which ignores the offer recipient.
**Exploitation:** Winner waits for auction to end, lets an offer be placed (or places one via a colluding account), then calls acceptOffer; escrow finalization routes NFT to the winner while the offer amount is paid out to the winner as seller, netting NFT plus offer funds.
**Insight:** In diamond/mixin inheritance with chained super calls, trace which override actually executes for each state; a fallthrough to auction finalization can silently redirect an asset to a different party than the caller intended.
