list() verifies ownership via ownerOf(_tokenId) == msg.sender but never transfers the NFT into the contract's custody. The seller retains full control of the NFT after listing.
If the seller transfers the NFT to another address, buy() reverts on _safeTransfer because the contract cannot move a token the seller no longer holds. The listing remains permanently active with no cleanup path.
Likelihood:
This occurs whenever a seller lists an NFT and then transfers it to another wallet — a common operation (gift, move to cold storage, sell on another platform)
A malicious seller can intentionally create permanent ghost listings
Impact:
Stale listings remain permanently active with no way to deactivate them (only cancelListing by seller or successful buy can set isActive = false)
activeListingsCounter is inflated, misleading any integration tracking marketplace activity
Buyers waste gas on reverting transactions when attempting to purchase ghost listings
Transfer the NFT into escrow on listing and return it on cancel:
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.
The contest is complete and the rewards are being distributed.