EthereumEthereum
0x12...6dd4
Voken TeraByte

Voken TeraByte

VokenTB

代币
市值
$1.00
 
价格
2%
此合同的源代码已经过验证!
合同元数据
编译器
0.7.5+commit.eb77ed08
语言
Solidity
合同源代码
文件 1 的 10:LibAuthPause.sol
// SPDX-License-Identifier: MIT
pragma solidity =0.7.5;

import "LibBaseAuth.sol";


/**
 * @dev Auth pause.
 */
contract AuthPause is BaseAuth {
    using Roles for Roles.Role;

    bool private _paused = false;

    event PausedON();
    event PausedOFF();


    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     */
    modifier onlyNotPaused() {
        require(!_paused, "Paused");
        _;
    }

    /**
     * @return Returns true if the contract is paused, false otherwise.
     */
    function isPaused()
        public
        view
        returns (bool)
    {
        return _paused;
    }

    /**
     * @dev Sets paused state.
     *
     * Can only be called by the current owner.
     */
    function setPaused(bool value)
        external
        onlyAgent
    {
        _paused = value;

        if (_paused) {
            emit PausedON();
        } else {
            emit PausedOFF();
        }
    }
}
合同源代码
文件 2 的 10:LibAuthProxy.sol
// SPDX-License-Identifier: MIT
pragma solidity =0.7.5;

import "LibBaseAuth.sol";


/**
 * @dev Auth proxy.
 */
contract AuthProxy is BaseAuth {
    using Roles for Roles.Role;

    Roles.Role private _proxies;
    
    event ProxyAdded(address indexed account);
    event ProxyRemoved(address indexed account);


    /**
     * @dev Throws if called by account which is not a proxy.
     */
    modifier onlyProxy() {
        require(isProxy(msg.sender), "ProxyRole: caller does not have the Proxy role");
        _;
    }

    /**
     * @dev Returns true if the `account` has the Proxy role.
     */
    function isProxy(address account)
        public
        view
        returns (bool)
    {
        return _proxies.has(account);
    }

    /**
     * @dev Give an `account` access to the Proxy role.
     *
     * Can only be called by the current owner.
     */
    function addProxy(address account)
        public
        onlyAgent
    {
        _proxies.add(account);
        emit ProxyAdded(account);
    }

    /**
     * @dev Remove an `account` access from the Proxy role.
     *
     * Can only be called by the current owner.
     */
    function removeProxy(address account)
        public
        onlyAgent
    {
        _proxies.remove(account);
        emit ProxyRemoved(account);
    }
}
合同源代码
文件 3 的 10:LibAuthVoken.sol
// SPDX-License-Identifier: MIT
pragma solidity =0.7.5;

import "LibBaseAuth.sol";
import "LibAuthPause.sol";
import "LibAuthProxy.sol";


contract AuthVoken is BaseAuth, AuthPause, AuthProxy {
    using Roles for Roles.Role;

    Roles.Role private _banks;
    Roles.Role private _minters;

    event BankAdded(address indexed account);
    event BankRemoved(address indexed account);
    event MinterAdded(address indexed account);
    event MinterRemoved(address indexed account);


    /**
     * @dev Throws if called by account which is not a minter.
     */
    modifier onlyMinter()
    {
        require(isMinter(msg.sender), "MinterRole: caller does not have the Minter role");
        _;
    }

    /**
     * @dev Returns true if the `account` has the Bank role.
     */
    function isBank(address account)
        public
        view
        returns (bool)
    {
        return _banks.has(account);
    }

    /**
     * @dev Give an `account` access to the Bank role.
     *
     * Can only be called by the current owner.
     */
    function addBank(address account)
        public
        onlyAgent
    {
        _banks.add(account);
        emit BankAdded(account);
    }

    /**
     * @dev Remove an `account` access from the Bank role.
     *
     * Can only be called by the current owner.
     */
    function removeBank(address account)
        public
        onlyAgent
    {
        _banks.remove(account);
        emit BankRemoved(account);
    }

    /**
     * @dev Returns true if the `account` has the Minter role
     */
    function isMinter(address account)
        public
        view
        returns (bool)
    {
        return _minters.has(account);
    }

    /**
     * @dev Give an `account` access to the Minter role.
     *
     * Can only be called by the current owner.
     */
    function addMinter(address account)
        public
        onlyAgent
    {
        _minters.add(account);
        emit MinterAdded(account);
    }

    /**
     * @dev Remove an `account` access from the Minter role.
     *
     * Can only be called by the current owner.
     */
    function removeMinter(address account)
        public
        onlyAgent
    {
        _minters.remove(account);
        emit MinterRemoved(account);
    }
}
合同源代码
文件 4 的 10: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);
    }
}

合同源代码
文件 5 的 10:LibBurning.sol
// SPDX-License-Identifier: MIT
pragma solidity =0.7.5;


import "LibSafeMath.sol";
import "LibBaseAuth.sol";


/**
 * @dev Burning.
 */
contract Burning is BaseAuth {
    using SafeMath for uint256;

    uint16 private _burningPermilleMin;
    uint16 private _burningPermilleMax;
    uint16 private _burningPermilleMod;

    constructor () {
        _burningPermilleMin = 10;
        _burningPermilleMax = 30;
        _burningPermilleMod = 21;
    }

    /**
     * @dev Sets the burning border from `min` and `max`.
     */
    function setBurningBorder(
        uint16 min,
        uint16 max
    )
        external
        onlyAgent
    {
        require(min <= 1000, "Set burning border: min exceeds 100.0%");
        require(max <= 1000, "Set burning border: max exceeds 100.0%");
        require(min <= max, 'Set burning border: min exceeds max');

        _burningPermilleMin = min;
        _burningPermilleMax = max;
        _burningPermilleMod = _burningPermilleMax - _burningPermilleMin + 1;
    }

    /**
     * @dev Returns the min/max value of burning permille.
     */
    function burningPermilleBorder()
        public
        view
        returns (uint16 min, uint16 max)
    {
        min = _burningPermilleMin;
        max = _burningPermilleMax;
    }

    /**
     * @dev Returns {value} of burning permille.
     */
    function burningPermille()
        public
        view
        returns (uint16)
    {
        if (_burningPermilleMax == 0)
            return 0;

        if (_burningPermilleMin == _burningPermilleMax)
            return _burningPermilleMin;

        return uint16(uint256(keccak256(abi.encode(blockhash(block.number - 1)))).mod(_burningPermilleMod).add(_burningPermilleMin));
    }
}
合同源代码
文件 6 的 10: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);
}
合同源代码
文件 7 的 10:LibIVesting.sol
// SPDX-License-Identifier: MIT
pragma solidity =0.7.5;


/**
 * @dev Interface of an vesting contract.
 */
interface IVesting {
    function vestingOf(address account) external view returns (uint256);
}
合同源代码
文件 8 的 10: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];
    }
}
合同源代码
文件 9 的 10:LibSafeMath.sol
// SPDX-License-Identifier: MIT
pragma solidity =0.7.5;


/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
    /**
     * @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)
    {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    /**
     * @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 sub(a, b, "SafeMath: subtraction overflow");
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(
        uint256 a,
        uint256 b,
        string memory errorMessage
    )
        internal
        pure
        returns (uint256)
    {
        require(b <= a, errorMessage);
        uint256 c = a - b;

        return c;
    }

    /**
     * @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)
    {
        // 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 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts 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
    )
        internal
        pure
        returns (uint256)
    {
        return div(a, b, "SafeMath: division by zero");
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts 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)
    {
        require(b > 0, errorMessage);
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts 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 mod(a, b, "SafeMath: modulo by zero");
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts with custom message 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,
        string memory errorMessage
    )
        internal
        pure
        returns (uint256)
    {
        require(b != 0, errorMessage);
        return a % b;
    }
}
合同源代码
文件 10 的 10:VokenTB.sol
// SPDX-License-Identifier: MIT
pragma solidity =0.7.5;

// Voken TeraByte Main Contract for vnCHAIN (vision.network)
//
// More info:
//   https://voken.io
//
// Contact us:
//   support@voken.io


import "LibSafeMath.sol";
import "LibIERC20.sol";
import "LibIVesting.sol";
import "LibAuthVoken.sol";
import "LibBurning.sol";


/**
 * @title VokenTB Main Contract for vnCHAIN
 */
contract VokenTB is IERC20, IVesting, AuthVoken, Burning {
    using SafeMath for uint256;

    struct Account {
        uint256 balance;

        uint160 voken;
        address payable referrer;

        IVesting[] vestingContracts;
        mapping (address => bool) hasVesting;

        mapping (address => uint256) allowances;
    }

    string private _name = "Voken TeraByte";
    string private _symbol = "VokenTB";
    uint8 private constant _decimals = 9;
    uint256 private constant _cap = 210_000_000e9;
    uint256 private _totalSupply;
    uint256 private _vokenCounter;
    bool private _changeVokenAddressAllowed;

    mapping (address => Account) private _accounts;
    mapping (uint160 => address payable) private _voken2address;

    event Mint(address indexed account, uint256 amount);
    event Burn(address indexed account, uint256 amount);
    event Donate(address indexed account, uint256 amount);
    event VokenAddressSet(address indexed account, uint160 voken);
    event ReferrerSet(address indexed account, address indexed referrerAccount);


    /**
     * @dev Donate
     */
    receive()
        external
        payable
    {
        if (msg.value > 0) {
            emit Donate(msg.sender, msg.value);
        }
    }

    /**
     * @dev Sets the full name of VOKEN.
     *
     * Can only be called by the current owner.
     */
    function setName(
        string calldata value
    )
        external
        onlyAgent
    {
        _name = value;
    }

    /**
     * @dev Sets the symbol of VOKEN.
     *
     * Can only be called by the current owner.
     */
    function setSymbol(
        string calldata value
    )
        external
        onlyAgent
    {
        _symbol = value;
    }

    /**
     * @dev Set change Voken address is allowed or not.
     */
    function setChangeVokenAddressAllowed(bool value)
        external
        onlyAgent
    {
        _changeVokenAddressAllowed = value;
    }

    /**
     * @dev Set Voken address by `voken`.
     */
    function setVokenAddress(uint160 voken)
        external
        returns (bool)
    {
        require(balanceOf(msg.sender) > 0, "Set Voken Address: balance is zero");
        require(voken > 0, "Set Voken Address: is zero address");

        if (_accounts[msg.sender].voken > 0) {
            require(_changeVokenAddressAllowed, "Change Voken Address: is not allowed");
            delete _voken2address[voken];
        }

        else {
            _vokenCounter = _vokenCounter.add(1);
        }

        _voken2address[voken] = msg.sender;
        _accounts[msg.sender].voken = voken;

        emit VokenAddressSet(msg.sender, voken);
        return true;
    }

    /**
     * @dev Set referrer.
     */
    function setReferrer(
        uint160 referrerVoken
    )
        external
        returns (bool)
    {
        address payable referrer_ = _voken2address[referrerVoken];

        require(referrer_ != address(0), "Set referrer: does not exist");
        require(_accounts[msg.sender].referrer == address(0), "Set referrer: was already exist");

        _accounts[msg.sender].referrer = referrer_;
        emit ReferrerSet(msg.sender, referrer_);
        return true;
    }

    /**
     * @dev Returns the full name of VOKEN.
     */
    function name()
        public
        view
        override
        returns (string memory)
    {
        return _name;
    }

    /**
     * @dev Returns the symbol of VOKEN.
     */
    function symbol()
        public
        view
        override
        returns (string memory)
    {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals used to get its user representation.
     */
    function decimals()
        public
        pure
        override
        returns (uint8)
    {
        return _decimals;
    }

    /**
     * @dev Returns the cap on VOKEN's total supply.
     */
    function cap()
        public
        pure
        returns (uint256)
    {
        return _cap;
    }

    /**
     * @dev Returns the amount of VOKEN in existence.
     */
    function totalSupply()
        public
        view
        override
        returns (uint256)
    {
        return _totalSupply;
    }

    /**
     * @dev Returns the amount of VOKEN owned by `account`.
     */
    function balanceOf(
        address account
    )
        public
        view
        override
        returns (uint256)
    {
        return _accounts[account].balance;
    }

    /**
     * @dev Returns the vesting contracts' addresses on `account`.
     */
    function vestingContracts(
        address account
    )
        public
        view
        returns (IVesting[] memory contracts)
    {
        contracts = _accounts[account].vestingContracts;
    }

    /**
     * @dev Returns `true` if change Voken address is allowed.
     */
    function isChangeVokenAddressAllowed()
        public
        view
        returns (bool)
    {
        return _changeVokenAddressAllowed;
    }

    /**
     * @dev Returns Voken address of `account`.
     */
    function address2voken(
        address account
    )
        public
        view
        returns (uint160)
    {
        return _accounts[account].voken;
    }

    /**
     * @dev Returns address of `voken`.
     */
    function voken2address(
        uint160 voken
    )
        public
        view
        returns (address payable)
    {
        return _voken2address[voken];
    }

    /**
     * @dev Returns amount of Voken address.
     */
    function vokenCounter()
        public
        view
        returns (uint256)
    {
        return _vokenCounter;
    }

    /**
     * @dev Returns the referrer of an `account`.
     */
    function referrer(
        address account
    )
        public
        view
        returns (address payable)
    {
        return _accounts[account].referrer;
    }

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 value)
        public
        override
        onlyNotPaused
        returns (bool)
    {
        _approve(msg.sender, spender, value);
        return true;
    }

    /**
     * @dev Returns the remaining number of VOKEN that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}.
     * This is zero by default.
     */
    function allowance(
        address owner,
        address spender
    )
        public
        override
        view
        returns (uint256)
    {
        return _accounts[owner].allowances[spender];
    }

    /**
     * @dev Returns the vesting amount of VOKEN by `account`.
     */
    function vestingOf(
        address account
    )
        public
        override
        view
        returns (uint256 reserved)
    {
        for (uint256 i = 0; i < _accounts[account].vestingContracts.length; i++) {
            if (
                _accounts[account].vestingContracts[i] != IVesting(0)
                &&
                isContract(address(_accounts[account].vestingContracts[i]))
            ) {
                try _accounts[account].vestingContracts[i].vestingOf(account) returns (uint256 value) {
                    reserved = reserved.add(value);
                }
    
                catch {
                    //
                }
            }
        }
    }

    /**
     * @dev Returns the available amount of VOKEN by `account` and a certain `amount`.
     */
    function availableOf(
        address account
    )
        public
        view
        returns (uint256)
    {
        return balanceOf(account).sub(vestingOf(account));
    }

    /**
     * @dev Destroys `amount` VOKEN from the caller.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     */
    function burn(
        uint256 amount
    )
        public
        returns (bool)
    {
        require(amount > 0, "Burn: amount is zero");

        uint256 balance = balanceOf(msg.sender);
        require(balance > 0, "Burn: balance is zero");

        if (balance >= amount) {
            _burn(msg.sender, amount);
        }
        
        else {
            _burn(msg.sender, balance);
        }

        return true;
    }

    /**
     * @dev Creates `amount` VOKEN and assigns them to `account`.
     *
     * Can only be called by a minter.
     */
    function mint(
        address account,
        uint256 amount
    )
        public
        onlyNotPaused
        onlyMinter
        returns (bool)
    {
        require(amount > 0, "Mint: amount is zero");

        _mint(account, amount);
        return true;
    }

    /**
     * @dev Creates `amount` VOKEN and assigns them to `account` with an `vestingContract`
     *
     * Can only be called by a minter.
     */
    function mintWithVesting(
        address account,
        uint256 amount,
        address vestingContract
    )
        public
        onlyNotPaused
        onlyMinter
        returns (bool)
    {
        require(amount > 0, "Mint: amount is zero");
        require(vestingContract != address(this), "Mint, vesting address is the token address");

        _mintWithVesting(account, amount, vestingContract);
        return true;
    }

    /**
     * @dev Moves `amount` VOKEN from the caller's account to `recipient`.
     *
     * Auto handle {WhitelistSignUp} when `amount` is a specific value.
     * Auto handle {Burn} when `recipient` is `address(0)`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(
        address recipient,
        uint256 amount
    )
        public
        override
        onlyNotPaused
        returns (bool)
    {
        require(amount > 0, "Transfer: amount is zero");

        // Burn
        if (recipient == address(0)) {
            uint256 balance = balanceOf(msg.sender);
            require(balance > 0, "Transfer: balance is zero");

            if (amount <= balance) {
                _burn(msg.sender, amount);
            }

            else {
                _burn(msg.sender, balance);
            }
        }

        // Transfer
        else {
            uint256 available = availableOf(msg.sender);
            require(available > 0, "Transfer: available balance is zero");
            require(amount <= available, "Transfer: insufficient available balance");
            
            _transfer(msg.sender, recipient, amount);
        }

        return true;
    }

    /**
     * @dev Moves `amount` VOKEN from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Auto handle {Burn} when `recipient` is `address(0)`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     * Emits an {Approval} event indicating the updated allowance.
     */
    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    )
        public
        override
        onlyNotPaused
        returns (bool)
    {
        require(amount > 0, "TransferFrom: amount is zero");

        // Burn
        if (recipient == address(0)) {
            uint256 balance = balanceOf(sender);
            require(balance > 0, "Transfer: balance is zero");

            if (amount <= balance) {
                _burn(sender, amount);
            }

            else {
                _burn(sender, balance);
            }
        }

        // Normal transfer
        else {
            uint256 available = availableOf(sender);
            require(available > 0, "TransferFrom: available balance is zero");
            require(amount <= available, "TransferFrom: insufficient available balance");
            
            _transfer(sender, recipient, amount);
            _approve(sender, msg.sender, _accounts[sender].allowances[msg.sender].sub(amount, "TransferFrom: amount exceeds allowance"));
        }

        return true;
    }

    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner`s VOKEN.
     *
     * Emits an {Approval} event.
     */
    function _approve(
        address owner,
        address spender,
        uint256 value
    )
        private
    {
        require(owner != address(0), "Approve: from the zero address");
        require(spender != address(0), "Approve: to the zero address");

        _accounts[owner].allowances[spender] = value;
        emit Approval(owner, spender, value);
    }

    /**
     * @dev Destroys `amount` VOKEN from `account`, reducing the total supply.
     *
     * Emits a {Burn} event.
     * Emits a {Transfer} event with `to` set to the zero address.
     */
    function _burn(
        address account,
        uint256 amount
    )
        private
    {
        _accounts[account].balance = _accounts[account].balance.sub(amount, "Burn: insufficient balance");
        _totalSupply = _totalSupply.sub(amount, "Burn: amount exceeds total supply");
        emit Burn(account, amount);
        emit Transfer(account, address(0), amount);
    }

    /**
     * @dev Creates `amount` VOKEN and assigns them to `account`, increasing the total supply.
     *
     * Emits a {Mint} event.
     * Emits a {Transfer} event with `from` set to the zero address.
     */
    function _mint(
        address account,
        uint256 amount
    )
        private
    {
        uint256 total = _totalSupply.add(amount);

        require(total <= _cap, "Mint: total supply cap exceeded");
        require(account != address(0), "Mint: to the zero address");

        _totalSupply = total;
        _accounts[account].balance = _accounts[account].balance.add(amount);
        emit Mint(account, amount);
        emit Transfer(address(0), account, amount);
    }

    /**
     * @dev Creates `amount` VOKEN and assigns them to `account` with an `vestingContract`, increasing the total supply.
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     */
    function _mintWithVesting(
        address account,
        uint256 amount,
        address vestingContract
    )
        private
    {
        uint256 total = _totalSupply.add(amount);

        require(total <= _cap, "Mint: total supply cap exceeded");
        require(account != address(0), "Mint: to the zero address");

        _totalSupply = total;
        _accounts[account].balance = _accounts[account].balance.add(amount);

        if (!_accounts[account].hasVesting[vestingContract]) {
            _accounts[account].vestingContracts.push(IVesting(vestingContract));
            _accounts[account].hasVesting[vestingContract] = true;
        }

        emit Mint(account, amount);
        emit Transfer(address(0), account, amount);
    }

    /**
     * @dev Moves `amount` VOKEN from `sender` to `recipient`.
     *
     * Emits a {Transfer} event.
     */
    function _transfer(
        address sender,
        address recipient,
        uint256 amount
    )
        private
    {
        if (!isBank(sender) && !isBank(recipient)) {
            uint16 permille = burningPermille();

            if (permille > 0) {
                uint256 amountBurn = amount.mul(permille).div(1_000);
                uint256 amountTransfer = amount.sub(amountBurn);
    
                _accounts[sender].balance = _accounts[sender].balance.sub(amountTransfer, "Transfer: insufficient balance");
                _accounts[recipient].balance = _accounts[recipient].balance.add(amountTransfer);
                emit Transfer(sender, recipient, amountTransfer);
    
                _burn(sender, amountBurn);
                
                return;
            }
        }

        _accounts[sender].balance = _accounts[sender].balance.sub(amount, "Transfer: insufficient balance");
        _accounts[recipient].balance = _accounts[recipient].balance.add(amount);
        emit Transfer(sender, recipient, amount);
    }

    /**
     * @dev Returns true if the `account` is a contract.
     */
    function isContract(address account)
        private
        view
        returns (bool)
    {
        uint256 size;
        assembly { size := extcodesize(account) }
        return size > 0;
    }
}
设置
{
  "compilationTarget": {
    "VokenTB.sol": "VokenTB"
  },
  "evmVersion": "istanbul",
  "libraries": {},
  "metadata": {
    "bytecodeHash": "ipfs"
  },
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "remappings": []
}
ABI
[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"AgentAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"AgentRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"BankAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"BankRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Burn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Donate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"MinterAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"MinterRemoved","type":"event"},{"anonymous":false,"inputs":[],"name":"PausedOFF","type":"event"},{"anonymous":false,"inputs":[],"name":"PausedON","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"ProxyAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"ProxyRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"referrerAccount","type":"address"}],"name":"ReferrerSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint160","name":"voken","type":"uint160"}],"name":"VokenAddressSet","type":"event"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"addAgent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"addBank","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"addMinter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"addProxy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"address2voken","outputs":[{"internalType":"uint160","name":"","type":"uint160"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"availableOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"burningPermille","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"burningPermilleBorder","outputs":[{"internalType":"uint16","name":"min","type":"uint16"},{"internalType":"uint16","name":"max","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isAgent","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isBank","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isChangeVokenAddressAllowed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isMinter","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isProxy","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"vestingContract","type":"address"}],"name":"mintWithVesting","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"referrer","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"removeAgent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"removeBank","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"removeMinter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"removeProxy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddr","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"rescueToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"min","type":"uint16"},{"internalType":"uint16","name":"max","type":"uint16"}],"name":"setBurningBorder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"value","type":"bool"}],"name":"setChangeVokenAddressAllowed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"value","type":"string"}],"name":"setName","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"value","type":"bool"}],"name":"setPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint160","name":"referrerVoken","type":"uint160"}],"name":"setReferrer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"value","type":"string"}],"name":"setSymbol","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint160","name":"voken","type":"uint160"}],"name":"setVokenAddress","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"vestingContracts","outputs":[{"internalType":"contract IVesting[]","name":"contracts","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"vestingOf","outputs":[{"internalType":"uint256","name":"reserved","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint160","name":"voken","type":"uint160"}],"name":"voken2address","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vokenCounter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address payable","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawEther","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]