pragma solidity 0.8.24;
import {Test, console} from "forge-std/Test.sol";
import {Snow} from "../src/Snow.sol";
import {Snowman} from "../src/Snowman.sol";
import {SnowmanAirdrop} from "../src/SnowmanAirdrop.sol";
import {DeploySnow} from "../script/DeploySnow.s.sol";
import {MockWETH} from "../src/mock/MockWETH.sol";
contract AllVulnerabilitiesPoC is Test {
Snow snow;
DeploySnow deployer;
MockWETH weth;
address collector;
uint256 FEE;
Snowman snowman;
SnowmanAirdrop airdrop;
bytes32 merkleRoot = bytes32(0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef);
address alice;
address bob;
address charlie;
address attacker;
function setUp() public {
deployer = new DeploySnow();
snow = deployer.run();
weth = deployer.weth();
collector = deployer.collector();
FEE = deployer.FEE();
snowman = new Snowman("ipfs://snowman");
airdrop = new SnowmanAirdrop(merkleRoot, address(snow), address(snowman));
alice = makeAddr("alice");
bob = makeAddr("bob");
charlie = makeAddr("charlie");
attacker = makeAddr("attacker");
deal(alice, 100 ether);
deal(bob, 100 ether);
deal(charlie, 100 ether);
deal(attacker, 100 ether);
weth.mint(alice, 100 * FEE);
weth.mint(bob, 100 * FEE);
weth.mint(charlie, 100 * FEE);
weth.mint(attacker, 100 * FEE);
}
function test_Snow_DualPaymentTrap_UserLosesFunds() public {
uint256 aliceInitialEth = alice.balance;
uint256 aliceInitialWeth = weth.balanceOf(alice);
vm.prank(alice);
weth.approve(address(snow), FEE);
vm.prank(alice);
snow.buySnow{value: FEE + 1}(1);
assertEq(aliceInitialEth - alice.balance, FEE + 1);
assertEq(aliceInitialWeth - weth.balanceOf(alice), FEE);
assertEq(address(snow).balance, FEE + 1);
assertEq(weth.balanceOf(address(snow)), FEE);
assertTrue((FEE + 1 + FEE) > FEE * 15 / 10);
}
function test_Snow_DualPaymentTrap_TooLittleETH() public {
vm.startPrank(bob);
weth.approve(address(snow), FEE);
uint256 bobInitialEth = bob.balance;
uint256 bobInitialWeth = weth.balanceOf(bob);
snow.buySnow{value: 1 ether}(1);
assertEq(bob.balance, bobInitialEth - 1 ether);
assertEq(weth.balanceOf(bob), bobInitialWeth - FEE);
assertEq(address(snow).balance, 1 ether);
vm.stopPrank();
}
}
- 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);
- }
+ function buySnow(uint256 amount) external payable {
+ uint256 totalFee = FEE * amount;
+
+ if (msg.value > 0) {
+ if (msg.value < totalFee) revert InsufficientETH();
+ if (msg.value > totalFee) {
+ // Refund excess
+ (bool success, ) = msg.sender.call{value: msg.value - totalFee}("");
+ require(success, "Refund failed");
+ }
+ } else {
+ SafeERC20.safeTransferFrom(weth, msg.sender, address(this), totalFee);
+ }
+ _mint(msg.sender, amount);
+ s_timer = block.timestamp;
+}