Snowman Merkle Airdrop

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

buySnow takes WETH and keeps the user's ETH when msg.value is not exactly the price, so the user pays twice

Root + Impact

buySnow takes WETH from the user when msg.value is not exactly the price, but never refunds or rejects the ETH that was sent, so the user pays twice.

Description

In buySnow, if the user does not send the exact ETH amount, even slightly more or slightly less, the contract charges them in WETH instead.

The ETH that the user already sent is not refunded or rejected. It stays in the contract and is later sent to the collector through collectFee.

As a result, the user pays twice: once in ETH and once in WETH.

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

Likelihood: Low. It requires the user to send a wrong ETH amount and to have approved WETH to the contract.

Impact: Low. The user loses the ETH they sent, but only because of their own mistake.

Proof of Concept

A user sends 1 wei more than the price. The contract takes the full price in WETH and also keeps all the ETH.

function testExtraEthIsKeptWhenPayingWithWeth() public {
address user = makeAddr("user");
uint256 amount = 1;
uint256 price = snow.s_buyFee() * amount;
​
deal(user, price + 1);
deal(address(weth), user, price);
​
vm.startPrank(user);
weth.approve(address(snow), price);
snow.buySnow{value: price + 1}(amount);
vm.stopPrank();
​
assertEq(weth.balanceOf(user), 0); // paid in WETH
assertEq(address(snow).balance, price + 1); // ETH was also kept
}

Recommended Mitigation

Reject any ETH sent when paying with WETH.

} else {
+ if (msg.value != 0) revert S__NotAllowed();
i_weth.safeTransferFrom(msg.sender, address(this), (s_buyFee * amount));
_mint(msg.sender, amount);
}
​
​
Updates

Lead Judging Commences

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