AirDropper

AI First Flight #5
Beginner FriendlyDeFiFoundry
EXP
View results
Submission Details
Impact: low
Likelihood: low
Invalid

claimFees emits no event and has no zero-balance guard, reducing transparency and wasting gas on empty sweeps

claimFees() emits no event and lacks a zero-balance guard, reducing transparency and wasting gas on empty sweeps

Description

claimFees() transfers the contract's ETH balance to the owner but emits no event and does not guard against a zero balance, so an empty sweep still executes a state-changing call with no observable record.

function claimFees() external onlyOwner {
(bool succ,) = payable(owner()).call{ value: address(this).balance }(""); // @> no event emitted; no balance>0 guard
if (!succ) {
revert MerkleAirdrop__TransferFailed();
}
}

(src/MerkleAirdrop.sol:42-47)

Risk

Likelihood: Low

This is a transparency and minor-gas concern that applies whenever fees are swept (or swept early at zero balance). It has no exploit path and cannot move funds incorrectly.

Impact: Low

The absence of a FeesClaimed event makes off-chain monitoring of owner withdrawals harder and less auditable. Calling with a zero balance performs an unnecessary external call and wastes gas without doing anything useful.

Proof of Concept

Calling claimFees() with no accumulated fees succeeds silently, emitting nothing and transferring zero.

function test_claimFeesEmptyNoEvent() public {
vm.recordLogs();
vm.prank(owner);
airdrop.claimFees(); // balance is 0
Vm.Log[] memory logs = vm.getRecordedLogs();
assertEq(logs.length, 0); // no FeesClaimed event
}

Recommended Mitigation

Emit a FeesClaimed event and short-circuit when the balance is zero.

+ event FeesClaimed(address indexed to, uint256 amount);
function claimFees() external onlyOwner {
+ uint256 amount = address(this).balance;
+ if (amount == 0) {
+ revert MerkleAirdrop__InvalidFeeAmount();
+ }
- (bool succ,) = payable(owner()).call{ value: address(this).balance }("");
+ (bool succ,) = payable(owner()).call{ value: amount }("");
if (!succ) {
revert MerkleAirdrop__TransferFailed();
}
+ emit FeesClaimed(owner(), amount);
}
Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge about 3 hours ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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

Give us feedback!