Description: cancelListing() transfers collateralForMinting[tokenId] back to the seller upon cancellation, but the NFT stays in the seller's wallet. A user can mint an NFT, list it, cancel the listing, and receive their collateral back — all while keeping the NFT. This can be repeated for every minted NFT.
Impact: Every whitelisted user can effectively mint NFTs for free by immediately listing and cancelling. The collateral mechanism — a core economic design of the protocol — is completely bypassed.
Proof of Concept:
An attacker with only 20 USDC can accumulate unlimited NFTs by repeatedly cycling through mint → list → cancel, recovering the collateral each time.
Run forge test --match-test test_poc_C1 -vvv to see the following output:
After mint #1, 20 USDC is locked in the contract. After list + cancel, the user recovers 20 USDC while still holding NFT #1. Using the recovered collateral to mint again and cancel, the attacker ends up with 2 NFTs, zero USDC spent, and the contract balance drained to zero.
Recommended Mitigation: cancelListing() should not return the collateral. Collateral should only be returned via collectUsdcFromSelling() after the NFT is actually sold.
No flag when the listing is canceled.
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.