Snowman Merkle Airdrop

AI First Flight #10
Beginner FriendlyFoundrySolidityNFT
EXP
View results
Submission Details
Impact: medium
Likelihood: high
Invalid

Missing Event Emissions in earnSnow() and collectFee() Functions


Description

The contract defines events but doesn't emit them in the corresponding functions, creating gaps in the event log that prevent proper tracking of contract activities.

// @> earnSnow() function missing event emission
function earnSnow() external canFarmSnow {
if (s_earnTimer != 0 && block.timestamp < (s_earnTimer + 1 weeks)) {
revert S__Timer();
}
_mint(msg.sender, 1);
s_earnTimer = block.timestamp;
// @> Missing: emit SnowEarned(msg.sender, 1);
}
// @> collectFee() function missing event emission
function collectFee() external onlyCollector {
uint256 collection = i_weth.balanceOf(address(this));
i_weth.transfer(s_collector, collection);
(bool collected,) = payable(s_collector).call{value: address(this).balance}("");
require(collected, "Fee collection failed!!!");
// @> Missing: emit FeeCollected();
}

Risk

Likelihood:

  • Reason 1 : Events are defined in the contract but never emitted during normal operations

  • Reason 2 : Both functions execute successfully without emitting their designated events

Impact:

  • Impact 1 : Off-chain applications cannot track token earning activities, breaking monitoring systems

  • Impact 2 : Fee collection operations are invisible on-chain, reducing transparency and auditability

Proof of Concept

Add these test functions to test/TestSnow.t.sol:

function testMissingSnowEarnedEvent() public {
// Setup: Expect SnowEarned event but it won't be emitted
vm.expectEmit(false, false, false, true);
emit SnowEarned(ashley, 1); // This expectation will fail
vm.prank(ashley);
snow.earnSnow(); // Function succeeds but no event emitted
// Verify token was still minted despite missing event
assert(snow.balanceOf(ashley) == 1);
}
function testMissingFeeCollectedEvent() public {
// Setup: Generate fees to collect
vm.startPrank(jerry);
weth.approve(address(snow), FEE);
snow.buySnow(1);
vm.stopPrank();
vm.prank(victory);
snow.buySnow{value: FEE}(1);
// Expect FeeCollected event but it won't be emitted
vm.expectEmit(false, false, false, true);
emit FeeCollected(); // This expectation will fail
vm.prank(collector);
snow.collectFee(); // Function succeeds but no event emitted
// Verify fees were still collected despite missing event
assert(weth.balanceOf(collector) == FEE);
assert(collector.balance == FEE);
}

Recommended Mitigation

function earnSnow() external canFarmSnow {
if (s_earnTimer != 0 && block.timestamp < (s_earnTimer + 1 weeks)) {
revert S__Timer();
}
_mint(msg.sender, 1);
s_earnTimer = block.timestamp;
+ emit SnowEarned(msg.sender, 1);
}
function collectFee() external onlyCollector {
uint256 collection = i_weth.balanceOf(address(this));
i_weth.transfer(s_collector, collection);
(bool collected,) = payable(s_collector).call{value: address(this).balance}("");
require(collected, "Fee collection failed!!!");
+ emit FeeCollected();
}
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!