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.
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.