The claimFaucetTokens function in the RaiseBoxFaucet contract uses inconsistent logic for resetting the daily claim counters for Sepolia ETH drips (dailyDrips) and token claims (dailyClaimCount). The ETH drip reset uses currentDay = block.timestamp / 24 hours, which resets dailyDrips based on a precise 24-hour boundary (Unix timestamp divided by 86400 seconds). In contrast, the token claim reset uses if (block.timestamp > lastFaucetDripDay + 1 days), which depends on the last claim timestamp (lastFaucetDripDay) plus a 24-hour period. This misalignment can cause the dailyClaimCount to not reset when expected, leading to a denial of service (DoS) where legitimate users are unable to claim tokens due to the dailyClaimLimit being reached prematurely.
Medium
The inconsistent reset logic can prevent users from claiming tokens on a new day if the lastFaucetDripDay + 1 days condition is not met, even though the ETH drip counter resets correctly. This disrupts the faucet’s functionality, especially in a testnet environment where users rely on timely token distribution for testing purposes. In a mainnet context, this could lead to user dissatisfaction and loss of trust in the protocol.
Denial of Service: Users may be unable to claim tokens due to dailyClaimCount not resetting, even when a new day has started for ETH drips.
Inconsistent Behavior: The mismatch between ETH and token reset logic creates confusion and unreliable faucet operation.
User Experience Degradation: Legitimate users are blocked from claiming tokens, impacting the faucet’s purpose of facilitating testnet interactions.
Manual code review
Foundry (for Proof of Concept testing)
Unified Reset Logic: Use the same reset mechanism for both dailyDrips and dailyClaimCount. Adopt the currentDay = block.timestamp / 24 hours logic for both to ensure consistent daily resets.
Update State Variables: Store the last reset day for both ETH and token claims in a single variable (e.g., lastResetDay) to avoid discrepancies.
Documentation: Clearly document the reset logic to ensure developers understand the daily boundary behavior.
Modified Code Example:
The following Foundry test demonstrates the bug by showing how the inconsistent reset logic prevents a user from claiming tokens on a new day due to dailyClaimCount not resetting.
Explanation of PoC:
The test deploys the RaiseBoxFaucet contract with a dailyClaimLimit of 2 for simplicity.
claimer1 claims tokens at 3.5 days (timestamp: 302400 seconds, currentDay = 3), setting dailyClaimCount = 1, lastFaucetDripDay = 302400, and lastDripDay = 3.
The time is warped to 4 days + 1 minute (timestamp: 345660 seconds, currentDay = 4), which is a new day for ETH drips, so during claimer2's claim, dailyDrips resets to 0 and lastDripDay updates to 4.
However, the token reset condition (block.timestamp > lastFaucetDripDay + 1 days = 345660 > 302400 + 86400 = 388800) is false, so dailyClaimCount is not reset and increments to 2.
claimer3 attempts to claim but fails due to RaiseBoxFaucet_DailyClaimLimitReached (since dailyClaimCount = 2 >= 2), demonstrating the DoS: on a new day, the token count carries over, blocking additional claims even though ETH resets correctly. If the logic was consistent, the count would reset, allowing more claims.
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.