Normal behavior: claimFaucetTokens() should perform all state updates (cooldown, hasClaimedEth, daily counters) before any external calls or token transfers, and be protected from reentrant calls.
Problem: External ETH transfer and token transfer occur while critical state is still mutable. An attacker contract can reenter during external call and claim many times, bypassing cooldown and daily limits.
Likelihood:
High — attacker contracts receive Ether and execute fallback/receive, providing a natural point to reenter while the contract is mid-function.
Frequent — any call path that pays ETH or transfers tokens to an external contract triggers this vector.
Impact:
Drain of faucet tokens and Sepolia ETH beyond intended limits.
Bypass of cooldown and daily caps causing unlimited repeated claims.
Explanation: When claimFaucetTokens() sends ETH to this attacker, the fallback receive() function executes before the faucet’s state updates, allowing another call into claimFaucetTokens().
This repeats, letting the attacker claim multiple times in one transaction and bypass all cooldown restrictions.
Explanation: Reordering the logic ensures all internal state updates happen before any external calls. Additionally, applying nonReentrant from OpenZeppelin’s ReentrancyGuard adds a second layer of safety. This strictly enforces cooldowns and prevents attackers from reentering the claim function mid-execution.
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.