Root + Impact
Description
-
The adjustDailyClaimLimit() function modifies the dailyClaimLimit state variable without emitting an event. This makes it difficult for off-chain services to monitor changes to this critical parameter, reducing transparency and auditability.
-
The adjustDailyClaimLimit function, which can only be called by the owner, directly modifies the dailyClaimLimit state variable but does not emit an event to signal that the change has occurred.
function adjustDailyClaimLimit(uint256 by, bool increaseClaimLimit) public onlyOwner {
if (increaseClaimLimit) {
@> dailyClaimLimit += by;
} else {
if (by > dailyClaimLimit) {
revert RaiseBoxFaucet_CurrentClaimLimitIsLessThanBy();
}
@> dailyClaimLimit -= by;
}
}
Risk
Likelihood:
Impact:
-
Lack of Transparency: Users and monitoring tools cannot easily track changes to one of the faucet's key parameters.
-
Difficulty for Off-Chain Services: Any off-chain service that needs to react to changes in the daily claim limit would have to constantly poll the contract, which is inefficient and slow.
Proof of Concept
pragma solidity ^0.8.30;
import {Test, console} from "forge-std/Test.sol";
import {RaiseBoxFaucet} from "../src/RaiseBoxFaucet.sol";
contract MissingEventsTest is Test {
RaiseBoxFaucet faucet;
address owner;
function setUp() public {
faucet = new RaiseBoxFaucet(
"RaiseBoxToken",
"RBT",
1000 * 10**18,
0.005 ether,
0.5 ether
);
owner = faucet.owner();
}
function testMissingEventOnAdjustDailyClaimLimit() public {
vm.expectEmit(true, true, true, true);
emit DailyClaimLimitUpdated(faucet.dailyClaimLimit(), faucet.dailyClaimLimit() + 50, true);
vm.prank(owner);
faucet.adjustDailyClaimLimit(50, true);
}
event DailyClaimLimitUpdated(uint256 oldLimit, uint256 newLimit, bool increase);
}
Test Result: The test fails as expected, confirming the absence of the event.
[FAIL: log != expected log] testMissingEventOnAdjustDailyClaimLimit() (gas: 24052)
Suite result: FAILED. 0 passed; 1 failed; 0 skipped; finished in 5.45ms (4.58ms CPU time)
Recommended Mitigation
An event should be emitted whenever the `dailyClaimLimit` is changed. This can be done by defining a `DailyClaimLimitUpdated` event and emitting it within the `adjustDailyClaimLimit` function.
```solidity
contract RaiseBoxFaucet is ERC20, Ownable {
// ...
event DailyClaimLimitUpdated(uint256 oldLimit, uint256 newLimit, bool increased);
function adjustDailyClaimLimit(uint256 by, bool increaseClaimLimit) public onlyOwner {
uint256 oldLimit = dailyClaimLimit;
if (increaseClaimLimit) {
dailyClaimLimit += by;
} else {
if (by > dailyClaimLimit) {
revert RaiseBoxFaucet_CurrentClaimLimitIsLessThanBy();
}
dailyClaimLimit -= by;
}
emit DailyClaimLimitUpdated(oldLimit, dailyClaimLimit, increaseClaimLimit);
}
// ...
}