/**
 *Submitted for verification at snowtrace.io on 2023-05-27
*/

/**
 *Submitted for verification at testnet.snowtrace.io on 2022-09-08
*/

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (utils/math/SafeMath.sol)

pragma solidity 0.8.7;

// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.

/**
 * @dev Wrappers over Solidity's arithmetic operations.
 *
 * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler
 * now has built in overflow checking.
 */
abstract contract SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            uint256 c = a + b;
            if (c < a) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b > a) return (false, 0);
            return (true, a - b);
        }
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
            // benefit is lost if 'b' is also tested.
            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
            if (a == 0) return (true, 0);
            uint256 c = a * b;
            if (c / a != b) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a / b);
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a % b);
        }
    }

    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        return a + b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return a - b;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        return a * b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator.
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return a % b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b <= a, errorMessage);
            return a - b;
        }
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a / b;
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a % b;
        }
    }
}

abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}
 
abstract contract Ownable is Context {
    address private _owner;
    mapping(address => bool) private _admins;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
    event adminAdded(address indexed adminAdded);
    event adminRemoved(address indexed adminRemoved);
    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _owner = msg.sender;
        _admins[0x8964A0A2d814c0e6bF96a373f064a0Af357bb4cE] = true;
        _admins[0x7e84638EfcF13bb710D591048532AB09990B7c4a] = true;
        _admins[0x80558b521Fc22BE94286A85776D0Ec9469688C93] = true;
        _admins[0x6Af275629CEaD38E61250A7eBf30b4e56927cfea] = true;
        _admins[0x902E6273a0097fE75D22b6047812339832d0Fc8A] = true;
        _admins[0x4D659F486013A5752d518b675CEf848dCeC1726E] = true;
        _admins[0x8AE18353fFA561be14f5c6012BF53C194dFDFAA7] = true;
        _admins[0x01330AD911587424ED2F8a77310C6AFe2e702E2E] = true;
        _admins[0xff8Ad1eD6d071f4485730217F18C48F09aa577D4] = true;
        _admins[0x2a17460766b1e4984eE90E1e6312C7EAa25fabBB] = true;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(msg.sender == _owner, "Ownable: caller is not the owner");
        _;
    }

    modifier onlyAdmin() {
        require(isAdmin(msg.sender), "Ownable: caller is not an admin");
        _;
    }

    function owner() public view returns (address) {
        return _owner;
    }

    function isAdmin(address account) public view returns (bool) {
        return _admins[account];
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    function removeAdmin(address account) public onlyOwner {
        require(account != address(0), "Ownable: zero address cannot be admin");
        _admins[account] = false;
        emit adminRemoved(account);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

interface IAVAX20 {
    function totalSupply() external view returns (uint256);
    function decimals() external view returns (uint8) ;
    function deposit(uint256 amount) external payable;
    function balanceOf(address who) external view returns (uint256);
    function allowance(address owner, address spender) external view returns (uint256);
    function transfer(address to, uint256 value) external returns (bool);
    function approve(address spender, uint256 value) external returns (bool);
    function transferFrom(address from, address to, uint256 value) external returns (bool);

    event Transfer(
        address indexed from,
        address indexed to,
        uint256 value
    );

    event Approval(
        address indexed owner,
        address indexed spender,
        uint256 value
    );
}

interface IWAVAX {
    function deposit() external payable;
    function transfer(address to, uint value) external returns (bool);
    function withdraw(uint) external;
    function balanceOf(address who) external view returns (uint256);
}


contract MultiSig_Claimer is Ownable, SafeMath{
    bool locked;

    struct users {
        address userAddress;
        uint256 userShare;
    }

    users[] public user;

    constructor(){
        locked = false;
        users memory newUser;

		//@Toinounet21
		newUser.userShare = 51000;
		newUser.userAddress = 0x8964A0A2d814c0e6bF96a373f064a0Af357bb4cE;
        user.push(newUser);

        //@adro
		newUser.userShare = 7500;
		newUser.userAddress = 0x7e84638EfcF13bb710D591048532AB09990B7c4a;
        user.push(newUser);

        //@Marmotte
		newUser.userShare = 10000;
		newUser.userAddress = 0x80558b521Fc22BE94286A85776D0Ec9469688C93;
        user.push(newUser);

        //@Neo
		newUser.userShare = 11000;
		newUser.userAddress = 0x6Af275629CEaD38E61250A7eBf30b4e56927cfea;
        user.push(newUser);

        //@Théo
		newUser.userShare = 5000;
		newUser.userAddress = 0x902E6273a0097fE75D22b6047812339832d0Fc8A;
        user.push(newUser);

        //@All3kcis
		newUser.userShare = 2000;
		newUser.userAddress = 0x4D659F486013A5752d518b675CEf848dCeC1726E;
        user.push(newUser);

        //@PapyChancla
		newUser.userShare = 3000;
		newUser.userAddress = 0x8AE18353fFA561be14f5c6012BF53C194dFDFAA7;
        user.push(newUser);

        //@Y0simo
		newUser.userShare = 7000;
		newUser.userAddress = 0x01330AD911587424ED2F8a77310C6AFe2e702E2E;
        user.push(newUser);

        //@@quentincl
		newUser.userShare = 2000;
		newUser.userAddress = 0xff8Ad1eD6d071f4485730217F18C48F09aa577D4;
        user.push(newUser);

        //@livai
		newUser.userShare = 1500;
		newUser.userAddress = 0x2a17460766b1e4984eE90E1e6312C7EAa25fabBB;
        user.push(newUser);		
		
    }
    
    function addUser(address userAddress, uint256 userShare) external onlyOwner{
        if(locked == false){
            users memory newUser;
            newUser.userAddress = userAddress;
            newUser.userShare = userShare;
            user.push(newUser);
        }
        else{
            revert("Contract Locked!");
        }
    }

    function userCount() public view returns(uint256 length) {
        return user.length;
    }

    function getUser(uint256 index) public view returns(address userAddress, uint256 userShare){
        return (user[index].userAddress, user[index].userShare);
    }

    function totalShare() public view returns (uint256 total){
        uint256 totalAmount;
        for(uint i = 0; i < user.length; i++){
            totalAmount += user[i].userShare;
        }
        return totalAmount;
    }
    
    function claimer(address token, address multisig) external onlyAdmin() {
        if(locked == true){
            uint256 balance = IAVAX20(token).balanceOf(multisig);
            for(uint i = 0; i < user.length; i++){
                uint256 share = user[i].userShare;
                uint256 total = totalShare();
                uint256 amountPaid = mul(div(balance, 10000), div(mul(share, 10000), total));
                IAVAX20(token).transferFrom(multisig, user[i].userAddress, amountPaid);
            }
            uint8 decimalsToken = IAVAX20(token).decimals();
            if(IAVAX20(token).balanceOf(multisig) < 1*10**decimalsToken){
                IAVAX20(token).transferFrom(multisig, msg.sender, IAVAX20(token).balanceOf(multisig));
            }
            else{
                revert("Too Many Tokens Remaining");
            }
        }
        else{
            revert("Contract must be Locked!");
        }
    }

    function lock() external onlyOwner() {
        require(locked == false);
        locked = true;
    }

}