Raisebox Faucet

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

Incorrect dailyDrips reset allows exceeding daily ETH cap

Incorrect dailyDrips reset allows exceeding daily ETH cap

Description

  • Normal behavior: the contract should enforce the daily ETH drip cap (dailySepEthCap) by tracking how much ETH has already been dripped today (dailyDrips) and only reset that counter when the global day boundary advances.

  • Specific issue: code resets dailyDrips in an else branch that can be triggered by a per-claimer condition (or other non-global condition). That single condition zeroes the global dailyDrips counter and allows the faucet to drip more ETH than the intended daily cap when unrelated users claim.

function claimFaucetTokens() public {
//existing code...
if (!hasClaimedEth[faucetClaimer] && !sepEthDripsPaused) {
//existing code...
} else {
@> dailyDrips = 0;
}
//existing code...
}

Risk

Likelihood: High

  • Happens when the specific branch condition is met (e.g., a claimant with an old last-claim timestamp), which is plausible in normal operation.

Impact: High

  • Global ETH distribution accounting is reset incorrectly and attackers or normal users can cause the faucet to distribute more than dailySepEthCap in a day.

Proof of Concept

This PoC demonstrates -> daily cap distribution by exercising many claims and triggering the problematic reset:

function testClaimFaucetEthTooMuchGiven() public {
// new contract with 0.4 eth drip limit setup
raiseBoxFaucet = new RaiseBoxFaucet("raiseboxtoken", "RB", 1000 * 10 ** 18, 0.005 ether, 0.4 ether);
vm.deal(address(raiseBoxFaucet), 10 ether);
// user94 made a claim earlier (3 days ago) which causes the problematic branch to run
address faucetClaimer0 = makeAddr(string(abi.encodePacked(uint256(94))));
vm.prank(faucetClaimer0);
raiseBoxFaucet.claimFaucetTokens();
advanceBlockTime(block.timestamp + 3 days);
uint256 sepEthDistributed = 0;
for (uint256 i = 0; i < 99; i++) {
address faucetClaimer = makeAddr(string(abi.encodePacked(uint256(i))));
uint256 preBalance = faucetClaimer.balance;
vm.prank(faucetClaimer);
raiseBoxFaucet.claimFaucetTokens();
sepEthDistributed += faucetClaimer.balance - preBalance;
}
// After the buggy reset, more than the daily cap (0.4 ETH) was distributed
assertGt(sepEthDistributed, 0.4 ether);
}

Run the test with:

forge test --match-test testClaimFaucetEthTooMuchGiven -vvv

Recommended Mitigation

  • Only reset dailyDrips on a global day boundary.

function claimFaucetTokens() public {
//existing code...
if (!hasClaimedEth[faucetClaimer] && !sepEthDripsPaused) {
//existing code...
- } else {
- dailyDrips = 0;
- }
//existing code...
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 8 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.