Snowman Merkle Airdrop

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

collectFee uses a bare ERC20 transfer instead of safeTransfer, silently failing for non-standard tokens

collectFee uses a bare transfer with discarded return, so a non-standard WETH can silently lock fees

Description

The contract declares using SafeERC20 for IERC20 and uses safeTransferFrom in buySnow, but collectFee moves the WETH balance with a raw ERC20 transfer whose boolean return is ignored.

function collectFee() external onlyCollector {
uint256 collection = i_weth.balanceOf(address(this));
i_weth.transfer(s_collector, collection); // @> bare transfer, return value discarded
(bool collected,) = payable(s_collector).call{value: address(this).balance}("");
require(collected, "Fee collection failed!!!");
}

A token that returns false on failure instead of reverting (USDT-style) would let collectFee continue and report success while no WETH actually moved.

Risk

Likelihood:

Depends on the configured WETH-like token. Canonical WETH reverts, but any non-standard or fee-on-transfer token returning false on failure triggers the silent path; the SafeERC20 import shows the codebase already expects to guard against this class.

Impact:

Collected fees remain locked in the contract while the call reports success, so the collector believes funds were swept when they were not. Loss is bounded to accrued fees.

Proof of Concept

A mock WETH returning false on transfer makes collectFee succeed yet move nothing.

function test_bareTransferSilentFail() public {
// i_weth configured to a token that returns false on transfer
vm.prank(collector);
snow.collectFee(); // does not revert
assertGt(weth.balanceOf(address(snow)), 0); // fees still stuck
}

Recommended Mitigation

Use the already-imported safeTransfer.

- i_weth.transfer(s_collector, collection);
+ i_weth.safeTransfer(s_collector, collection);
Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge about 5 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!