dailyDrips is reset for repeat ETH claimers , allowing the daily ETH cap (dailySepEthCap) to be bypassed.
Description
-
Each user can claim a fixed amount of faucet tokens and, if they have not claimed ETH before, a small amount of Sepolia ETH.
-
The contract resets dailyDrips = 0 whenever a user who has already claimed ETH calls claimFaucetTokens().
function claimFaucetTokens() public {
....
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"
);
}
@> }else {
@> dailyDrips = 0;
}
Risk
Likelihood:
-
Users can trigger this whenever they have previously claimed ETH and call claimFaucetTokens() again.
-
Occurs even without malicious intent, simply by interacting with the faucet multiple times in a day.
Impact:
-
Daily ETH cap can be bypassed.
-
Faucet may run out of ETH faster than intended.
-
Misleading metrics for ETH distribution.
Proof of Concept
This PoC shows that when user2, user3 and user4 claimed from the faucet for the 1st time they received Sepolia ETh and dailyDrips increased to 3 but when user1 claimed from the faucet again dailyDrips reset to 0
function testdailydripreset() public {
vm.prank(user1);
raiseBoxFaucet.claimFaucetTokens();
vm.warp(block.timestamp + raiseBoxFaucet.CLAIM_COOLDOWN());
vm.prank(user2);
raiseBoxFaucet.claimFaucetTokens();
vm.prank(user3);
raiseBoxFaucet.claimFaucetTokens();
vm.prank(user4);
raiseBoxFaucet.claimFaucetTokens();
console.log("Drip before the reclaim by user 1st",raiseBoxFaucet.dailyDrips());
assertEq(raiseBoxFaucet.dailyDrips(), 150000000000000000);
vm.prank(user1);
raiseBoxFaucet.claimFaucetTokens();
console.log("Drip after the reclaim by user 1st",raiseBoxFaucet.dailyDrips());
assertEq(raiseBoxFaucet.dailyDrips(), 0);
}
Ran 1 test for test/RaiseBoxFaucet.t.sol:TestRaiseBoxFaucet
[PASS] testdailydripreset() (gas: 591487)
Logs:
Drip before the reclaim by user 1st 150000000000000000
Drip after the reclaim by user 1st 0
Recommended Mitigation
Remove the else part in the if-else block which checks if a user has claimed for the first time
Remove the else part in the if-else block which checks if a user has claimed for the first time
- else {dailyDrips = 0;}