An attacker contract can exploit the onERC721Received callback in buyPresent() to re-enter the function repeatedly, draining a victim's entire SantaToken balance in a single transaction. Without reentrancy, each buyPresent(victim) call drains 1e18 tokens. With reentrancy, every token the victim holds is drained in one atomic transaction before the victim can react.
Any address can call buyPresent(victim) for any SantaToken holder with no approval required (Solmate burns without allowance checks). Deploying a contract with onERC721Received to amplify the drain requires only standard Solidity knowledge and gas.
buyPresent() makes two sequential external calls with no reentrancy guard:
_mintAndIncrement() calls OZ _safeMint(msg.sender, ...), which fires onERC721Received on the attacker contract after minting. At this point, the burn has already executed but no state prevents another call. The attacker re-calls buyPresent(victim) from inside the callback:
The entire victim balance is drained before the outermost call returns. No state is written between calls to prevent re-entry.
Likelihood:
No victim approval required - Solmate _burn bypasses allowance checks entirely
Any SantaToken holder is an immediate target
Reentrancy amplifies the drain from 1e18 per call to the victim's full balance per transaction
Impact:
Victim's entire SantaToken balance drained atomically in one transaction
Attacker gains one NFT per 1e18 tokens drained — multiple NFTs per transaction
Victim has no opportunity to react — the entire drain is atomic
Combined with F-4 (wrong burn address), every token holder is already a target even without reentrancy
Add OpenZeppelin's ReentrancyGuard and apply nonReentrant to both buyPresent() and collectPresent():
Additionally, fix the CEI violation in buyPresent() by writing any relevant state before making external calls.
The contest is live. Earn rewards by submitting a finding.
Submissions are being reviewed by our AI judge. Results will be available in a few minutes.
View all submissionsThe contest is complete and the rewards are being distributed.