Description: After a successful sale, collectUsdcFromSelling() adds collateralForMinting[listing.tokenId] to the seller's payout but never resets it to zero. Each time the NFT is resold and collectUsdcFromSelling() is called, the same collateral amount is paid out again, draining the contract.
Impact: Every resale of an NFT allows the seller to claim the original minter's collateral again. The more times an NFT changes hands, the more USDC is drained from the contract.
Proof of Concept:
Each time an NFT is sold and collectUsdcFromSelling() is called, collateralForMinting[tokenId] is included in the payout but never reset. The same 20 USDC collateral is paid out to every seller in the chain.
Run forge test --match-test test_poc_H1 -vvv to see the following output:
After User A collects, collateralForMinting[6] remains 20e6. When User B sells the same NFT and collects, the same 20 USDC is paid out again. The original 20 USDC collateral has now been paid out twice — and will continue to be paid on every subsequent resale.
Recommended Mitigation: Add collateralForMinting[listing.tokenId] = 0; after transferring the collateral to the seller.
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.