The mintSnowman()
function assigns token IDs using a global counter s_TokenCounter
, which is used before being incremented. This makes future token IDs fully predictable. If a legitimate user attempts to mint a token (e.g., tokenId = 10), an attacker can observe the transaction in the mempool, predict the exact tokenId, and front-run the transaction by sending their own with higher gas fees. As a result, the attacker receives the intended token ID before the victim's transaction is processed.
Likelihood: High
Exploitable by anyone monitoring the mempool.
No on-chain restrictions, no signature checks.
No additional contracts or setup required.
Can be automated with basic MEV bots or flashbots bundles.
Impact:
Token ID sniping becomes trivial — attacker steals the exact token(s) a user is attempting to mint.
If token IDs are linked to rarity, airdrops, metadata, or in-game value, the economic damage is significant.
This undermines trust and fairness in the minting process.
No contract interaction is needed — even basic mempool watchers can exploit this.
Flow:
Alice submits tx to mint 1 NFT → assume - expectedTokenId = 10
.
Attacker sees her tx in mempool.
Attacker copies calldata and sends tx with higher gas.
Attacker gets tokenId 10
, Alice gets 11
.
Move the counter increment before the external _safeMint()
call to avoid predictability and eliminate reentrancy risk :
Use randomized token assignment (e.g. keccak256
-based shuffle).
Implement commit-reveal schemes for higher-value mints.
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.