Root + Impact
Description
The Claimed event is emitted after the faucetDrip is transferred to the user, potentially causing confusion and misinterpretation of the event by users and dapps.
function claimFaucetTokens() public {
...
lastClaimTime[faucetClaimer] = block.timestamp;
dailyClaimCount++;
_transfer(address(this), faucetClaimer, faucetDrip);
@> emit Claimed(msg.sender, faucetDrip);
...
}
Risk
Likelihood:
Impact:
Proof of Concept
Add the following code snippet to the RaiseBoxFaucet.t.sol test file.
This code snippet is designed to demonstrate the Claimed event is emitted after the faucetDrip is transferred to the user, after all standard ERC20 events have already been emitted.
event SepEthDripped(address indexed claimant, uint256 amount);
event Transfer(address indexed from, address indexed to, uint256 value);
event Claimed(address indexed user, uint256 amount);
function testClaimedEvents() public {
vm.expectEmit(true, false, false, true, address(raiseBoxFaucet));
emit SepEthDripped(user1, raiseBoxFaucet.sepEthAmountToDrip());
vm.expectEmit(true, true, false, true, address(raiseBoxFaucet));
emit Transfer(address(raiseBoxFaucet), user1, raiseBoxFaucet.faucetDrip());
vm.expectEmit(true, false, false, true, address(raiseBoxFaucet));
emit Claimed(user1, raiseBoxFaucet.faucetDrip());
vm.prank(user1);
raiseBoxFaucet.claimFaucetTokens();
console.log("user balance of ETH: ", user1.balance);
console.log("user balance of faucet tokens: ", raiseBoxFaucet.balanceOf(user1));
}
Recommended Mitigation
To follow the Check-Effects-Interactions (CEI) pattern and emit the event before the interaction, the Claimed event should be emitted before the faucetDrip is transferred to the user.
function claimFaucetTokens() public {
...
// Effects
lastClaimTime[faucetClaimer] = block.timestamp;
dailyClaimCount++;
+ emit Claimed(msg.sender, faucetDrip);
// Interactions
_transfer(address(this), faucetClaimer, faucetDrip);
- emit Claimed(msg.sender, faucetDrip);
...