Raisebox Faucet

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

Faucet and ETH drips resets are not synced causing user friction

Root + Impact / Faucet and ETH drips resets are not synced causing user friction

Description

  • The protocol defines daily limits for both Faucet token and ETH drips, which should reset every 24 hours.

  • However, the RaiseBoxFaucet::dailyClaimCount is reset exactly after 24 hours have passed, while the ETH drip counter RaiseBoxFaucet::dailyDrips is reset based on a strict “day change” condition.

  • This desynchronization causes inconsistent reset timing between the two.

uint256 currentDay = block.timestamp / 24 hours;
@> if (currentDay > lastDripDay) {
lastDripDay = currentDay;
dailyDrips = 0;
// dailyClaimCount = 0;
}
@> if (block.timestamp > lastFaucetDripDay + 1 days) {
lastFaucetDripDay = block.timestamp;
dailyClaimCount = 0;
}

Risk

Likelihood:

  • The issue can occur on any RaiseBoxFaucet::claimFaucetTokens call where only one of the limits is reset due to the timing mismatch.

Impact

  • Users may experience friction when one of the limits (Faucet or ETH) is reset while the other remains locked.

  • As a result, new users may be unable to perform the intended “happy path” action of claiming both Faucet tokens and ETH in a single call, reducing usability and creating confusion.

Proof of Concept

Add the following test to RaiseBoxFaucet.t.sol to reproduce the issue:

function test_audit_faucetAndEthDripsResetsAreNotSynced() public {
// Start at 3 days and 12 hours not to hit the CLAIM_COOLDOWN period
vm.warp(84 hours);
vm.prank(user1);
raiseBoxFaucet.claimFaucetTokens();
// Move to the next day
vm.warp(block.timestamp + 12 hours);
vm.prank(user2);
raiseBoxFaucet.claimFaucetTokens();
uint256 dailyFaucetClaimCount = raiseBoxFaucet.dailyClaimCount();
uint256 dailyEthDripsCount = raiseBoxFaucet.dailyDrips() /
raiseBoxFaucet.sepEthAmountToDrip();
// ETH count has been reset, but faucet count not
assertGt(dailyFaucetClaimCount, dailyEthDripsCount);
}

Recommended Mitigation

  • Unify the reset logic for both Faucet and ETH drips to use the same condition.

  • A recommended approach is to perform the reset at the beginning of claimFaucetTokens, based on whether 24 hours have passed since the last reset.

  • Using a 24-hour interval is preferable to an “exact day change,” as it ensures consistency and aligns with the RaiseBoxFaucet::CLAIM_COOLDOWN check.

function claimFaucetTokens() public {
// Checks
faucetClaimer = msg.sender;
+ // Use same variable lastDripDay for both - ETH and Faucet token to simplify and make sure they are in sync
+ if (block.timestamp > lastDripDay + 1 days) {
+ lastDripDay = block.timestamp;
+ dailyClaimCount = 0; // Faucet token
+ dailyDrips = 0; // ETH
+ }
if (!hasClaimedEth[faucetClaimer] && !sepEthDripsPaused) {
- uint256 currentDay = block.timestamp / 24 hours;
- if (currentDay > lastDripDay) {
- lastDripDay = currentDay;
- dailyDrips = 0;
- // dailyClaimCount = 0;
- }
- if (block.timestamp > lastFaucetDripDay + 1 days) {
- lastFaucetDripDay = block.timestamp;
- dailyClaimCount = 0;
- }
// Effects
Updates

Lead Judging Commences

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

dailyClaimCount Reset Bug

Appeal created

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

Inconsistent day calculation methods cause desynchronization between ETH and token daily resets.

Support

FAQs

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