// File: LibBaseAuth.sol



// SPDX-License-Identifier: MIT
pragma solidity =0.7.5;

import "LibRoles.sol";
import "LibIERC20.sol";


/**
 * @dev Base auth.
 */
contract BaseAuth {
    using Roles for Roles.Role;

    Roles.Role private _agents;

    event AgentAdded(address indexed account);
    event AgentRemoved(address indexed account);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor ()
    {
        _agents.add(msg.sender);
        emit AgentAdded(msg.sender);
    }

    /**
     * @dev Throws if called by account which is not an agent.
     */
    modifier onlyAgent() {
        require(isAgent(msg.sender), "AgentRole: caller does not have the Agent role");
        _;
    }

    /**
     * @dev Rescue compatible ERC20 Token
     *
     * Can only be called by an agent.
     */
    function rescueToken(
        address tokenAddr,
        address recipient,
        uint256 amount
    )
        external
        onlyAgent
    {
        IERC20 _token = IERC20(tokenAddr);
        require(recipient != address(0), "Rescue: recipient is the zero address");
        uint256 balance = _token.balanceOf(address(this));

        require(balance >= amount, "Rescue: amount exceeds balance");
        _token.transfer(recipient, amount);
    }

    /**
     * @dev Withdraw Ether
     *
     * Can only be called by an agent.
     */
    function withdrawEther(
        address payable recipient,
        uint256 amount
    )
        external
        onlyAgent
    {
        require(recipient != address(0), "Withdraw: recipient is the zero address");
        uint256 balance = address(this).balance;
        require(balance >= amount, "Withdraw: amount exceeds balance");
        recipient.transfer(amount);
    }

    /**
     * @dev Returns true if the `account` has the Agent role.
     */
    function isAgent(address account)
        public
        view
        returns (bool)
    {
        return _agents.has(account);
    }

    /**
     * @dev Give an `account` access to the Agent role.
     *
     * Can only be called by an agent.
     */
    function addAgent(address account)
        public
        onlyAgent
    {
        _agents.add(account);
        emit AgentAdded(account);
    }

    /**
     * @dev Remove an `account` access from the Agent role.
     *
     * Can only be called by an agent.
     */
    function removeAgent(address account)
        public
        onlyAgent
    {
        _agents.remove(account);
        emit AgentRemoved(account);
    }
}


// File: LibIERC20.sol



// SPDX-License-Identifier: MIT
pragma solidity =0.7.5;


/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    function name() external view returns (string memory);
    function symbol() external view returns (string memory);
    function decimals() external view returns (uint8);
    function totalSupply() external view returns (uint256);
    function allowance(address owner, address spender) external view returns (uint256);
    function balanceOf(address account) external view returns (uint256);
    function approve(address spender, uint256 amount) external returns (bool);
    function transfer(address recipient, uint256 amount) external returns (bool);
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);

    event Approval(address indexed owner, address indexed spender, uint256 value);
    event Transfer(address indexed from, address indexed to, uint256 value);
}

// File: LibRoles.sol



// SPDX-License-Identifier: MIT
pragma solidity =0.7.5;


/**
 * @dev Library for managing addresses assigned to a Role.
 */
library Roles {
    struct Role
    {
        mapping (address => bool) bearer;
    }

    /**
     * @dev Give an account access to this role.
     */
    function add(
        Role storage role,
        address account
    )
        internal
    {
        require(!has(role, account), "Roles: account already has role");
        role.bearer[account] = true;
    }

    /**
     * @dev Remove an account's access to this role.
     */
    function remove(
        Role storage role,
        address account
    )
        internal
    {
        require(has(role, account), "Roles: account does not have role");
        role.bearer[account] = false;
    }

    /**
     * @dev Check if an account has this role.
     *
     * @return bool
     */
    function has(
        Role storage role,
        address account
    )
        internal
        view
        returns (bool)
    {
        require(account != address(0), "Roles: account is the zero address");
        return role.bearer[account];
    }
}

// File: VokenMigrate.sol



// SPDX-License-Identifier: MIT
pragma solidity =0.7.5;

import "LibBaseAuth.sol";


contract VokenMigrate is BaseAuth {
    receive() external payable {}
}