contract Airdrop is Ownable {
    using ECDSA for bytes32;
    using SafeERC20 for IERC20;

    // Events

    event EmergencyWithdraw(
        IERC20 token,
        uint256 amount
    );

    event ClaimAirdrop(
        IERC20 token,
        uint256 amount
    );

    // Storage

    /// @dev Store the users who already claim your rewards
    mapping(address => bool) public claimedAddress;

    function claimAirdrop(
        IERC20 _token,
        uint256 _amount,
        bytes calldata _signature
    ) external {
        address sender = msg.sender;

        require(!claimedAddress[sender], "Airdrop::claimAirdrop: The sender has already claimed the tokens");

        claimedAddress[sender] = true;

        bytes32 signatureMsg = keccak256(
            abi.encodePacked(
                address(this),
                sender,
                _token,
                _amount
            )
        );

        _token.safeTransfer(sender, _amount);

        require(
            owner() == signatureMsg.toEthSignedMessageHash().recover(_signature),
            "Airdrop::claimAirdrop: Invalid owner signature"
        );

        emit ClaimAirdrop(_token, _amount);
    }

    // OnlyOwner functions

    /**
     * @dev Use to withdraw ERC20 tokens or ETH in emergency cases
     *
     * @param _token The ERC20 token, if is address 0, ETH currency
     * @param _amount The amount of ERC20 token or ETH
     *
     * Requirements:
     *
     * - Only the owner can send this function
     */
    function emergencyWithdraw(IERC20 _token, uint256 _amount) external onlyOwner {
        address sender = msg.sender;

        if (address(_token) != address(0))
            _token.safeTransfer(sender, _amount);
        else
            payable(sender).transfer(_amount);

        emit EmergencyWithdraw(_token, _amount);
    }
}
/**
 * @author Victor Fage <victorfage@gmail.com>
 *
 * @notice Contract which provides a basic one ERC20 token airdrop, where an address can claim an amount
 * of reward ERC20 tokens, with the signature of the owner
 * Also the owner of the contract can remove the tokens
 * Before who the claimer send the claim the contract must was funded with reward ERC20 token
 */
function emergencyWithdraw(IERC20 _token, uint256 _amount) external onlyOwner {
    address sender = msg.sender;

    if (address(_token) != address(0))
        _token.safeTransfer(sender, _amount);
    else
        payable(sender).transfer(_amount);

    emit EmergencyWithdraw(_token, _amount);
}

/**
 * @dev Use to withdraw ERC20 tokens or ETH in emergency cases
 *
 * @param _token The ERC20 token, if is address 0, ETH currency
 * @param _amount The amount of ERC20 token or ETH
 *
 * Requirements:
 *
 * - Only the owner can send this function
 */