Snowman Merkle Airdrop

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

### [H-1] Incorrect ETH and Weth Fee Calculations in ```Snow::buySnow``` Function.

Author Revealed upon completion

[H-1] Incorrect ETH and Weth Fee Calculations in Snow::buySnow Function.

Description

The fee Charged to users in terms of ETH and WETH in Snow::buySnow
Function contains incorrect calculations,rounding errors,precision error and
unimaginary amounts,which leads to minting excessively large amount of tokens.

Impact:

1.Users can mint astronomically large amount of snow tokens due to mismatch of eth and weth calculations.

2.Excessive minting inflates the total supply of snow tokens which devalues the token and can result
in overflow/underflow issues.

3.Malicious user can exploit this issue and can mint large amount of tokens.

Proof of Concept

1.Despite of minting correct tokens as Bob.Bob cannot buy snow tokens due to math error.

2.Bob minted 1e18 tokens, but the contract logic is trying to transfer 1e36 tokens which results
in ERC20insufficientbalance error.

POC With Weth-Payment:

function test_buysnowExploitwithWETH() public {
//buying snow tokens as bob(user)
vm.startPrank(bob);
weth.mint(bob, 1e18);
weth.approve(address(snow), type(uint).max);
snow.buySnow{value: 0}(1e18);
vm.stopPrank();
/*
OwnTest::test_buysnowExploit()
├─ [0] VM::startPrank(bob: [0x1D96F2f6BeF1202E4Ce1Ff6Dad0c2CB002861d3e])
│ └─ ← [Return]
├─ [49997] MockWETH::mint(bob: [0x1D96F2f6BeF1202E4Ce1Ff6Dad0c2CB002861d3e], 1000000000000000000 [1e18])
│ ├─ emit Transfer(from: 0x0000000000000000000000000000000000000000, to: bob: [0x1D96F2f6BeF1202E4Ce1Ff6Dad0c2CB002861d3e], value: 1000000000000000000 [1e18])
│ └─ ← [Return]
├─ [26927] MockWETH::approve(Snow: [0x2e234DAe75C793f67A35089C9d99245E1C58470b], 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77])
│ ├─ emit Approval(owner: bob: [0x1D96F2f6BeF1202E4Ce1Ff6Dad0c2CB002861d3e], spender: Snow: [0x2e234DAe75C793f67A35089C9d99245E1C58470b], value: 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77])
│ └─ ← [Return] true
├─ [10932] Snow::buySnow(1000000000000000000 [1e18])
│ ├─ [3911] MockWETH::transferFrom(bob: [0x1D96F2f6BeF1202E4Ce1Ff6Dad0c2CB002861d3e], Snow: [0x2e234DAe75C793f67A35089C9d99245E1C58470b], 1000000000000000000000000000000000000 [1e36])
│ │ └─ ← [Revert] ERC20InsufficientBalance(0x1D96F2f6BeF1202E4Ce1Ff6Dad0c2CB002861d3e, 1000000000000000000 [1e18], 1000000000000000000000000000000000000 [1e36])
│ └─ ← [Revert] ERC20InsufficientBalance(0x1D96F2f6BeF1202E4Ce1Ff6Dad0c2CB002861d3e, 1000000000000000000 [1e18], 1000000000000000000000000000000000000 [1e36])
└─ ← [Revert] ERC20InsufficientBalance(0x1D96F2f6BeF1202E4Ce1Ff6Dad0c2CB002861d3e, 1000000000000000000 [1e18], 1000000000000000000000000000000000000 [1e36])
Suite result: FAILED. 0 passed; 1 failed; 0 skipped; finished in 21.45ms (4.91ms CPU time)*/
}

3.Due to incorrect calculations ,the if statement of ETH payment will never gets exceuted.

4.This will result making LHS(msg.value) ==1e18 ,But due to wrong calculations
RHS will be 1e36 due to which this if (msg.value == (s_buyFee * amount)) condition
will not get satisfied ,resulting into weth condition execution

POC with ETH-Payment:
function test_buysnowExploitwithETH() public {
vm.deal(bob, 10 ether);
vm.startPrank(bob);
snow.buySnow{value: 1e18}(1e18);
vm.stopPrank();
}

Recommended Mitigation

Use Correct precision calculations:

function buySnow(uint256 amount) external payable canFarmSnow {
require(amount > 0, "Amount must be greater than zero");
// Scale amount for ETH and WETH consistency
uint256 scaledAmount = amount / 1e18;
uint256 totalCost = s_buyFee * scaledAmount;
if (msg.value > 0) {
// ETH payment path
require(msg.value == totalCost, "Incorrect ETH sent");
} else {
// WETH payment path
i_weth.safeTransferFrom(msg.sender, address(this), totalCost);
}
_mint(msg.sender, scaledAmount); // Mint the Snow tokens
s_earnTimer = block.timestamp;
emit SnowBought(msg.sender, scaledAmount);
Updates

Lead Judging Commences

yeahchibyke Lead Judge about 23 hours ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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