When minting, users deposit lockAmount USDC as collateral stored in collateralForMinting[tokenId]. This collateral belongs to the original minter.
cancelListing() sends collateralForMinting[tokenId] to listing.seller — the current lister, not the original minter. After a secondary sale, the buyer can list and cancel to steal the minter's collateral without ever having deposited any.
Likelihood:
Any buyer who relists and cancels receives the original minter's collateral — normal marketplace flow
Impact:
20 USDC stolen per token. Combined with the listing overwrite, the original minter also loses sale proceeds — total loss is collateral + proceeds
Run with forge test --match-test testExploit_CollateralTheft. Bob gains 20 USDC he never deposited (Alice's minting collateral), and Alice's collectUsdcFromSelling reverts — total loss to Alice is 119 USDC.
Track the original minter per token and return collateral only to them. This ensures secondary buyers cannot claim collateral they never deposited.
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.