Raisebox Faucet

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

Daily ETH cap can be trivially reset

# Daily ETH cap can be trivially reset

## Description

Inside claimFaucetTokens, when a claimer is **not** eligible for Sepolia ETH—because they have already claimed or drips are paused—the function executes `else { dailyDrips = 0; }`. That unconditional reset wipes the running total of ETH distributed for the day. As a result, any repeat claimer (or a claim during a pause) can zero the counter, erasing the record of prior distributions.

## Risk

  • **Severity:** High

  • The faucet’s daily Sepolia ETH budget, enforced via dailySepEthCap, can be bypassed. After the counter is reset, subsequent first-time claimers see dailyDrips == 0 and drain ETH even if the cap was already reached.

- An attacker can script alternating first-time and repeat claims to continually drain the faucet’s ETH reserves far beyond the intended daily cap.

## Proof of Concept

Run the following scenario:

```text

1. User A (first-time claimer) calls `claimFaucetTokens` → `dailyDrips = 0.005 ether`.

2. User B (repeat claimer) calls `claimFaucetTokens` → `dailyDrips` is set back to `0`.

3. User C (first-time) now calls `claimFaucetTokens` → faucet believes no ETH has been distributed today and sends another `0.005 ether`.

4. Repeat step 2 with any repeat claimer to keep resetting the counter, allowing unlimited first-time claims per day.

```

Under attack, the faucet loses its ETH buffer despite nominal caps.

## Recommended Mitigation

Track dailyDrips as cumulative ETH sent during the current day and reset it **only** when the day boundary rolls over:

```solidity

if (block.timestamp / 1 days > lastDripDay) {

lastDripDay = block.timestamp / 1 days;

dailyDrips = 0;

}

if (!hasClaimedEth[claimant] && !sepEthDripsPaused) {

uint256 newTotal = dailyDrips + sepEthAmountToDrip;

if (newTotal <= dailySepEthCap) {

dailyDrips = newTotal;

hasClaimedEth[claimant] = true;

(bool success, ) = claimant.call{value: sepEthAmountToDrip}("");

if (!success) revert RaiseBoxFaucet_EthTransferFailed();

} else {

emit SepEthDripSkipped(claimant, "Daily ETH cap reached");

}

}

```

  • Delete the branch that sets dailyDrips = 0 when ETH isn’t distributed.

  • Reset dailyDrips only when a new day starts.

- Always increment `dailyDrips` just before sending ETH so the cap reflects actual payouts.

Updates

Lead Judging Commences

inallhonesty Lead Judge
23 days ago
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.