Snowman Merkle Airdrop

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

Users can receive tokens without proper payment validation

Users can potentially receive tokens without proper payment validation due to flawed payment logic in Snow::buySnow

Description: The payment validation logic in buySnow uses an equality check for ETH payments but falls through to WETH transfer without proper validation if the ETH amount doesn't match exactly. This creates a potential for users to receive tokens without proper payment.

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);
}
}

The logic flaw allows scenarios where:

  • User sends wrong ETH amount (triggers else branch)

  • WETH transfer fails but tokens are still minted

  • No explicit validation of payment success

Impact: Users can potentially receive tokens without paying, breaking the economic model.

Proof of Concept:

function test_PaymentLogicFlaw() public {
uint256 initialBalance = snow.balanceOf(attacker);
// Send wrong ETH amount with no WETH approval
uint256 correctFee = getBuyFee();
try snow.buySnow{value: 1 wei}(1) {
uint256 newBalance = snow.balanceOf(attacker);
if (newBalance > initialBalance) {
// If this succeeds, there's a bug - got tokens with wrong payment
}
} catch {
// Attack failed as expected - payment validation working
}
}

Recommended Mitigation: Implement explicit payment path validation:

error S__InvalidPayment();
function buySnow(uint256 amount) external payable canFarmSnow {
if (amount == 0) revert S__ZeroValue();
uint256 totalCost = s_buyFee * amount;
if (msg.value > 0) {
// ETH payment path
if (msg.value != totalCost) {
revert S__InvalidPayment();
}
_mint(msg.sender, amount);
} else {
// WETH payment path
i_weth.safeTransferFrom(msg.sender, address(this), totalCost);
_mint(msg.sender, amount);
}
emit SnowBought(msg.sender, amount);
}
Updates

Lead Judging Commences

yeahchibyke Lead Judge 3 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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