When a buyer purchases an NFT, the original seller should be able to call collectUsdcFromSelling to receive their sale proceeds and collateral. The onlySeller modifier checks that s_listings[listingId].seller == msg.sender.
s_listings is keyed by tokenId, not by a unique listing ID. When the new owner re-lists the same token, list() overwrites the entire Listing struct — including the seller field. The original seller's collectUsdcFromSelling call permanently reverts because onlySeller now points to the new owner.
Likelihood:
Every time a buyer re-lists the same tokenId before the original seller collects, the seller field is overwritten. This is normal marketplace usage — no malicious intent required.
The list() function only checks isActive == false, which is already the case after buy() sets it. There is no guard preventing overwrite of an uncollected listing.
Impact:
The original seller's sale proceeds and minting collateral are permanently locked in the contract. On a 100 USDC sale with 20 USDC collateral, the seller loses 119 USDC (proceeds + collateral - fee) with no recovery path.
There is no admin function to rescue locked funds. The seller cannot call collectUsdcFromSelling because onlySeller will always revert for them on that listing.
Alice mints an NFT (20 USDC collateral) and lists it at 100 USDC. Bob buys it — 100 USDC enters the contract. Before Alice calls collectUsdcFromSelling, Bob re-lists the same tokenId at 150 USDC. The s_listings[tokenId] struct is overwritten with Bob as the seller. Alice calls collectUsdcFromSelling and it reverts with "Only seller can call this function". Alice ends with 0 USDC — her 100 USDC proceeds and 20 USDC collateral are permanently locked.
Use listingsCounter as the mapping key instead of tokenId. Each listing gets a unique ID, so re-listing the same token creates a new entry without overwriting the previous one. The original seller can still collect from their listing ID.
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.