Snowman Merkle Airdrop

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

`buySnow` precision mismatch — fee calculated for whole tokens but mint executed in wei (10^18 discrepancy)

Description

  • Normal: buySnow(amount) should give amount whole tokens for the correct fee.

  • Bug: s_buyFee = _buyFee * 10**18 (fee per whole token), but _mint(msg.sender, amount) uses amount as wei. With _buyFee = 5:

    • Expected: pay 5 ETH, get 1 whole Snow (10^18 wei)

    • Actual: pay 5 ETH, get 1 wei (10^-18 Snow)

    • User overpays by 10^18x

s_buyFee = _buyFee * PRECISION; //@> 5 * 10^18 = 5e18 (per whole token)
// ...
if (msg.value == (s_buyFee * amount)) { //@> 5e18 * 1 = 5 ETH
_mint(msg.sender, amount); //@> mints 1 wei — not 1 whole token!
}

Risk

  • Likelihood: Certain — deterministic mismatch

  • Impact: HIGH — Users pay for whole tokens, receive wei-level amounts

Proof of Concept

function testH03_BuySnowPrecisionMismatch() public {
assertEq(snow.s_buyFee(), 5 * 10 ** 18);
uint256 costForOneWei = snow.s_buyFee() * 1;
assertEq(costForOneWei, 5e18); // 5 ETH for 1 wei!
weth.mint(bob, 5e18);
vm.startPrank(bob);
weth.approve(address(snow), 5e18);
snow.buySnow(1);
vm.stopPrank();
assertEq(snow.balanceOf(bob), 1); // 1 wei
assertEq(weth.balanceOf(address(snow)), 5e18); // 5e18 paid
}

Recommended Mitigation

- _mint(msg.sender, amount);
+ _mint(msg.sender, amount * 10**18);
Updates

Lead Judging Commences

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