pragma solidity ^0.8.24;
import {Test} from "forge-std/Test.sol";
import {Snow} from "../src/Snow.sol";
import {DeploySnow} from "../script/DeploySnow.s.sol";
import {MockWETH} from "../src/mock/MockWETH.sol";
* PoC: buySnow does not refund msg.value when msg.value != s_buyFee * amount
*
* If the user sends ETH that doesn't exactly match the fee, the function:
* 1. Pulls WETH from the user via safeTransferFrom (the else branch)
* 2. Never returns the ETH sent as msg.value
* 3. The ETH is permanently stuck in the contract (only the collector can sweep it)
*/
contract PoC_BuySnowEthLoss is Test {
Snow snow;
DeploySnow deployer;
MockWETH weth;
address collector;
uint256 FEE;
address victim;
function setUp() public {
deployer = new DeploySnow();
snow = deployer.run();
weth = deployer.weth();
collector = deployer.collector();
FEE = deployer.FEE();
victim = makeAddr("victim");
weth.mint(victim, FEE);
deal(victim, FEE);
}
function test_PoC_EthNotRefundedWhenMsgValueMismatch() public {
uint256 userEthBefore = victim.balance;
uint256 userWethBefore = weth.balanceOf(victim);
uint256 contractEthBefore = address(snow).balance;
uint256 contractWethBefore = weth.balanceOf(address(snow));
vm.startPrank(victim);
weth.approve(address(snow), FEE);
snow.buySnow{value: FEE - 1}(1);
vm.stopPrank();
assertEq(address(snow).balance, contractEthBefore + (FEE - 1), "ETH should be stuck in contract");
assertEq(victim.balance, userEthBefore - (FEE - 1), "Victim lost their ETH");
assertEq(weth.balanceOf(victim), userWethBefore - FEE, "Victim also paid WETH");
assertEq(weth.balanceOf(address(snow)), contractWethBefore + FEE, "Contract has the WETH too");
assertEq(snow.balanceOf(victim), 1, "Victim got snow tokens");
}
function test_PoC_ExactCheckSucceeds_NoLoss() public {
uint256 userEthBefore = victim.balance;
vm.prank(victim);
snow.buySnow{value: FEE}(1);
assertEq(victim.balance, userEthBefore - FEE, "ETH spent correctly");
assertEq(address(snow).balance, FEE, "Contract holds the ETH");
assertEq(snow.balanceOf(victim), 1, "Victim got snow");
}
}