NFTDealers::buy() violates CEI pattern via _safeTransfer() enabling reentrancy`buy()` violates CEI pattern, `isActive` set after `_safeTransfer()` creating a state inconsistency window, where a malicious ERC721 receiver contract can observe stale state during `onERC721Received()` callback
A malicious buyer contract can re-enter `NFTDealers::buy()` during `onERC721Received()` callback. However, since the NFT has already transferred to the attacker on the first call, the second `_safeTransfer()` will revert as the seller is no longer the owner. The attacker ends up paying double for the same NFT — so the practical impact is self-harm rather than protocol drain. Severity is reduced to Medium due to low likelihood of successful exploitation.
Likelihood: Low
Attacker contract must be whitelisted
Impact: Low
Nothing violates on protocol
Attack flow:
Deploy BuyAttacker, fund with 2x listing.price USDC
Call BuyAttacker::attack(listingId)
First buy() USDC transferred, NFT transferred to BuyAttacker, callback triggered
Inside onERC721Received isActive still true, re-enter buy()
Second `buy()` USDC transferred again, `_safeTransfer` reverts (seller no longer owner)
Entire second re-entry reverts, but first call already succeeded
Net result: attacker paid listing.price once, owns NFT no gain, no protocol loss
Follow CEI pattern update `isActive` before any external calls:
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.