Snowman Merkle Airdrop

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

Incorrect fee calculation in Snow:: buysnow function.

Root + Impact

Description

  • The buySnow function calculates the fee as s_buyFee * amount, but s_buyFee is already scaled by PRECISION (10¹⁸) in the constructor. This means the actual fee is 1e18 times larger than intended, making the token extremely expensive to purchase.


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);
}
s_earnTimer = block.timestamp;
emit SnowBought(msg.sender, amount);
}

Risk

Likelihood:

  • The bug triggers immediately upon deployment when**_buyFee > 0**.


Impact:

  • Users will pay far more than expected (e.g., if _buyFee = 1, the actual fee becomes 1e18 per token).

  • The contract could become unusable because the required WETH/ETH fee is astronomically high.

  • If s_buyFee is set to a small value (e.g., 1), the multiplication by PRECISION makes it 1e18, which is likely unintended.


Proof of Concept

This is the step by step exploit.

  1. Deploy the Contract

    • Suppose _buyFee = 1 (intended to mean 1 wei per token).

    • The constructor sets s_buyFee = 1 * 1e18.

  2. User Calls buySnow(100)

    • Expected fee: 100 * 1 wei = 100 wei.

    • Actual fee: 100 * 1e18 = 100 ether.

    • The user must pay 100 ETH for just 100 tokens, which is economically unviable.

  3. Result

    • The token becomes too expensive to buy, breaking the contract's functionality.

Recommended Mitigation

The following changes ensures the fee is calculated correctly (e.g., 1 * 100 / 1e18 = 100 wei instead of 100 * 1e18)

- remove this code
+ add this code
function buySnow(uint256 amount) external payable canFarmSnow {
+ uint256 fee = (s_buyFee * amount) / PRECISION;
- if (msg.value == (s_buyFee * amount)) {
+ if (msg.value == fee) {
_mint(msg.sender, amount);
} else
- i_weth.safeTransferFrom(msg.sender, address(this), (s_buyFee * amount));
+ i_weth.safeTransferFrom(msg.sender, address(this), fee);
_mint(msg.sender, amount);
}
s_earnTimer = block.timestamp;
emit SnowBought(msg.sender, amount);
}
Updates

Lead Judging Commences

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

Appeal created

ghufranhassan1 Submitter
5 months ago
yeahchibyke Lead Judge
5 months ago
yeahchibyke Lead Judge 5 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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