Raisebox Faucet

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

User can claim eth sepolia even though the dailySepEthCap was reached

User can claim eth sepolia even though the dailySepEthCap was reached

Description

Each time a user claims drip for the first time, he will earn an amount of sepolia eth.
And each time it appends the dailyDrips will be incremented, and we will check if it is greater than sepEthAmountToDrip as the following:

if (!hasClaimedEth[faucetClaimer] && !sepEthDripsPaused) {
...
if (dailyDrips + sepEthAmountToDrip <= dailySepEthCap && address(this).balance >= sepEthAmountToDrip) {
hasClaimedEth[faucetClaimer] = true;
dailyDrips += sepEthAmountToDrip;
}
...
} else {
dailyDrips = 0;
}

The problem is related to the else settlement. If user claims a drip again, he will trigger this settlement and if the dailyDrips already reach the dailySepEthCap, it will return to 0 allowing another user who didn't claim drip yet to earn sepolia eth even though the dailySepEthCap was already reached this day.

Risk

Likelyhood (High) : Every time the claimer calls the function claimFaucetTokens, the dailyDrip will be reset.

Impact (Medium) : The sepolia eth reserves of the contract could be drained unintentionally by new claimers, because this else settlement breaks the dailyDrip and dailySepEthCap conditions.

Proof of Concept

In the RaiseBoxFaucet.t.sol change the sepEthDrip and the dailySepEthCap for test purposes:

function setUp() public {
owner = address(this);
raiseBoxFaucet = new RaiseBoxFaucet(
"raiseboxtoken",
"RB",
1000 * 10 ** 18,
0.5 ether, // instead of 0.005 ether
1 ether // instead of 0.5 ether
);
...
}

And add this test :

function testDailySepEthDrip() public {
vm.prank(user1);
raiseBoxFaucet.claimFaucetTokens();
assertEq(block.timestamp, raiseBoxFaucet.getUserLastClaimTime(user1));
// 3 days later
advanceBlockTime(block.timestamp + 3 days);
vm.prank(user2);
raiseBoxFaucet.claimFaucetTokens();
assertEq(user2.balance, 0.5 ether);
vm.prank(user3);
raiseBoxFaucet.claimFaucetTokens();
assertEq(user3.balance, 0.5 ether);
// Daily ETH cap reached for user4, expected
vm.prank(user4);
raiseBoxFaucet.claimFaucetTokens();
assertEq(user4.balance, 0 ether);
// User1 reclaim a drip once more and dailydrip for new user is reset the same day
vm.prank(user1);
raiseBoxFaucet.claimFaucetTokens();
// user5 claim the sepEthdrip even if the daily Eth cap is supposed to be reached.
vm.prank(user5);
raiseBoxFaucet.claimFaucetTokens();
assertEq(user5.balance, 0.5 ether);
}

Recommended Mitigation

Remove the else stalement.

if (!hasClaimedEth[faucetClaimer] && !sepEthDripsPaused) {
...
if (dailyDrips + sepEthAmountToDrip <= dailySepEthCap && address(this).balance >= sepEthAmountToDrip) {
hasClaimedEth[faucetClaimer] = true;
dailyDrips += sepEthAmountToDrip;
}
...
+ }
- } else {
- dailyDrips = 0;
- }
Updates

Lead Judging Commences

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