Snowman Merkle Airdrop

First Flight #42
Beginner FriendlyFoundrySolidityNFT
100 EXP
Submission Details
Impact: high
Likelihood: medium
Invalid

Ambiguous ETH/WETH Payment Logic Leads to Unintended WETH Drain

Author Revealed upon completion

Root + Impact

Description

If the amount of ETH sent by the user is slightly more or less than s_buyFee * amount, the function will assume the user intends to pay with WETH and will attempt to transfer it.

The problem is: if the user has previously approved WETH, the contract will directly deduct WETH from the user's balance—even if the user actually intended to pay with ETH—resulting in an unexpected loss of assets.

function buySnow(uint256 amount) external payable canFarmSnow {
@> if (msg.value == (s_buyFee * amount)) {
_mint(msg.sender, amount);
@> } else {
i_weth.safeTransferFrom(msg.sender, address(this), (s_buyFee * amount));
_mint(msg.sender, amount);
}

Risk

Impact:

The user intended to purchase Snow using ETH, but WETH was mistakenly deducted by the contract.

As a result, the user's assets were incorrectly transferred, leading to a financial loss.

Proof of Concept

// Assume s\_buyFee = 0.01 ETH and amount = 10, so the expected payment is 0.1 ETH
// When the user inputs the amount via the frontend, a buffer is automatically added, resulting in an overpayment of 0.0001 ETH
buySnow{value: 0.1001 ether}(10);
// Since msg.value ≠ s\_buyFee \* amount, the function enters the `else` branch
// If the user has previously approved enough WETH, it will be directly deducted:
i_weth.safeTransferFrom(msg.sender, address(this), 0.1 ether);
// In reality: the user loses 0.1 ETH (ignored) + 0.1 WETH (deducted)

Recommended Mitigation

Enforce that only one payment method is allowed—either an exact ETH amount or a full WETH transfer—to avoid ambiguous logic.

require(
msg.value == 0 || msg.value == (s_buyFee * amount),
"Invalid ETH value sent"
);
Updates

Lead Judging Commences

yeahchibyke Lead Judge
about 17 hours ago
yeahchibyke Lead Judge about 5 hours ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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