Raisebox Faucet

First Flight #50
Beginner FriendlySolidity
100 EXP
View results
Submission Details
Severity: high
Valid

DailyDrips variable resets to zero when non-first-time users claim, bypassing daily ETH cap

Root + Impact

Description

  • Describe the normal behavior in one or more sentences

  • Explain the specific issue or problem in one or more sentences

// Root cause in the codebase with @> marks to highlight the relevant section

Scope:

  • RaiseBoxFaucet.sol (Lines 185-213)

  • Function: claimFaucetTokens()

Description:

Root cause + Impact: The dailyDrips tracking variable is incorrectly reset to 0 in an else block (line 212) that executes whenever a user who has already claimed ETH attempts to claim again. This logic error causes the daily ETH cap mechanism to fail completely. The else block executes for all users except first-time claimers when ETH drips are active, resetting the cumulative daily ETH counter back to zero. This allows the contract to distribute significantly more ETH than the intended dailySepEthCap by alternating between first-time and returning users.

Risk:

Likelihood: This bug triggers automatically with normal faucet usage. Any claim by a returning user (or when ETH drips are paused) resets the counter, making it trivial to bypass the daily limit.

Impact: The daily ETH cap becomes completely ineffective. An attacker can coordinate multiple addresses to repeatedly drain the ETH balance beyond daily limits, potentially emptying the contract's ETH reserves.

Proof of Concept

if (!hasClaimedEth[faucetClaimer] && !sepEthDripsPaused) {
uint256 currentDay = block.timestamp / 24 hours;
if (currentDay > lastDripDay) {
lastDripDay = currentDay;
dailyDrips = 0; // Correct reset for new day
}
if (dailyDrips + sepEthAmountToDrip <= dailySepEthCap && ...) {
// Drip ETH logic
dailyDrips += sepEthAmountToDrip; // Increment counter
}
} else {
dailyDrips = 0; // BUG: Should NOT reset here!
}
// Attack Scenario:
// Daily cap: 0.5 ETH, Drip amount: 0.005 ETH per user
// 1. User A (first time) claims → dailyDrips = 0.005 ETH
// 2. User B (returning) claims → dailyDrips = 0 (reset!)
// 3. User C (first time) claims → dailyDrips = 0.005 ETH (should be 0.01)
// 4. User D (returning) claims → dailyDrips = 0 (reset!)
// 5. Repeat 100 times = 0.5 ETH drained (should stop after 100 first-timers)

Recommended Mitigation

- remove this code
-} else {
- dailyDrips = 0;
}
+ add this code
if (!hasClaimedEth[faucetClaimer] && !sepEthDripsPaused) {
uint256 currentDay = block.timestamp / 24 hours;
if (currentDay > lastDripDay) {
lastDripDay = currentDay;
dailyDrips = 0;
}
if (dailyDrips + sepEthAmountToDrip <= dailySepEthCap &&
address(this).balance >= sepEthAmountToDrip) {
hasClaimedEth[faucetClaimer] = true;
dailyDrips += sepEthAmountToDrip;
(bool success,) = faucetClaimer.call{value: sepEthAmountToDrip}("");
require(success, "ETH transfer failed");
emit SepEthDripped(faucetClaimer, sepEthAmountToDrip);
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 14 days ago
Submission Judgement Published
Validated
Assigned finding tags:

dailyDrips Reset Bug

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.