Raisebox Faucet

First Flight #50
Beginner FriendlySolidity
100 EXP
Submission Details
Impact: high
Likelihood: high

The dailyDrips is incorrectly set to zero

Author Revealed upon completion

Root + Impact

Description

  • A person who is not receiving ETH for the first time will mistakenly set the ETH issuance count for that day to 0.

if (!hasClaimedEth[faucetClaimer] && !sepEthDripsPaused) {
uint256 currentDay = block.timestamp / 24 hours;
if (currentDay > lastDripDay) {
lastDripDay = currentDay;
dailyDrips = 0;
// dailyClaimCount = 0;
}
if (dailyDrips + sepEthAmountToDrip <= dailySepEthCap && address(this).balance >= sepEthAmountToDrip) {
hasClaimedEth[faucetClaimer] = true;
dailyDrips += sepEthAmountToDrip;
(bool success,) = faucetClaimer.call{value: sepEthAmountToDrip}("");
if (success) {
emit SepEthDripped(faucetClaimer, sepEthAmountToDrip);
} else {
revert RaiseBoxFaucet_EthTransferFailed();
}
} else {
emit SepEthDripSkipped(
faucetClaimer,
address(this).balance < sepEthAmountToDrip ? "Faucet out of ETH" : "Daily ETH cap reached"
);
}
} else {
// @>
dailyDrips = 0;
}

Risk

Likelihood:

  • If this is not the first time to claim (or ETH is suspended), clear dailyDrips to zero


Impact:

  • If it is not the first time to receive (or ETH is suspended), dailyDrips will be cleared to zero. For a person who is not receiving for the first time, this may cause the actual amount of distribution to exceed the daily ETH limit.

Proof of Concept

/// @notice Testing dailyDrips reset logic error
/// @dev Proving that users who are not claiming for the first time may accidentally reset the ETH issuance count for the day
function testDailyDripsResetBug() public {
console.log("=== Testing dailyDrips reset logic error ===");
// Initial state
uint256 initialDailyDrips = raiseBoxFaucet.dailyDrips();
console.log("Initial dailyDrips:", initialDailyDrips);
// First user claims for the first time - dailyDrips should be increased
vm.prank(user1);
raiseBoxFaucet.claimFaucetTokens();
uint256 afterFirstUser = raiseBoxFaucet.dailyDrips();
console.log("DailyDrips after user1's first claim:", afterFirstUser);
// Verify that dailyDrips are increased for the first user
assertEq(afterFirstUser, raiseBoxFaucet.sepEthAmountToDrip(), "The first user should increase their dailyDrips");
// Second user claims for the first time - dailyDrips should continue to increase
vm.prank(user2);
raiseBoxFaucet.claimFaucetTokens();
uint256 afterSecondUser = raiseBoxFaucet.dailyDrips();
console.log("user2's dailyDrips after first claim:", afterSecondUser);
// Verify that the second user also increases their dailyDrips
uint256 expectedDrips = raiseBoxFaucet.sepEthAmountToDrip() * 2;
assertEq(afterSecondUser, expectedDrips, "The second user should continue to increase their dailyDrips");
// Now the first user claims again (not for the first time) - this will trigger a bug!
vm.warp(block.timestamp + 3 days); // Wait for the cooldown period
vm.prank(user1);
raiseBoxFaucet.claimFaucetTokens();
uint256 afterUser1SecondClaim = raiseBoxFaucet.dailyDrips();
console.log("user1's dailyDrips after the second claim:", afterUser1SecondClaim);
// This is the bug: dailyDrips is accidentally reset to 0!
assertEq(afterUser1SecondClaim, 0, "BUG: user1's second claim accidentally resets dailyDrips to 0");
console.log("=== Problem Analysis ===");
console.log("Problem: In line 212 of the claimFaucetTokens function, when this is not the user's first claim, ");
console.log("The code executes 'dailyDrips = 0;', which resets the ETH issuance count for that day");
console.log("This means that subsequent first-time claiming users on the same day may receive more ETH than the daily limit");
// Demonstrate the impact of this bug: The third user makes their first claim, but dailyDrips is reset
vm.prank(user3);
raiseBoxFaucet.claimFaucetTokens();
uint256 afterUser3FirstClaim = raiseBoxFaucet.dailyDrips();
console.log("user3's dailyDrips after first claim:", afterUser3FirstClaim);
// Verify that the third user still receives ETH even though the previous dailyDrips were reset.
assertEq(afterUser3FirstClaim, raiseBoxFaucet.sepEthAmountToDrip(), "The third user still receives ETH");
console.log("Impact: This defeats the daily ETH limit protection mechanism");
}

Recommended Mitigation

- remove 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}("");
if (success) {
emit SepEthDripped(faucetClaimer, sepEthAmountToDrip);
} else {
revert RaiseBoxFaucet_EthTransferFailed();
}
} else {
emit SepEthDripSkipped(
faucetClaimer,
address(this).balance < sepEthAmountToDrip ? "Faucet out of ETH" : "Daily ETH cap reached"
);
}
}

Support

FAQs

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