Once an NFT is sold (or even just a listing is canceled), the seller can call collectUsdcFromSelling as many times as they want. The function checks that the listing is inactive and that the caller is the seller, but it never marks the collection as "done." Neither collateralForMinting is zeroed nor is there any flag to block repeat calls. Every call sends the same payout again.
On top of that, the function works after cancelListing too — even though no sale took place. The seller cancels their listing, gets collateral back from the cancel, then calls collectUsdcFromSelling to collect a "sale price" that was never paid. This steals directly from other users' deposits.
Likelihood: Any seller who has listed an NFT can do this right away. No timing, no setup — just call the function twice. That's it.
Impact: Total loss of funds. The attacker drains all USDC in the contract — other sellers' payments, other minters' collateral, everything. On top of that, totalFeesCollected gets inflated with each call, so eventually withdrawFees will try to send more than what's left and permanently revert.
Attack Path 1 — Repeated collection after a real sale:
10 users each mint (20 USDC collateral each). Contract holds 200 USDC.
User0 lists NFT #1 at 50 USDC. Carol buys it. Contract now has 250 USDC.
User0 calls collectUsdcFromSelling(1) — gets 69.5 USDC (50 - fee + 20 collateral).
User0 calls it again — same payout. And again. Contract drains until empty.
Attack Path 2 — Collection after cancel (no sale ever happened):
5 users mint. Contract holds 100 USDC.
User0 lists at 10 USDC, then cancels — gets 20 USDC collateral back.
User0 calls collectUsdcFromSelling(1) — listing is inactive from the cancel, so it passes. Sends 9.9 USDC from other users' collateral. No sale ever occurred.
Track whether a listing has already been collected, zero out the collateral after returning it, and make sure a canceled listing can't be collected as if it were a sale.
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.