ETH Price: $2,549.19 (+1.58%)

Transaction Decoder

Block:
18273778 at Oct-04-2023 01:08:47 AM +UTC
Transaction Fee:
0.001194910884124898 ETH $3.05
Gas Used:
94,357 Gas / 12.663722714 Gwei

Emitted Events:

109 MTON.Transfer( from=[Sender] 0xff1f43422a0240ccbd29c16197853b372a61255d, to=[Receiver] Swapper, value=1500000000000000000 )
110 MTON.Approval( owner=[Sender] 0xff1f43422a0240ccbd29c16197853b372a61255d, spender=[Receiver] Swapper, value=0 )
111 MTON.Transfer( from=[Receiver] Swapper, to=0x0000000000000000000000000000000000000001, value=1500000000000000000 )
112 TON.Transfer( from=TONVault, to=[Receiver] Swapper, value=1500000000000000000 )
113 TON.Approval( owner=TONVault, spender=[Receiver] Swapper, value=17115527699479392589658853 )
114 TON.Transfer( from=[Receiver] Swapper, to=[Sender] 0xff1f43422a0240ccbd29c16197853b372a61255d, value=1500000000000000000 )
115 Swapper.Swapped( account=[Sender] 0xff1f43422a0240ccbd29c16197853b372a61255d, unreleased=1500000000000000000, transferred=1500000000000000000 )

Account State Difference:

  Address   Before After State Difference Code
1.167398869889862783 Eth1.167634762389862783 Eth0.0002358925
0x2be5e8c1...a9b3433C5
0xe3a87a93...45aa34669
0xFF1F4342...72a61255d
0.080148063017693427 Eth
Nonce: 51
0.078953152133568529 Eth
Nonce: 52
0.001194910884124898

Execution Trace

Swapper.swap( vestingToken=0xe3a87a9343D262F5f11280058ae807B45aa34669 ) => ( True )
  • MTON.balanceOf( account=0xFF1F43422A0240CCbD29C16197853b372a61255d ) => ( 1500000000000000000 )
  • MTON.transferFrom( sender=0xFF1F43422A0240CCbD29C16197853b372a61255d, recipient=0x8DB1fdfDa8D1024f8a5B5dCed5eC1918435F2fc8, amount=1500000000000000000 ) => ( True )
  • MTON.transfer( recipient=0x0000000000000000000000000000000000000001, amount=1500000000000000000 ) => ( True )
  • TON.transferFrom( sender=0xf68C26aA86607C64b6a86dC2A987530eFd3ae941, recipient=0x8DB1fdfDa8D1024f8a5B5dCed5eC1918435F2fc8, amount=1500000000000000000 ) => ( True )
  • TON.transfer( recipient=0xFF1F43422A0240CCbD29C16197853b372a61255d, amount=1500000000000000000 ) => ( True )
    File 1 of 4: Swapper
    // File: contracts/openzeppelin-solidity/token/ERC20/IERC20.sol
    
    pragma solidity ^0.5.0;
    
    /**
     * @dev Interface of the ERC20 standard as defined in the EIP. Does not include
     * the optional functions; to access them see `ERC20Detailed`.
     */
    interface IERC20 {
        /**
         * @dev Returns the amount of tokens in existence.
         */
        function totalSupply() external view returns (uint256);
    
        /**
         * @dev Returns the amount of tokens owned by `account`.
         */
        function balanceOf(address account) external view returns (uint256);
    
        /**
         * @dev Moves `amount` tokens from the caller's account to `recipient`.
         *
         * Returns a boolean value indicating whether the operation succeeded.
         *
         * Emits a `Transfer` event.
         */
        function transfer(address recipient, uint256 amount) external returns (bool);
    
        /**
         * @dev Returns the remaining number of tokens that `spender` will be
         * allowed to spend on behalf of `owner` through `transferFrom`. This is
         * zero by default.
         *
         * This value changes when `approve` or `transferFrom` are called.
         */
        function allowance(address owner, address spender) external view returns (uint256);
    
        /**
         * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
         *
         * Returns a boolean value indicating whether the operation succeeded.
         *
         * > Beware that changing an allowance with this method brings the risk
         * that someone may use both the old and the new allowance by unfortunate
         * transaction ordering. One possible solution to mitigate this race
         * condition is to first reduce the spender's allowance to 0 and set the
         * desired value afterwards:
         * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
         *
         * Emits an `Approval` event.
         */
        function approve(address spender, uint256 amount) external returns (bool);
    
        /**
         * @dev Moves `amount` tokens from `sender` to `recipient` using the
         * allowance mechanism. `amount` is then deducted from the caller's
         * allowance.
         *
         * Returns a boolean value indicating whether the operation succeeded.
         *
         * Emits a `Transfer` event.
         */
        function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
    
        /**
         * @dev Emitted when `value` tokens are moved from one account (`from`) to
         * another (`to`).
         *
         * Note that `value` may be zero.
         */
        event Transfer(address indexed from, address indexed to, uint256 value);
    
        /**
         * @dev Emitted when the allowance of a `spender` for an `owner` is set by
         * a call to `approve`. `value` is the new allowance.
         */
        event Approval(address indexed owner, address indexed spender, uint256 value);
    }
    
    // File: contracts/openzeppelin-solidity/math/SafeMath.sol
    
    pragma solidity ^0.5.0;
    
    /**
     * @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) {
            require(b <= a, "SafeMath: subtraction overflow");
            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-solidity/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) {
            // Solidity only automatically asserts when dividing by 0
            require(b > 0, "SafeMath: division by zero");
            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) {
            require(b != 0, "SafeMath: modulo by zero");
            return a % b;
        }
    }
    
    // File: contracts/openzeppelin-solidity/token/ERC20/ERC20.sol
    
    pragma solidity ^0.5.0;
    
    
    
    /**
     * @dev Implementation of the `IERC20` interface.
     *
     * This implementation is agnostic to the way tokens are created. This means
     * that a supply mechanism has to be added in a derived contract using `_mint`.
     * For a generic mechanism see `ERC20Mintable`.
     *
     * *For a detailed writeup see our guide [How to implement supply
     * mechanisms](https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226).*
     *
     * We have followed general OpenZeppelin guidelines: functions revert instead
     * of returning `false` on failure. This behavior is nonetheless conventional
     * and does not conflict with the expectations of ERC20 applications.
     *
     * Additionally, an `Approval` event is emitted on calls to `transferFrom`.
     * This allows applications to reconstruct the allowance for all accounts just
     * by listening to said events. Other implementations of the EIP may not emit
     * these events, as it isn't required by the specification.
     *
     * Finally, the non-standard `decreaseAllowance` and `increaseAllowance`
     * functions have been added to mitigate the well-known issues around setting
     * allowances. See `IERC20.approve`.
     */
    contract ERC20 is IERC20 {
        using SafeMath for uint256;
    
        mapping (address => uint256) private _balances;
    
        mapping (address => mapping (address => uint256)) private _allowances;
    
        uint256 private _totalSupply;
    
        /**
         * @dev See `IERC20.totalSupply`.
         */
        function totalSupply() public view returns (uint256) {
            return _totalSupply;
        }
    
        /**
         * @dev See `IERC20.balanceOf`.
         */
        function balanceOf(address account) public view returns (uint256) {
            return _balances[account];
        }
    
        /**
         * @dev See `IERC20.transfer`.
         *
         * Requirements:
         *
         * - `recipient` cannot be the zero address.
         * - the caller must have a balance of at least `amount`.
         */
        function transfer(address recipient, uint256 amount) public returns (bool) {
            _transfer(msg.sender, recipient, amount);
            return true;
        }
    
        /**
         * @dev See `IERC20.allowance`.
         */
        function allowance(address owner, address spender) public view returns (uint256) {
            return _allowances[owner][spender];
        }
    
        /**
         * @dev See `IERC20.approve`.
         *
         * Requirements:
         *
         * - `spender` cannot be the zero address.
         */
        function approve(address spender, uint256 value) public returns (bool) {
            _approve(msg.sender, spender, value);
            return true;
        }
    
        /**
         * @dev See `IERC20.transferFrom`.
         *
         * Emits an `Approval` event indicating the updated allowance. This is not
         * required by the EIP. See the note at the beginning of `ERC20`;
         *
         * Requirements:
         * - `sender` and `recipient` cannot be the zero address.
         * - `sender` must have a balance of at least `value`.
         * - the caller must have allowance for `sender`'s tokens of at least
         * `amount`.
         */
        function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) {
            _transfer(sender, recipient, amount);
            _approve(sender, msg.sender, _allowances[sender][msg.sender].sub(amount));
            return true;
        }
    
        /**
         * @dev Atomically increases the allowance granted to `spender` by the caller.
         *
         * This is an alternative to `approve` that can be used as a mitigation for
         * problems described in `IERC20.approve`.
         *
         * Emits an `Approval` event indicating the updated allowance.
         *
         * Requirements:
         *
         * - `spender` cannot be the zero address.
         */
        function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
            _approve(msg.sender, spender, _allowances[msg.sender][spender].add(addedValue));
            return true;
        }
    
        /**
         * @dev Atomically decreases the allowance granted to `spender` by the caller.
         *
         * This is an alternative to `approve` that can be used as a mitigation for
         * problems described in `IERC20.approve`.
         *
         * Emits an `Approval` event indicating the updated allowance.
         *
         * Requirements:
         *
         * - `spender` cannot be the zero address.
         * - `spender` must have allowance for the caller of at least
         * `subtractedValue`.
         */
        function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
            _approve(msg.sender, spender, _allowances[msg.sender][spender].sub(subtractedValue));
            return true;
        }
    
        /**
         * @dev Moves tokens `amount` from `sender` to `recipient`.
         *
         * This is internal function is equivalent to `transfer`, and can be used to
         * e.g. implement automatic token fees, slashing mechanisms, etc.
         *
         * Emits a `Transfer` event.
         *
         * Requirements:
         *
         * - `sender` cannot be the zero address.
         * - `recipient` cannot be the zero address.
         * - `sender` must have a balance of at least `amount`.
         */
        function _transfer(address sender, address recipient, uint256 amount) internal {
            require(sender != address(0), "ERC20: transfer from the zero address");
            require(recipient != address(0), "ERC20: transfer to the zero address");
    
            _balances[sender] = _balances[sender].sub(amount);
            _balances[recipient] = _balances[recipient].add(amount);
            emit Transfer(sender, recipient, amount);
        }
    
        /** @dev Creates `amount` tokens and assigns them to `account`, increasing
         * the total supply.
         *
         * Emits a `Transfer` event with `from` set to the zero address.
         *
         * Requirements
         *
         * - `to` cannot be the zero address.
         */
        function _mint(address account, uint256 amount) internal {
            require(account != address(0), "ERC20: mint to the zero address");
    
            _totalSupply = _totalSupply.add(amount);
            _balances[account] = _balances[account].add(amount);
            emit Transfer(address(0), account, amount);
        }
    
         /**
         * @dev Destoys `amount` tokens from `account`, reducing the
         * total supply.
         *
         * Emits a `Transfer` event with `to` set to the zero address.
         *
         * Requirements
         *
         * - `account` cannot be the zero address.
         * - `account` must have at least `amount` tokens.
         */
        function _burn(address account, uint256 value) internal {
            require(account != address(0), "ERC20: burn from the zero address");
    
            _totalSupply = _totalSupply.sub(value);
            _balances[account] = _balances[account].sub(value);
            emit Transfer(account, address(0), value);
        }
    
        /**
         * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens.
         *
         * This is internal function is equivalent to `approve`, and can be used to
         * e.g. set automatic allowances for certain subsystems, etc.
         *
         * Emits an `Approval` event.
         *
         * Requirements:
         *
         * - `owner` cannot be the zero address.
         * - `spender` cannot be the zero address.
         */
        function _approve(address owner, address spender, uint256 value) internal {
            require(owner != address(0), "ERC20: approve from the zero address");
            require(spender != address(0), "ERC20: approve to the zero address");
    
            _allowances[owner][spender] = value;
            emit Approval(owner, spender, value);
        }
    
        /**
         * @dev Destoys `amount` tokens from `account`.`amount` is then deducted
         * from the caller's allowance.
         *
         * See `_burn` and `_approve`.
         */
        function _burnFrom(address account, uint256 amount) internal {
            _burn(account, amount);
            _approve(account, msg.sender, _allowances[account][msg.sender].sub(amount));
        }
    }
    
    // File: contracts/openzeppelin-solidity/access/Roles.sol
    
    pragma solidity ^0.5.0;
    
    /**
     * @title Roles
     * @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: contracts/openzeppelin-solidity/access/roles/MinterRole.sol
    
    pragma solidity ^0.5.0;
    
    
    contract MinterRole {
        using Roles for Roles.Role;
    
        event MinterAdded(address indexed account);
        event MinterRemoved(address indexed account);
    
        Roles.Role private _minters;
    
        constructor () internal {
            _addMinter(msg.sender);
        }
    
        modifier onlyMinter() {
            require(isMinter(msg.sender), "MinterRole: caller does not have the Minter role");
            _;
        }
    
        function isMinter(address account) public view returns (bool) {
            return _minters.has(account);
        }
    
        function addMinter(address account) public onlyMinter {
            _addMinter(account);
        }
    
        function renounceMinter() public {
            _removeMinter(msg.sender);
        }
    
        function _addMinter(address account) internal {
            _minters.add(account);
            emit MinterAdded(account);
        }
    
        function _removeMinter(address account) internal {
            _minters.remove(account);
            emit MinterRemoved(account);
        }
    }
    
    // File: contracts/openzeppelin-solidity/token/ERC20/ERC20Mintable.sol
    
    pragma solidity ^0.5.0;
    
    
    
    /**
     * @dev Extension of `ERC20` that adds a set of accounts with the `MinterRole`,
     * which have permission to mint (create) new tokens as they see fit.
     *
     * At construction, the deployer of the contract is the only minter.
     */
    contract ERC20Mintable is ERC20, MinterRole {
        /**
         * @dev See `ERC20._mint`.
         *
         * Requirements:
         *
         * - the caller must have the `MinterRole`.
         */
        function mint(address account, uint256 amount) public onlyMinter returns (bool) {
            _mint(account, amount);
            return true;
        }
    }
    
    // File: contracts/openzeppelin-solidity/ownership/Secondary.sol
    
    pragma solidity ^0.5.0;
    
    /**
     * @dev A Secondary contract can only be used by its primary account (the one that created it).
     */
    contract Secondary {
        address private _primary;
    
        /**
         * @dev Emitted when the primary contract changes.
         */
        event PrimaryTransferred(
            address recipient
        );
    
        /**
         * @dev Sets the primary account to the one that is creating the Secondary contract.
         */
        constructor () internal {
            _primary = msg.sender;
            emit PrimaryTransferred(_primary);
        }
    
        /**
         * @dev Reverts if called from any account other than the primary.
         */
        modifier onlyPrimary() {
            require(msg.sender == _primary, "Secondary: caller is not the primary account");
            _;
        }
    
        /**
         * @return the address of the primary.
         */
        function primary() public view returns (address) {
            return _primary;
        }
    
        /**
         * @dev Transfers contract to a new primary.
         * @param recipient The address of new primary.
         */
        function transferPrimary(address recipient) public onlyPrimary {
            require(recipient != address(0), "Secondary: new primary is the zero address");
            _primary = recipient;
            emit PrimaryTransferred(_primary);
        }
    }
    
    // File: contracts/minime/Controlled.sol
    
    pragma solidity ^0.5.0;
    
    contract Controlled {
        /// @notice The address of the controller is the only address that can call
        ///  a function with this modifier
        modifier onlyController { require(msg.sender == controller, "Controlled: caller is not the controller"); _; }
    
        address payable public controller;
    
        constructor () public { controller = msg.sender;}
    
        /// @notice Changes the controller of the contract
        /// @param _newController The new controller of the contract
        function changeController(address payable _newController) public onlyController {
            controller = _newController;
        }
    }
    
    // File: contracts/minime/TokenController.sol
    
    pragma solidity ^0.5.0;
    
    /// @dev The token controller contract must implement these functions
    contract TokenController {
        /// @notice Called when `_owner` sends ether to the MiniMe Token contract
        /// @param _owner The address that sent the ether to create tokens
        /// @return True if the ether is accepted, false if it throws
        function proxyPayment(address _owner) public payable returns(bool);
    
        /// @notice Notifies the controller about a token transfer allowing the
        ///  controller to react if desired
        /// @param _from The origin of the transfer
        /// @param _to The destination of the transfer
        /// @param _amount The amount of the transfer
        /// @return False if the controller does not authorize the transfer
        function onTransfer(address _from, address _to, uint _amount) public returns(bool);
    
        /// @notice Notifies the controller about an approval allowing the
        ///  controller to react if desired
        /// @param _owner The address that calls `approve()`
        /// @param _spender The spender in the `approve()` call
        /// @param _amount The amount in the `approve()` call
        /// @return False if the controller does not authorize the approval
        function onApprove(address _owner, address _spender, uint _amount) public
            returns(bool);
    }
    
    // File: contracts/minime/MiniMeToken.sol
    
    pragma solidity ^0.5.0;
    
    /*
        Copyright 2016, Jordi Baylina
    
        This program is free software: you can redistribute it and/or modify
        it under the terms of the GNU General Public License as published by
        the Free Software Foundation, either version 3 of the License, or
        (at your option) any later version.
    
        This program is distributed in the hope that it will be useful,
        but WITHOUT ANY WARRANTY; without even the implied warranty of
        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        GNU General Public License for more details.
    
        You should have received a copy of the GNU General Public License
        along with this program.  If not, see <http://www.gnu.org/licenses/>.
     */
    
    /// @title MiniMeToken Contract
    /// @author Jordi Baylina
    /// @dev This token contract's goal is to make it easy for anyone to clone this
    ///  token using the token distribution at a given block, this will allow DAO's
    ///  and DApps to upgrade their features in a decentralized manner without
    ///  affecting the original token
    /// @dev It is ERC20 compliant, but still needs to under go further testing.
    
    
    
    contract ApproveAndCallFallBack {
        function receiveApproval(address from, uint256 _amount, address _token, bytes memory _data) public;
    }
    
    /// @dev The actual token contract, the default controller is the msg.sender
    ///  that deploys the contract, so usually this token will be deployed by a
    ///  token controller contract, which Giveth will call a "Campaign"
    contract MiniMeToken is Controlled {
    
        string public name;                //The Token's name: e.g. DigixDAO Tokens
        uint8 public decimals;             //Number of decimals of the smallest unit
        string public symbol;              //An identifier: e.g. REP
        string public version = 'MMT_0.2'; //An arbitrary versioning scheme
    
    
        /// @dev `Checkpoint` is the structure that attaches a block number to a
        ///  given value, the block number attached is the one that last changed the
        ///  value
        struct  Checkpoint {
    
            // `fromBlock` is the block number that the value was generated from
            uint128 fromBlock;
    
            // `value` is the amount of tokens at a specific block number
            uint128 value;
        }
    
        // `parentToken` is the Token address that was cloned to produce this token;
        //  it will be 0x0 for a token that was not cloned
        MiniMeToken public parentToken;
    
        // `parentSnapShotBlock` is the block number from the Parent Token that was
        //  used to determine the initial distribution of the Clone Token
        uint public parentSnapShotBlock;
    
        // `creationBlock` is the block number that the Clone Token was created
        uint public creationBlock;
    
        // `balances` is the map that tracks the balance of each address, in this
        //  contract when the balance changes the block number that the change
        //  occurred is also included in the map
        mapping (address => Checkpoint[]) balances;
    
        // `allowed` tracks any extra transfer rights as in all ERC20 tokens
        mapping (address => mapping (address => uint256)) allowed;
    
        // Tracks the history of the `totalSupply` of the token
        Checkpoint[] totalSupplyHistory;
    
        // Flag that determines if the token is transferable or not.
        bool public transfersEnabled;
    
        // The factory used to create new clone tokens
        MiniMeTokenFactory public tokenFactory;
    
    ////////////////
    // Constructor
    ////////////////
    
        /// @notice Constructor to create a MiniMeToken
        /// @param _tokenFactory The address of the MiniMeTokenFactory contract that
        ///  will create the Clone token contracts, the token factory needs to be
        ///  deployed first
        /// @param _parentToken Address of the parent token, set to 0x0 if it is a
        ///  new token
        /// @param _parentSnapShotBlock Block of the parent token that will
        ///  determine the initial distribution of the clone token, set to 0 if it
        ///  is a new token
        /// @param _tokenName Name of the new token
        /// @param _decimalUnits Number of decimals of the new token
        /// @param _tokenSymbol Token Symbol for the new token
        /// @param _transfersEnabled If true, tokens will be able to be transferred
        constructor (
            address _tokenFactory,
            address payable _parentToken,
            uint _parentSnapShotBlock,
            string memory _tokenName,
            uint8 _decimalUnits,
            string memory  _tokenSymbol,
            bool _transfersEnabled
        ) public {
            tokenFactory = MiniMeTokenFactory(_tokenFactory);
            name = _tokenName;                                 // Set the name
            decimals = _decimalUnits;                          // Set the decimals
            symbol = _tokenSymbol;                             // Set the symbol
            parentToken = MiniMeToken(_parentToken);
            parentSnapShotBlock = _parentSnapShotBlock;
            transfersEnabled = _transfersEnabled;
            creationBlock = block.number;
        }
    
    
    ///////////////////
    // ERC20 Methods
    ///////////////////
    
        /// @notice Send `_amount` tokens to `_to` from `msg.sender`
        /// @param _to The address of the recipient
        /// @param _amount The amount of tokens to be transferred
        /// @return Whether the transfer was successful or not
        function transfer(address _to, uint256 _amount) public returns (bool success) {
            require(transfersEnabled, "MiniMeToken: transfer is not enable");
            doTransfer(msg.sender, _to, _amount);
            return true;
        }
    
        /// @notice Send `_amount` tokens to `_to` from `_from` on the condition it
        ///  is approved by `_from`
        /// @param _from The address holding the tokens being transferred
        /// @param _to The address of the recipient
        /// @param _amount The amount of tokens to be transferred
        /// @return True if the transfer was successful
        function transferFrom(address _from, address _to, uint256 _amount
        ) public returns (bool success) {
    
            // The controller of this contract can move tokens around at will,
            //  this is important to recognize! Confirm that you trust the
            //  controller of this contract, which in most situations should be
            //  another open source smart contract or 0x0
            if (msg.sender != controller) {
                require(transfersEnabled, "MiniMeToken: transfer is not enable");
    
                // The standard ERC 20 transferFrom functionality
                require(allowed[_from][msg.sender] >= _amount);
                allowed[_from][msg.sender] -= _amount;
            }
            doTransfer(_from, _to, _amount);
            return true;
        }
    
        /// @dev This is the actual transfer function in the token contract, it can
        ///  only be called by other functions in this contract.
        /// @param _from The address holding the tokens being transferred
        /// @param _to The address of the recipient
        /// @param _amount The amount of tokens to be transferred
        /// @return True if the transfer was successful
        function doTransfer(address _from, address _to, uint _amount
        ) internal {
    
               if (_amount == 0) {
                   emit Transfer(_from, _to, _amount);    // Follow the spec to louch the event when transfer 0
                   return;
               }
    
               require(parentSnapShotBlock < block.number);
    
               // Do not allow transfer to 0x0 or the token contract itself
               require((_to != address(0)) && (_to != address(this)));
    
               // If the amount being transfered is more than the balance of the
               //  account the transfer throws
               uint previousBalanceFrom = balanceOfAt(_from, block.number);
    
               require(previousBalanceFrom >= _amount);
    
               // Alerts the token controller of the transfer
               if (isContract(controller)) {
                   require(TokenController(controller).onTransfer(_from, _to, _amount));
               }
    
               // First update the balance array with the new value for the address
               //  sending the tokens
               updateValueAtNow(balances[_from], previousBalanceFrom - _amount);
    
               // Then update the balance array with the new value for the address
               //  receiving the tokens
               uint previousBalanceTo = balanceOfAt(_to, block.number);
               require(previousBalanceTo + _amount >= previousBalanceTo); // Check for overflow
               updateValueAtNow(balances[_to], previousBalanceTo + _amount);
    
               // An event to make the transfer easy to find on the blockchain
               emit Transfer(_from, _to, _amount);
    
        }
    
        /// @param _owner The address that's balance is being requested
        /// @return The balance of `_owner` at the current block
        function balanceOf(address _owner) public view returns (uint256 balance) {
            return balanceOfAt(_owner, block.number);
        }
    
        /// @notice `msg.sender` approves `_spender` to spend `_amount` tokens on
        ///  its behalf. This is a modified version of the ERC20 approve function
        ///  to be a little bit safer
        /// @param _spender The address of the account able to transfer the tokens
        /// @param _amount The amount of tokens to be approved for transfer
        /// @return True if the approval was successful
        function approve(address _spender, uint256 _amount) public returns (bool success) {
            require(transfersEnabled, "MiniMeToken: transfer is not enable");
    
            // To change the approve amount you first have to reduce the addresses`
            //  allowance to zero by calling `approve(_spender,0)` if it is not
            //  already 0 to mitigate the race condition described here:
            //  https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
            require((_amount == 0) || (allowed[msg.sender][_spender] == 0));
    
            // Alerts the token controller of the approve function call
            if (isContract(controller)) {
                require(TokenController(controller).onApprove(msg.sender, _spender, _amount));
            }
    
            allowed[msg.sender][_spender] = _amount;
            emit Approval(msg.sender, _spender, _amount);
            return true;
        }
    
        /// @dev This function makes it easy to read the `allowed[]` map
        /// @param _owner The address of the account that owns the token
        /// @param _spender The address of the account able to transfer the tokens
        /// @return Amount of remaining tokens of _owner that _spender is allowed
        ///  to spend
        function allowance(address _owner, address _spender
        ) public view returns (uint256 remaining) {
            return allowed[_owner][_spender];
        }
    
        /// @notice `msg.sender` approves `_spender` to send `_amount` tokens on
        ///  its behalf, and then a function is triggered in the contract that is
        ///  being approved, `_spender`. This allows users to use their tokens to
        ///  interact with contracts in one function call instead of two
        /// @param _spender The address of the contract able to transfer the tokens
        /// @param _amount The amount of tokens to be approved for transfer
        /// @return True if the function call was successful
        function approveAndCall(address _spender, uint256 _amount, bytes memory _extraData
        ) public returns (bool success) {
            require(approve(_spender, _amount));
    
            ApproveAndCallFallBack(_spender).receiveApproval(
                msg.sender,
                _amount,
                address(this),
                _extraData
            );
    
            return true;
        }
    
        /// @dev This function makes it easy to get the total number of tokens
        /// @return The total number of tokens
        function totalSupply() public view returns (uint) {
            return totalSupplyAt(block.number);
        }
    
    
    ////////////////
    // Query balance and totalSupply in History
    ////////////////
    
        /// @dev Queries the balance of `_owner` at a specific `_blockNumber`
        /// @param _owner The address from which the balance will be retrieved
        /// @param _blockNumber The block number when the balance is queried
        /// @return The balance at `_blockNumber`
        function balanceOfAt(address _owner, uint _blockNumber) public view
            returns (uint) {
    
            // These next few lines are used when the balance of the token is
            //  requested before a check point was ever created for this token, it
            //  requires that the `parentToken.balanceOfAt` be queried at the
            //  genesis block for that token as this contains initial balance of
            //  this token
            if ((balances[_owner].length == 0)
                || (balances[_owner][0].fromBlock > _blockNumber)) {
                if (address(parentToken) != address(0)) {
                    return parentToken.balanceOfAt(_owner, min(_blockNumber, parentSnapShotBlock));
                } else {
                    // Has no parent
                    return 0;
                }
    
            // This will return the expected balance during normal situations
            } else {
                return getValueAt(balances[_owner], _blockNumber);
            }
        }
    
        /// @notice Total amount of tokens at a specific `_blockNumber`.
        /// @param _blockNumber The block number when the totalSupply is queried
        /// @return The total amount of tokens at `_blockNumber`
        function totalSupplyAt(uint _blockNumber) public view returns(uint) {
    
            // These next few lines are used when the totalSupply of the token is
            //  requested before a check point was ever created for this token, it
            //  requires that the `parentToken.totalSupplyAt` be queried at the
            //  genesis block for this token as that contains totalSupply of this
            //  token at this block number.
            if ((totalSupplyHistory.length == 0)
                || (totalSupplyHistory[0].fromBlock > _blockNumber)) {
                if (address(parentToken) != address(0)) {
                    return parentToken.totalSupplyAt(min(_blockNumber, parentSnapShotBlock));
                } else {
                    return 0;
                }
    
            // This will return the expected totalSupply during normal situations
            } else {
                return getValueAt(totalSupplyHistory, _blockNumber);
            }
        }
    
    ////////////////
    // Clone Token Method
    ////////////////
    
        /// @notice Creates a new clone token with the initial distribution being
        ///  this token at `_snapshotBlock`
        /// @param _cloneTokenName Name of the clone token
        /// @param _cloneDecimalUnits Number of decimals of the smallest unit
        /// @param _cloneTokenSymbol Symbol of the clone token
        /// @param _snapshotBlock Block when the distribution of the parent token is
        ///  copied to set the initial distribution of the new clone token;
        ///  if the block is zero than the actual block, the current block is used
        /// @param _transfersEnabled True if transfers are allowed in the clone
        /// @return The address of the new MiniMeToken Contract
        function createCloneToken(
            string memory _cloneTokenName,
            uint8 _cloneDecimalUnits,
            string memory _cloneTokenSymbol,
            uint _snapshotBlock,
            bool _transfersEnabled
            ) public returns(address) {
            if (_snapshotBlock == 0) _snapshotBlock = block.number;
            MiniMeToken cloneToken = tokenFactory.createCloneToken(
                address(this),
                _snapshotBlock,
                _cloneTokenName,
                _cloneDecimalUnits,
                _cloneTokenSymbol,
                _transfersEnabled
                );
    
            cloneToken.changeController(msg.sender);
    
            // An event to make the token easy to find on the blockchain
            emit NewCloneToken(address(cloneToken), _snapshotBlock);
            return address(cloneToken);
        }
    
    ////////////////
    // Generate and destroy tokens
    ////////////////
    
        /// @notice Generates `_amount` tokens that are assigned to `_owner`
        /// @param _owner The address that will be assigned the new tokens
        /// @param _amount The quantity of tokens generated
        /// @return True if the tokens are generated correctly
        function generateTokens(address _owner, uint _amount
        ) public onlyController returns (bool) {
            uint curTotalSupply = totalSupply();
            require(curTotalSupply + _amount >= curTotalSupply); // Check for overflow
            uint previousBalanceTo = balanceOf(_owner);
            require(previousBalanceTo + _amount >= previousBalanceTo); // Check for overflow
            updateValueAtNow(totalSupplyHistory, curTotalSupply + _amount);
            updateValueAtNow(balances[_owner], previousBalanceTo + _amount);
            emit Transfer(address(0), _owner, _amount);
            return true;
        }
    
    
        /// @notice Burns `_amount` tokens from `_owner`
        /// @param _owner The address that will lose the tokens
        /// @param _amount The quantity of tokens to burn
        /// @return True if the tokens are burned correctly
        function destroyTokens(address _owner, uint _amount
        ) onlyController public returns (bool) {
            uint curTotalSupply = totalSupply();
            require(curTotalSupply >= _amount);
            uint previousBalanceFrom = balanceOf(_owner);
            require(previousBalanceFrom >= _amount);
            updateValueAtNow(totalSupplyHistory, curTotalSupply - _amount);
            updateValueAtNow(balances[_owner], previousBalanceFrom - _amount);
            emit Transfer(_owner, address(0), _amount);
            return true;
        }
    
    ////////////////
    // Enable tokens transfers
    ////////////////
    
    
        /// @notice Enables token holders to transfer their tokens freely if true
        /// @param _transfersEnabled True if transfers are allowed in the clone
        function enableTransfers(bool _transfersEnabled) public onlyController {
            transfersEnabled = _transfersEnabled;
        }
    
    ////////////////
    // Internal helper functions to query and set a value in a snapshot array
    ////////////////
    
        /// @dev `getValueAt` retrieves the number of tokens at a given block number
        /// @param checkpoints The history of values being queried
        /// @param _block The block number to retrieve the value at
        /// @return The number of tokens being queried
        function getValueAt(Checkpoint[] storage checkpoints, uint _block
        ) view internal returns (uint) {
            if (checkpoints.length == 0) return 0;
    
            // Shortcut for the actual value
            if (_block >= checkpoints[checkpoints.length-1].fromBlock)
                return checkpoints[checkpoints.length-1].value;
            if (_block < checkpoints[0].fromBlock) return 0;
    
            // Binary search of the value in the array
            uint min = 0;
            uint max = checkpoints.length-1;
            while (max > min) {
                uint mid = (max + min + 1)/ 2;
                if (checkpoints[mid].fromBlock<=_block) {
                    min = mid;
                } else {
                    max = mid-1;
                }
            }
            return checkpoints[min].value;
        }
    
        /// @dev `updateValueAtNow` used to update the `balances` map and the
        ///  `totalSupplyHistory`
        /// @param checkpoints The history of data being updated
        /// @param _value The new number of tokens
        function updateValueAtNow(Checkpoint[] storage checkpoints, uint _value
        ) internal  {
            if ((checkpoints.length == 0)
            || (checkpoints[checkpoints.length -1].fromBlock < block.number)) {
                   Checkpoint storage newCheckPoint = checkpoints[ checkpoints.length++ ];
                   newCheckPoint.fromBlock =  uint128(block.number);
                   newCheckPoint.value = uint128(_value);
               } else {
                   Checkpoint storage oldCheckPoint = checkpoints[checkpoints.length-1];
                   oldCheckPoint.value = uint128(_value);
               }
        }
    
        /// @dev Internal function to determine if an address is a contract
        /// @param _addr The address being queried
        /// @return True if `_addr` is a contract
        function isContract(address _addr) view internal returns(bool) {
            uint size;
            if (_addr == address(0)) return false;
            assembly {
                size := extcodesize(_addr)
            }
            return size>0;
        }
    
        /// @dev Helper function to return a min betwen the two uints
        function min(uint a, uint b) pure internal returns (uint) {
            return a < b ? a : b;
        }
    
        /// @notice The fallback function: If the contract's controller has not been
        ///  set to 0, then the `proxyPayment` method is called which relays the
        ///  ether and creates tokens as described in the token controller contract
        function () external payable {
            require(isContract(controller));
            require(TokenController(controller).proxyPayment.value(msg.value)(msg.sender));
        }
    
    //////////
    // Safety Methods
    //////////
    
        /// @notice This method can be used by the controller to extract mistakenly
        ///  sent tokens to this contract.
        /// @param _token The address of the token contract that you want to recover
        ///  set to 0 in case you want to extract ether.
        function claimTokens(address payable _token) public onlyController {
            if (_token == address(0)) {
                controller.transfer(address(this).balance);
                return;
            }
    
            MiniMeToken token = MiniMeToken(_token);
            uint balance = token.balanceOf(address(this));
            token.transfer(controller, balance);
            emit ClaimedTokens(_token, controller, balance);
        }
    
    ////////////////
    // Events
    ////////////////
        event ClaimedTokens(address indexed _token, address indexed _controller, uint _amount);
        event Transfer(address indexed _from, address indexed _to, uint256 _amount);	
        event NewCloneToken(address indexed _cloneToken, uint _snapshotBlock);
        event Approval(	
            address indexed _owner,	
            address indexed _spender,	
            uint256 _amount	
            );
    }
    
    
    ////////////////
    // MiniMeTokenFactory
    ////////////////
    
    /// @dev This contract is used to generate clone contracts from a contract.
    ///  In solidity this is the way to create a contract from a contract of the
    ///  same class
    contract MiniMeTokenFactory {
    
        /// @notice Update the DApp by creating a new token with new functionalities
        ///  the msg.sender becomes the controller of this clone token
        /// @param _parentToken Address of the token being cloned
        /// @param _snapshotBlock Block of the parent token that will
        ///  determine the initial distribution of the clone token
        /// @param _tokenName Name of the new token
        /// @param _decimalUnits Number of decimals of the new token
        /// @param _tokenSymbol Token Symbol for the new token
        /// @param _transfersEnabled If true, tokens will be able to be transferred
        /// @return The address of the new token contract
        function createCloneToken(
            address payable _parentToken,
            uint _snapshotBlock,
            string memory _tokenName,
            uint8 _decimalUnits,
            string memory _tokenSymbol,
            bool _transfersEnabled
        ) public returns (MiniMeToken) {
            MiniMeToken newToken = new MiniMeToken(
                address(this),
                _parentToken,
                _snapshotBlock,
                _tokenName,
                _decimalUnits,
                _tokenSymbol,
                _transfersEnabled
                );
    
            newToken.changeController(msg.sender);
            return newToken;
        }
    }
    
    // File: contracts/VestingTokenStep.sol
    
    pragma solidity ^0.5.0;
    
    
    
    contract VestingTokenStep is MiniMeToken {
        using SafeMath for uint256;
    
        bool public initiated;
    
        // Durations and timestamps are expressed in UNIX time, the same units as block.timestamp.
        uint256 public cliff;
        uint256 public start;
        uint256 public duration;
        uint256 public constant UNIT_IN_SECONDS = 60 * 60 * 24 * 30;
    
        mapping (address => uint256) public released;
    
        constructor (
            address tokenFactory,
            address payable parentToken,
            uint parentSnapShotBlock,
            string memory tokenName,
            uint8 decimalUnits,
            string memory tokenSymbol,
            bool transfersEnabled
        )
            public
            MiniMeToken(tokenFactory, parentToken, parentSnapShotBlock, tokenName, decimalUnits, tokenSymbol, transfersEnabled)
        {
            // solhint-disable-previous-line no-empty-blocks
        }
    
        modifier beforeInitiated() {
            require(!initiated, "VestingTokenStep: cannot execute after initiation");
            _;
        }
    
        modifier afterInitiated() {
            require(initiated, "VestingTokenStep: cannot execute before initiation");
            _;
        }
    
        /**
         * @notice Makes vested tokens releasable.
         * @param _start the time (as Unix time) at which point vesting starts
         * @param cliffDuration duration in unit(30 days) of the cliff in which tokens will begin to vest
         * @param _duration duration in unit(30 days) of the period in which the tokens will vest(after the cliff period)
         */
        function initiate(uint256 _start, uint256 cliffDuration, uint256 _duration) public beforeInitiated onlyController {
            initiated = true;
    
            enableTransfers(false);
    
            // solhint-disable-next-line max-line-length
            require(cliffDuration <= _duration, "VestingTokenStep: cliff is longer than duration");
            require(_duration != 0, "VestingTokenStep: duration is 0");
            // solhint-disable-next-line max-line-length
            require(_start.add(_duration.mul(UNIT_IN_SECONDS)) > block.timestamp, "VestingTokenStep: final time is before current time");
    
            duration = _duration;
            start = _start;
            cliff = start.add(cliffDuration.mul(UNIT_IN_SECONDS));
        }
    
        /**
         * @dev This is the actual transfer function in the token contract.
         * @param from The address holding the tokens being transferred
         * @param to The address of the recipient
         * @param amount The amount of tokens to be transferred
         */
        function doTransfer(address from, address to, uint amount) internal beforeInitiated {
            super.doTransfer(from, to, amount);
        }
    
        /**
         * @notice Destroys releasable tokens.
         * @param beneficiary the beneficiary of the tokens.
         */
        function destroyReleasableTokens(address beneficiary) public afterInitiated onlyController returns (uint256 unreleased) {
            unreleased = releasableAmount(beneficiary);
    
            require(unreleased != 0, "VestingTokenStep: no tokens are due");
    
            released[beneficiary] = released[beneficiary].add(unreleased);
    
            require(destroyTokens(beneficiary, unreleased), "VestingTokenStep: failed to destroy tokens");
        }
    
        /**
         * @dev Calculates the amount that has already vested but hasn't been released yet.
         * @param beneficiary the beneficiary of the tokens.
         */
        function releasableAmount(address beneficiary) public view returns (uint256) {
            return _vestedAmount(beneficiary).sub(released[beneficiary]);
        }
    
        /**
         * @dev Calculates the amount that has already vested.
         * @param beneficiary the beneficiary of the tokens.
         */
        function _vestedAmount(address beneficiary) private view returns (uint256) {
            if (!initiated) {
                return 0;
            }
    
            uint256 currentVestedAmount = balanceOf(beneficiary);
            uint256 totalVestedAmount = currentVestedAmount.add(released[beneficiary]);
    
            if (block.timestamp < cliff) {
                return 0;
            } else if (block.timestamp >= cliff.add(duration.mul(UNIT_IN_SECONDS))) {
                return totalVestedAmount;
            } else {
                uint256 currenUnit = block.timestamp.sub(cliff).div(UNIT_IN_SECONDS).add(1);
                return totalVestedAmount.mul(currenUnit).div(duration);
            }
        }
    }
    
    // File: contracts/TONVault.sol
    
    pragma solidity ^0.5.0;
    
    
    
    
    contract TONVault is Secondary {
        using SafeMath for uint256;
    
        ERC20Mintable public ton;
    
        constructor (ERC20Mintable tonToken) public {
            ton = tonToken;
        }
    
        function setApprovalAmount(address approval, uint256 amount) public onlyPrimary {
            ton.approve(approval, amount);
        }
        
        function withdraw(uint256 amount, address recipient) public onlyPrimary {
            ton.transfer(recipient, amount);
        }
    }
    
    // File: contracts/Burner.sol
    
    pragma solidity ^0.5.0;
    
    contract Burner {
        constructor () public {
        }
    }
    
    // File: contracts/Swapper.sol
    
    pragma solidity ^0.5.0;
    
    
    
    
    
    
    
    
    contract Swapper is Secondary {
        using SafeMath for uint256;
    
        mapping(address => uint256) public ratio;
    
        ERC20Mintable public _token;
        IERC20 public mton;
        TONVault public vault;
        address public constant burner = 0x0000000000000000000000000000000000000001;
        uint256 public startTimestamp;
    
        event Swapped(address account, uint256 unreleased, uint256 transferred);
        event Withdrew(address recipient, uint256 amount);
        event UpdateRatio(address vestingToken, uint256 tokenRatio);
        event SetVault(address vaultAddress);
    
        modifier onlyBeforeStart() {
            require(block.timestamp < startTimestamp || startTimestamp == 0, "Swapper: cannot execute after start");
            _;
        }
    
        constructor (ERC20Mintable token, address mtonAddress) public {
            _token = token;
            mton = IERC20(mtonAddress);
        }
    
        function updateRatio(address vestingToken, uint256 tokenRatio) external onlyPrimary onlyBeforeStart {
            ratio[vestingToken] = tokenRatio;
            emit UpdateRatio(vestingToken, tokenRatio);
        }
    
        function setStart(uint256 _startTimestamp) external onlyPrimary {
            require(startTimestamp == 0, "Swapper: the starttime is already set");
            startTimestamp = _startTimestamp;
        }
    
        function swap(address payable vestingToken) external returns (bool) {
            uint256 tokenRatio = ratio[vestingToken];
            require(tokenRatio != 0, "VestingSwapper: not valid sale token address");
    
            uint256 unreleased = releasableAmount(vestingToken, msg.sender);
            if (unreleased == 0) {
                return true;
            }
    
            if (vestingToken == address(mton)) {
                mton.transferFrom(msg.sender, address(this), unreleased);
                mton.transfer(burner, unreleased);
            } else {
                unreleased = VestingTokenStep(vestingToken).destroyReleasableTokens(msg.sender);
            }
            uint256 ton_amount = unreleased.mul(tokenRatio);
            _token.transferFrom(address(vault), address(this), ton_amount);
            _token.transfer(msg.sender, ton_amount);
            
            emit Swapped(msg.sender, unreleased, ton_amount);
            return true;
        }
    
        // TokenController
    
        /// @notice Called when `_owner` sends ether to the MiniMe Token contract
        /// @param _owner The address that sent the ether to create tokens
        /// @return True if the ether is accepted, false if it throws
        function proxyPayment(address _owner) public payable returns(bool) {
            return true;
        }
    
        /// @notice Notifies the controller about a token transfer allowing the
        ///  controller to react if desired
        /// @param _from The origin of the transfer
        /// @param _to The destination of the transfer
        /// @param _amount The amount of the transfer
        /// @return False if the controller does not authorize the transfer
        function onTransfer(address _from, address _to, uint _amount) public returns(bool) {
            return true;
        }
    
        /// @notice Notifies the controller about an approval allowing the
        ///  controller to react if desired
        /// @param _owner The address that calls `approve()`
        /// @param _spender The spender in the `approve()` call
        /// @param _amount The amount in the `approve()` call
        /// @return False if the controller does not authorize the approval
        function onApprove(address _owner, address _spender, uint _amount) public returns(bool) {
            return true;
        }
    
        function releasableAmount(address payable vestingToken, address beneficiary) public view returns (uint256) {
            if (vestingToken == address(mton)) {
                return mton.balanceOf(beneficiary);
            } else {
                return VestingTokenStep(vestingToken).releasableAmount(beneficiary);
            }
        }
    
        function changeController(VestingTokenStep vestingToken, address payable newController) external onlyPrimary {
            vestingToken.changeController(newController);
        }
    
        function setVault(TONVault vaultAddress) external onlyPrimary {
            vault = vaultAddress;
            emit SetVault(address(vaultAddress));
        }
    }

    File 2 of 4: MTON
    // File: openzeppelin-solidity/contracts/GSN/Context.sol
    
    pragma solidity ^0.5.0;
    
    /*
     * @dev Provides information about the current execution context, including the
     * sender of the transaction and its data. While these are generally available
     * via msg.sender and msg.data, they should not be accessed in such a direct
     * manner, since when dealing with GSN meta-transactions the account sending and
     * paying for execution may not be the actual sender (as far as an application
     * is concerned).
     *
     * This contract is only required for intermediate, library-like contracts.
     */
    contract Context {
        // Empty internal constructor, to prevent people from mistakenly deploying
        // an instance of this contract, which should be used via inheritance.
        constructor () internal { }
        // solhint-disable-previous-line no-empty-blocks
    
        function _msgSender() internal view returns (address payable) {
            return msg.sender;
        }
    
        function _msgData() internal view returns (bytes memory) {
            this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
            return msg.data;
        }
    }
    
    // File: openzeppelin-solidity/contracts/ownership/Ownable.sol
    
    pragma solidity ^0.5.0;
    
    /**
     * @dev Contract module which provides a basic access control mechanism, where
     * there is an account (an owner) that can be granted exclusive access to
     * specific functions.
     *
     * This module is used through inheritance. It will make available the modifier
     * `onlyOwner`, which can be applied to your functions to restrict their use to
     * the owner.
     */
    contract Ownable is Context {
        address private _owner;
    
        event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
    
        /**
         * @dev Initializes the contract setting the deployer as the initial owner.
         */
        constructor () internal {
            address msgSender = _msgSender();
            _owner = msgSender;
            emit OwnershipTransferred(address(0), msgSender);
        }
    
        /**
         * @dev Returns the address of the current owner.
         */
        function owner() public view returns (address) {
            return _owner;
        }
    
        /**
         * @dev Throws if called by any account other than the owner.
         */
        modifier onlyOwner() {
            require(isOwner(), "Ownable: caller is not the owner");
            _;
        }
    
        /**
         * @dev Returns true if the caller is the current owner.
         */
        function isOwner() public view returns (bool) {
            return _msgSender() == _owner;
        }
    
        /**
         * @dev Leaves the contract without owner. It will not be possible to call
         * `onlyOwner` functions anymore. Can only be called by the current owner.
         *
         * NOTE: Renouncing ownership will leave the contract without an owner,
         * thereby removing any functionality that is only available to the owner.
         */
        function renounceOwnership() public onlyOwner {
            emit OwnershipTransferred(_owner, address(0));
            _owner = address(0);
        }
    
        /**
         * @dev Transfers ownership of the contract to a new account (`newOwner`).
         * Can only be called by the current owner.
         */
        function transferOwnership(address newOwner) public onlyOwner {
            _transferOwnership(newOwner);
        }
    
        /**
         * @dev Transfers ownership of the contract to a new account (`newOwner`).
         */
        function _transferOwnership(address newOwner) internal {
            require(newOwner != address(0), "Ownable: new owner is the zero address");
            emit OwnershipTransferred(_owner, newOwner);
            _owner = newOwner;
        }
    }
    
    // File: openzeppelin-solidity/contracts/token/ERC20/IERC20.sol
    
    pragma solidity ^0.5.0;
    
    /**
     * @dev Interface of the ERC20 standard as defined in the EIP. Does not include
     * the optional functions; to access them see {ERC20Detailed}.
     */
    interface IERC20 {
        /**
         * @dev Returns the amount of tokens in existence.
         */
        function totalSupply() external view returns (uint256);
    
        /**
         * @dev Returns the amount of tokens owned by `account`.
         */
        function balanceOf(address account) external view returns (uint256);
    
        /**
         * @dev Moves `amount` tokens from the caller's account to `recipient`.
         *
         * Returns a boolean value indicating whether the operation succeeded.
         *
         * Emits a {Transfer} event.
         */
        function transfer(address recipient, uint256 amount) external returns (bool);
    
        /**
         * @dev Returns the remaining number of tokens that `spender` will be
         * allowed to spend on behalf of `owner` through {transferFrom}. This is
         * zero by default.
         *
         * This value changes when {approve} or {transferFrom} are called.
         */
        function allowance(address owner, address spender) external view returns (uint256);
    
        /**
         * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
         *
         * Returns a boolean value indicating whether the operation succeeded.
         *
         * IMPORTANT: Beware that changing an allowance with this method brings the risk
         * that someone may use both the old and the new allowance by unfortunate
         * transaction ordering. One possible solution to mitigate this race
         * condition is to first reduce the spender's allowance to 0 and set the
         * desired value afterwards:
         * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
         *
         * Emits an {Approval} event.
         */
        function approve(address spender, uint256 amount) external returns (bool);
    
        /**
         * @dev Moves `amount` tokens from `sender` to `recipient` using the
         * allowance mechanism. `amount` is then deducted from the caller's
         * allowance.
         *
         * Returns a boolean value indicating whether the operation succeeded.
         *
         * Emits a {Transfer} event.
         */
        function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
    
        /**
         * @dev Emitted when `value` tokens are moved from one account (`from`) to
         * another (`to`).
         *
         * Note that `value` may be zero.
         */
        event Transfer(address indexed from, address indexed to, uint256 value);
    
        /**
         * @dev Emitted when the allowance of a `spender` for an `owner` is set by
         * a call to {approve}. `value` is the new allowance.
         */
        event Approval(address indexed owner, address indexed spender, uint256 value);
    }
    
    // File: openzeppelin-solidity/contracts/math/SafeMath.sol
    
    pragma solidity ^0.5.0;
    
    /**
     * @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.
         *
         * _Available since v2.4.0._
         */
        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.
         *
         * _Available since v2.4.0._
         */
        function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
            // Solidity only automatically asserts when dividing by 0
            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.
         *
         * _Available since v2.4.0._
         */
        function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
            require(b != 0, errorMessage);
            return a % b;
        }
    }
    
    // File: openzeppelin-solidity/contracts/token/ERC20/ERC20.sol
    
    pragma solidity ^0.5.0;
    
    
    
    
    /**
     * @dev Implementation of the {IERC20} interface.
     *
     * This implementation is agnostic to the way tokens are created. This means
     * that a supply mechanism has to be added in a derived contract using {_mint}.
     * For a generic mechanism see {ERC20Mintable}.
     *
     * TIP: For a detailed writeup see our guide
     * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
     * to implement supply mechanisms].
     *
     * We have followed general OpenZeppelin guidelines: functions revert instead
     * of returning `false` on failure. This behavior is nonetheless conventional
     * and does not conflict with the expectations of ERC20 applications.
     *
     * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
     * This allows applications to reconstruct the allowance for all accounts just
     * by listening to said events. Other implementations of the EIP may not emit
     * these events, as it isn't required by the specification.
     *
     * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
     * functions have been added to mitigate the well-known issues around setting
     * allowances. See {IERC20-approve}.
     */
    contract ERC20 is Context, IERC20 {
        using SafeMath for uint256;
    
        mapping (address => uint256) private _balances;
    
        mapping (address => mapping (address => uint256)) private _allowances;
    
        uint256 private _totalSupply;
    
        /**
         * @dev See {IERC20-totalSupply}.
         */
        function totalSupply() public view returns (uint256) {
            return _totalSupply;
        }
    
        /**
         * @dev See {IERC20-balanceOf}.
         */
        function balanceOf(address account) public view returns (uint256) {
            return _balances[account];
        }
    
        /**
         * @dev See {IERC20-transfer}.
         *
         * Requirements:
         *
         * - `recipient` cannot be the zero address.
         * - the caller must have a balance of at least `amount`.
         */
        function transfer(address recipient, uint256 amount) public returns (bool) {
            _transfer(_msgSender(), recipient, amount);
            return true;
        }
    
        /**
         * @dev See {IERC20-allowance}.
         */
        function allowance(address owner, address spender) public view returns (uint256) {
            return _allowances[owner][spender];
        }
    
        /**
         * @dev See {IERC20-approve}.
         *
         * Requirements:
         *
         * - `spender` cannot be the zero address.
         */
        function approve(address spender, uint256 amount) public returns (bool) {
            _approve(_msgSender(), spender, amount);
            return true;
        }
    
        /**
         * @dev See {IERC20-transferFrom}.
         *
         * Emits an {Approval} event indicating the updated allowance. This is not
         * required by the EIP. See the note at the beginning of {ERC20};
         *
         * Requirements:
         * - `sender` and `recipient` cannot be the zero address.
         * - `sender` must have a balance of at least `amount`.
         * - the caller must have allowance for `sender`'s tokens of at least
         * `amount`.
         */
        function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) {
            _transfer(sender, recipient, amount);
            _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
            return true;
        }
    
        /**
         * @dev Atomically increases the allowance granted to `spender` by the caller.
         *
         * This is an alternative to {approve} that can be used as a mitigation for
         * problems described in {IERC20-approve}.
         *
         * Emits an {Approval} event indicating the updated allowance.
         *
         * Requirements:
         *
         * - `spender` cannot be the zero address.
         */
        function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
            _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
            return true;
        }
    
        /**
         * @dev Atomically decreases the allowance granted to `spender` by the caller.
         *
         * This is an alternative to {approve} that can be used as a mitigation for
         * problems described in {IERC20-approve}.
         *
         * Emits an {Approval} event indicating the updated allowance.
         *
         * Requirements:
         *
         * - `spender` cannot be the zero address.
         * - `spender` must have allowance for the caller of at least
         * `subtractedValue`.
         */
        function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
            _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
            return true;
        }
    
        /**
         * @dev Moves tokens `amount` from `sender` to `recipient`.
         *
         * This is internal function is equivalent to {transfer}, and can be used to
         * e.g. implement automatic token fees, slashing mechanisms, etc.
         *
         * Emits a {Transfer} event.
         *
         * Requirements:
         *
         * - `sender` cannot be the zero address.
         * - `recipient` cannot be the zero address.
         * - `sender` must have a balance of at least `amount`.
         */
        function _transfer(address sender, address recipient, uint256 amount) internal {
            require(sender != address(0), "ERC20: transfer from the zero address");
            require(recipient != address(0), "ERC20: transfer to the zero address");
    
            _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
            _balances[recipient] = _balances[recipient].add(amount);
            emit Transfer(sender, recipient, amount);
        }
    
        /** @dev Creates `amount` tokens and assigns them to `account`, increasing
         * the total supply.
         *
         * Emits a {Transfer} event with `from` set to the zero address.
         *
         * Requirements
         *
         * - `to` cannot be the zero address.
         */
        function _mint(address account, uint256 amount) internal {
            require(account != address(0), "ERC20: mint to the zero address");
    
            _totalSupply = _totalSupply.add(amount);
            _balances[account] = _balances[account].add(amount);
            emit Transfer(address(0), account, amount);
        }
    
        /**
         * @dev Destroys `amount` tokens from `account`, reducing the
         * total supply.
         *
         * Emits a {Transfer} event with `to` set to the zero address.
         *
         * Requirements
         *
         * - `account` cannot be the zero address.
         * - `account` must have at least `amount` tokens.
         */
        function _burn(address account, uint256 amount) internal {
            require(account != address(0), "ERC20: burn from the zero address");
    
            _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
            _totalSupply = _totalSupply.sub(amount);
            emit Transfer(account, address(0), amount);
        }
    
        /**
         * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens.
         *
         * This is internal function is equivalent to `approve`, and can be used to
         * e.g. set automatic allowances for certain subsystems, etc.
         *
         * Emits an {Approval} event.
         *
         * Requirements:
         *
         * - `owner` cannot be the zero address.
         * - `spender` cannot be the zero address.
         */
        function _approve(address owner, address spender, uint256 amount) internal {
            require(owner != address(0), "ERC20: approve from the zero address");
            require(spender != address(0), "ERC20: approve to the zero address");
    
            _allowances[owner][spender] = amount;
            emit Approval(owner, spender, amount);
        }
    
        /**
         * @dev Destroys `amount` tokens from `account`.`amount` is then deducted
         * from the caller's allowance.
         *
         * See {_burn} and {_approve}.
         */
        function _burnFrom(address account, uint256 amount) internal {
            _burn(account, amount);
            _approve(account, _msgSender(), _allowances[account][_msgSender()].sub(amount, "ERC20: burn amount exceeds allowance"));
        }
    }
    
    // File: openzeppelin-solidity/contracts/access/Roles.sol
    
    pragma solidity ^0.5.0;
    
    /**
     * @title Roles
     * @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: openzeppelin-solidity/contracts/access/roles/MinterRole.sol
    
    pragma solidity ^0.5.0;
    
    
    
    contract MinterRole is Context {
        using Roles for Roles.Role;
    
        event MinterAdded(address indexed account);
        event MinterRemoved(address indexed account);
    
        Roles.Role private _minters;
    
        constructor () internal {
            _addMinter(_msgSender());
        }
    
        modifier onlyMinter() {
            require(isMinter(_msgSender()), "MinterRole: caller does not have the Minter role");
            _;
        }
    
        function isMinter(address account) public view returns (bool) {
            return _minters.has(account);
        }
    
        function addMinter(address account) public onlyMinter {
            _addMinter(account);
        }
    
        function renounceMinter() public {
            _removeMinter(_msgSender());
        }
    
        function _addMinter(address account) internal {
            _minters.add(account);
            emit MinterAdded(account);
        }
    
        function _removeMinter(address account) internal {
            _minters.remove(account);
            emit MinterRemoved(account);
        }
    }
    
    // File: openzeppelin-solidity/contracts/token/ERC20/ERC20Mintable.sol
    
    pragma solidity ^0.5.0;
    
    
    
    /**
     * @dev Extension of {ERC20} that adds a set of accounts with the {MinterRole},
     * which have permission to mint (create) new tokens as they see fit.
     *
     * At construction, the deployer of the contract is the only minter.
     */
    contract ERC20Mintable is ERC20, MinterRole {
        /**
         * @dev See {ERC20-_mint}.
         *
         * Requirements:
         *
         * - the caller must have the {MinterRole}.
         */
        function mint(address account, uint256 amount) public onlyMinter returns (bool) {
            _mint(account, amount);
            return true;
        }
    }
    
    // File: openzeppelin-solidity/contracts/token/ERC20/ERC20Detailed.sol
    
    pragma solidity ^0.5.0;
    
    
    /**
     * @dev Optional functions from the ERC20 standard.
     */
    contract ERC20Detailed is IERC20 {
        string private _name;
        string private _symbol;
        uint8 private _decimals;
    
        /**
         * @dev Sets the values for `name`, `symbol`, and `decimals`. All three of
         * these values are immutable: they can only be set once during
         * construction.
         */
        constructor (string memory name, string memory symbol, uint8 decimals) public {
            _name = name;
            _symbol = symbol;
            _decimals = decimals;
        }
    
        /**
         * @dev Returns the name of the token.
         */
        function name() public view returns (string memory) {
            return _name;
        }
    
        /**
         * @dev Returns the symbol of the token, usually a shorter version of the
         * name.
         */
        function symbol() public view returns (string memory) {
            return _symbol;
        }
    
        /**
         * @dev Returns the number of decimals used to get its user representation.
         * For example, if `decimals` equals `2`, a balance of `505` tokens should
         * be displayed to a user as `5,05` (`505 / 10 ** 2`).
         *
         * Tokens usually opt for a value of 18, imitating the relationship between
         * Ether and Wei.
         *
         * NOTE: This information is only used for _display_ purposes: it in
         * no way affects any of the arithmetic of the contract, including
         * {IERC20-balanceOf} and {IERC20-transfer}.
         */
        function decimals() public view returns (uint8) {
            return _decimals;
        }
    }
    
    // File: openzeppelin-solidity/contracts/introspection/ERC165Checker.sol
    
    pragma solidity ^0.5.10;
    
    /**
     * @dev Library used to query support of an interface declared via {IERC165}.
     *
     * Note that these functions return the actual result of the query: they do not
     * `revert` if an interface is not supported. It is up to the caller to decide
     * what to do in these cases.
     */
    library ERC165Checker {
        // As per the EIP-165 spec, no interface should ever match 0xffffffff
        bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;
    
        /*
         * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7
         */
        bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;
    
        /**
         * @dev Returns true if `account` supports the {IERC165} interface,
         */
        function _supportsERC165(address account) internal view returns (bool) {
            // Any contract that implements ERC165 must explicitly indicate support of
            // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid
            return _supportsERC165Interface(account, _INTERFACE_ID_ERC165) &&
                !_supportsERC165Interface(account, _INTERFACE_ID_INVALID);
        }
    
        /**
         * @dev Returns true if `account` supports the interface defined by
         * `interfaceId`. Support for {IERC165} itself is queried automatically.
         *
         * See {IERC165-supportsInterface}.
         */
        function _supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {
            // query support of both ERC165 as per the spec and support of _interfaceId
            return _supportsERC165(account) &&
                _supportsERC165Interface(account, interfaceId);
        }
    
        /**
         * @dev Returns true if `account` supports all the interfaces defined in
         * `interfaceIds`. Support for {IERC165} itself is queried automatically.
         *
         * Batch-querying can lead to gas savings by skipping repeated checks for
         * {IERC165} support.
         *
         * See {IERC165-supportsInterface}.
         */
        function _supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {
            // query support of ERC165 itself
            if (!_supportsERC165(account)) {
                return false;
            }
    
            // query support of each interface in _interfaceIds
            for (uint256 i = 0; i < interfaceIds.length; i++) {
                if (!_supportsERC165Interface(account, interfaceIds[i])) {
                    return false;
                }
            }
    
            // all interfaces supported
            return true;
        }
    
        /**
         * @notice Query if a contract implements an interface, does not check ERC165 support
         * @param account The address of the contract to query for support of an interface
         * @param interfaceId The interface identifier, as specified in ERC-165
         * @return true if the contract at account indicates support of the interface with
         * identifier interfaceId, false otherwise
         * @dev Assumes that account contains a contract that supports ERC165, otherwise
         * the behavior of this method is undefined. This precondition can be checked
         * with the `supportsERC165` method in this library.
         * Interface identification is specified in ERC-165.
         */
        function _supportsERC165Interface(address account, bytes4 interfaceId) private view returns (bool) {
            // success determines whether the staticcall succeeded and result determines
            // whether the contract at account indicates support of _interfaceId
            (bool success, bool result) = _callERC165SupportsInterface(account, interfaceId);
    
            return (success && result);
        }
    
        /**
         * @notice Calls the function with selector 0x01ffc9a7 (ERC165) and suppresses throw
         * @param account The address of the contract to query for support of an interface
         * @param interfaceId The interface identifier, as specified in ERC-165
         * @return success true if the STATICCALL succeeded, false otherwise
         * @return result true if the STATICCALL succeeded and the contract at account
         * indicates support of the interface with identifier interfaceId, false otherwise
         */
        function _callERC165SupportsInterface(address account, bytes4 interfaceId)
            private
            view
            returns (bool, bool)
        {
            bytes memory encodedParams = abi.encodeWithSelector(_INTERFACE_ID_ERC165, interfaceId);
            (bool success, bytes memory result) = account.staticcall.gas(30000)(encodedParams);
            if (result.length < 32) return (false, false);
            return (success, abi.decode(result, (bool)));
        }
    }
    
    // File: contracts/stake/interfaces/SeigManagerI.sol
    
    pragma solidity ^0.5.12;
    
    
    interface SeigManagerI {
      function registry() external view returns (address);
      function depositManager() external view returns (address);
      function ton() external view returns (address);
      function wton() external view returns (address);
      function powerton() external view returns (address);
      function tot() external view returns (address);
      function coinages(address rootchain) external view returns (address);
      function commissionRates(address rootchain) external view returns (uint256);
    
      function lastCommitBlock(address rootchain) external view returns (uint256);
      function seigPerBlock() external view returns (uint256);
      function lastSeigBlock() external view returns (uint256);
      function pausedBlock() external view returns (uint256);
      function unpausedBlock() external view returns (uint256);
      function DEFAULT_FACTOR() external view returns (uint256);
    
      function deployCoinage(address rootchain) external returns (bool);
      function setCommissionRate(address rootchain, uint256 commission) external returns (bool);
    
      function uncomittedStakeOf(address rootchain, address account) external view returns (uint256);
      function stakeOf(address rootchain, address account) external view returns (uint256);
      function additionalTotBurnAmount(address rootchain, address account, uint256 amount) external view returns (uint256 totAmount);
    
      function onTransfer(address sender, address recipient, uint256 amount) external returns (bool);
      function onCommit() external returns (bool);
      function onDeposit(address rootchain, address account, uint256 amount) external returns (bool);
      function onWithdraw(address rootchain, address account, uint256 amount) external returns (bool);
    
    }
    
    // File: contracts/stake/tokens/OnApproveConstant.sol
    
    pragma solidity ^0.5.12;
    
    
    contract OnApproveConstant {
      bytes4 public constant INTERFACE_ID_ON_APPROVE = bytes4(keccak256("onApprove(address,address,uint256,bytes)"));
    }
    
    // File: contracts/stake/tokens/ERC20OnApprove.sol
    
    pragma solidity ^0.5.12;
    
    
    
    
    
    contract ERC20OnApprove is ERC20, OnApproveConstant {
      function approveAndCall(address spender, uint256 amount, bytes memory data) public returns (bool) {
        require(approve(spender, amount));
        _callOnApprove(msg.sender, spender, amount, data);
      }
    
      function _callOnApprove(address owner, address spender, uint256 amount, bytes memory data) internal {
        require(ERC165Checker._supportsInterface(spender, INTERFACE_ID_ON_APPROVE),
          "ERC20OnApprove: spender doesn't support onApprove");
    
        (bool ok, bytes memory res) = spender.call(
          abi.encodeWithSelector(
            INTERFACE_ID_ON_APPROVE,
            owner,
            spender,
            amount,
            data
          )
        );
    
        require(ok, string(res));
        // require(ok, "ERC20OnApprove: failed to call onApprove");
      }
    
    }
    
    // File: contracts/stake/tokens/AuthController.sol
    
    pragma solidity ^0.5.12;
    
    
    
    interface MinterRoleRenounceTarget {
      function renounceMinter() external;
    }
    
    interface PauserRoleRenounceTarget {
      function renouncePauser() external;
    }
    
    interface OwnableTarget {
      function renounceOwnership() external;
      function transferOwnership(address newOwner) external;
    }
    
    contract AuthController is Ownable {
      function renounceMinter(address target) public onlyOwner {
        MinterRoleRenounceTarget(target).renounceMinter();
      }
    
      function renouncePauser(address target) public onlyOwner {
        PauserRoleRenounceTarget(target).renouncePauser();
      }
    
      function renounceOwnership(address target) public onlyOwner {
        OwnableTarget(target).renounceOwnership();
      }
    
      function transferOwnership(address target, address newOwner) public onlyOwner {
        OwnableTarget(target).transferOwnership(newOwner);
      }
    }
    
    // File: contracts/stake/tokens/SeigToken.sol
    
    pragma solidity ^0.5.12;
    
    
    
    
    
    
    
    contract SeigToken is ERC20, Ownable, ERC20OnApprove, AuthController {
      SeigManagerI public seigManager;
    
      function setSeigManager(SeigManagerI _seigManager) external onlyOwner {
        seigManager = _seigManager;
      }
    
      //////////////////////
      // Override ERC20 functions
      //////////////////////
    
      function _transfer(address sender, address recipient, uint256 amount) internal {
        require(msg.sender == sender || msg.sender == recipient, "SeigToken: only sender or recipient can transfer");
        super._transfer(sender, recipient, amount);
        if (address(seigManager) != address(0)) {
          // seigManager.onTransfer(sender, recipient, amount);
        }
      }
    
      function _mint(address account, uint256 amount) internal {
        super._mint(account, amount);
        if (address(seigManager) != address(0)) {
          // seigManager.onTransfer(address(0), account, amount);
        }
      }
    
      function _burn(address account, uint256 amount) internal {
        super._burn(account, amount);
        if (address(seigManager) != address(0)) {
          // seigManager.onTransfer(account, address(0), amount);
        }
      }
    }
    
    // File: contracts/stake/tokens/MTON.sol
    
    pragma solidity ^0.5.12;
    
    
    
    
    
    
    
    
    /**
     * @dev Current implementations is just for testing seigniorage manager.
     */
    contract MTON is Ownable, ERC20Mintable, ERC20Detailed, SeigToken {
      constructor() public ERC20Detailed("Marketing Tokamak Network Token", "MTON", 18) {}
    
      function setSeigManager(SeigManagerI _seigManager) external {
        revert("MTON: MTON doesn't allow setSeigManager");
      }
    }

    File 3 of 4: TONVault
    // File: contracts/openzeppelin-solidity/token/ERC20/IERC20.sol
    
    pragma solidity ^0.5.0;
    
    /**
     * @dev Interface of the ERC20 standard as defined in the EIP. Does not include
     * the optional functions; to access them see `ERC20Detailed`.
     */
    interface IERC20 {
        /**
         * @dev Returns the amount of tokens in existence.
         */
        function totalSupply() external view returns (uint256);
    
        /**
         * @dev Returns the amount of tokens owned by `account`.
         */
        function balanceOf(address account) external view returns (uint256);
    
        /**
         * @dev Moves `amount` tokens from the caller's account to `recipient`.
         *
         * Returns a boolean value indicating whether the operation succeeded.
         *
         * Emits a `Transfer` event.
         */
        function transfer(address recipient, uint256 amount) external returns (bool);
    
        /**
         * @dev Returns the remaining number of tokens that `spender` will be
         * allowed to spend on behalf of `owner` through `transferFrom`. This is
         * zero by default.
         *
         * This value changes when `approve` or `transferFrom` are called.
         */
        function allowance(address owner, address spender) external view returns (uint256);
    
        /**
         * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
         *
         * Returns a boolean value indicating whether the operation succeeded.
         *
         * > Beware that changing an allowance with this method brings the risk
         * that someone may use both the old and the new allowance by unfortunate
         * transaction ordering. One possible solution to mitigate this race
         * condition is to first reduce the spender's allowance to 0 and set the
         * desired value afterwards:
         * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
         *
         * Emits an `Approval` event.
         */
        function approve(address spender, uint256 amount) external returns (bool);
    
        /**
         * @dev Moves `amount` tokens from `sender` to `recipient` using the
         * allowance mechanism. `amount` is then deducted from the caller's
         * allowance.
         *
         * Returns a boolean value indicating whether the operation succeeded.
         *
         * Emits a `Transfer` event.
         */
        function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
    
        /**
         * @dev Emitted when `value` tokens are moved from one account (`from`) to
         * another (`to`).
         *
         * Note that `value` may be zero.
         */
        event Transfer(address indexed from, address indexed to, uint256 value);
    
        /**
         * @dev Emitted when the allowance of a `spender` for an `owner` is set by
         * a call to `approve`. `value` is the new allowance.
         */
        event Approval(address indexed owner, address indexed spender, uint256 value);
    }
    
    // File: contracts/openzeppelin-solidity/math/SafeMath.sol
    
    pragma solidity ^0.5.0;
    
    /**
     * @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) {
            require(b <= a, "SafeMath: subtraction overflow");
            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-solidity/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) {
            // Solidity only automatically asserts when dividing by 0
            require(b > 0, "SafeMath: division by zero");
            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) {
            require(b != 0, "SafeMath: modulo by zero");
            return a % b;
        }
    }
    
    // File: contracts/openzeppelin-solidity/token/ERC20/ERC20.sol
    
    pragma solidity ^0.5.0;
    
    
    
    /**
     * @dev Implementation of the `IERC20` interface.
     *
     * This implementation is agnostic to the way tokens are created. This means
     * that a supply mechanism has to be added in a derived contract using `_mint`.
     * For a generic mechanism see `ERC20Mintable`.
     *
     * *For a detailed writeup see our guide [How to implement supply
     * mechanisms](https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226).*
     *
     * We have followed general OpenZeppelin guidelines: functions revert instead
     * of returning `false` on failure. This behavior is nonetheless conventional
     * and does not conflict with the expectations of ERC20 applications.
     *
     * Additionally, an `Approval` event is emitted on calls to `transferFrom`.
     * This allows applications to reconstruct the allowance for all accounts just
     * by listening to said events. Other implementations of the EIP may not emit
     * these events, as it isn't required by the specification.
     *
     * Finally, the non-standard `decreaseAllowance` and `increaseAllowance`
     * functions have been added to mitigate the well-known issues around setting
     * allowances. See `IERC20.approve`.
     */
    contract ERC20 is IERC20 {
        using SafeMath for uint256;
    
        mapping (address => uint256) private _balances;
    
        mapping (address => mapping (address => uint256)) private _allowances;
    
        uint256 private _totalSupply;
    
        /**
         * @dev See `IERC20.totalSupply`.
         */
        function totalSupply() public view returns (uint256) {
            return _totalSupply;
        }
    
        /**
         * @dev See `IERC20.balanceOf`.
         */
        function balanceOf(address account) public view returns (uint256) {
            return _balances[account];
        }
    
        /**
         * @dev See `IERC20.transfer`.
         *
         * Requirements:
         *
         * - `recipient` cannot be the zero address.
         * - the caller must have a balance of at least `amount`.
         */
        function transfer(address recipient, uint256 amount) public returns (bool) {
            _transfer(msg.sender, recipient, amount);
            return true;
        }
    
        /**
         * @dev See `IERC20.allowance`.
         */
        function allowance(address owner, address spender) public view returns (uint256) {
            return _allowances[owner][spender];
        }
    
        /**
         * @dev See `IERC20.approve`.
         *
         * Requirements:
         *
         * - `spender` cannot be the zero address.
         */
        function approve(address spender, uint256 value) public returns (bool) {
            _approve(msg.sender, spender, value);
            return true;
        }
    
        /**
         * @dev See `IERC20.transferFrom`.
         *
         * Emits an `Approval` event indicating the updated allowance. This is not
         * required by the EIP. See the note at the beginning of `ERC20`;
         *
         * Requirements:
         * - `sender` and `recipient` cannot be the zero address.
         * - `sender` must have a balance of at least `value`.
         * - the caller must have allowance for `sender`'s tokens of at least
         * `amount`.
         */
        function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) {
            _transfer(sender, recipient, amount);
            _approve(sender, msg.sender, _allowances[sender][msg.sender].sub(amount));
            return true;
        }
    
        /**
         * @dev Atomically increases the allowance granted to `spender` by the caller.
         *
         * This is an alternative to `approve` that can be used as a mitigation for
         * problems described in `IERC20.approve`.
         *
         * Emits an `Approval` event indicating the updated allowance.
         *
         * Requirements:
         *
         * - `spender` cannot be the zero address.
         */
        function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
            _approve(msg.sender, spender, _allowances[msg.sender][spender].add(addedValue));
            return true;
        }
    
        /**
         * @dev Atomically decreases the allowance granted to `spender` by the caller.
         *
         * This is an alternative to `approve` that can be used as a mitigation for
         * problems described in `IERC20.approve`.
         *
         * Emits an `Approval` event indicating the updated allowance.
         *
         * Requirements:
         *
         * - `spender` cannot be the zero address.
         * - `spender` must have allowance for the caller of at least
         * `subtractedValue`.
         */
        function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
            _approve(msg.sender, spender, _allowances[msg.sender][spender].sub(subtractedValue));
            return true;
        }
    
        /**
         * @dev Moves tokens `amount` from `sender` to `recipient`.
         *
         * This is internal function is equivalent to `transfer`, and can be used to
         * e.g. implement automatic token fees, slashing mechanisms, etc.
         *
         * Emits a `Transfer` event.
         *
         * Requirements:
         *
         * - `sender` cannot be the zero address.
         * - `recipient` cannot be the zero address.
         * - `sender` must have a balance of at least `amount`.
         */
        function _transfer(address sender, address recipient, uint256 amount) internal {
            require(sender != address(0), "ERC20: transfer from the zero address");
            require(recipient != address(0), "ERC20: transfer to the zero address");
    
            _balances[sender] = _balances[sender].sub(amount);
            _balances[recipient] = _balances[recipient].add(amount);
            emit Transfer(sender, recipient, amount);
        }
    
        /** @dev Creates `amount` tokens and assigns them to `account`, increasing
         * the total supply.
         *
         * Emits a `Transfer` event with `from` set to the zero address.
         *
         * Requirements
         *
         * - `to` cannot be the zero address.
         */
        function _mint(address account, uint256 amount) internal {
            require(account != address(0), "ERC20: mint to the zero address");
    
            _totalSupply = _totalSupply.add(amount);
            _balances[account] = _balances[account].add(amount);
            emit Transfer(address(0), account, amount);
        }
    
         /**
         * @dev Destoys `amount` tokens from `account`, reducing the
         * total supply.
         *
         * Emits a `Transfer` event with `to` set to the zero address.
         *
         * Requirements
         *
         * - `account` cannot be the zero address.
         * - `account` must have at least `amount` tokens.
         */
        function _burn(address account, uint256 value) internal {
            require(account != address(0), "ERC20: burn from the zero address");
    
            _totalSupply = _totalSupply.sub(value);
            _balances[account] = _balances[account].sub(value);
            emit Transfer(account, address(0), value);
        }
    
        /**
         * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens.
         *
         * This is internal function is equivalent to `approve`, and can be used to
         * e.g. set automatic allowances for certain subsystems, etc.
         *
         * Emits an `Approval` event.
         *
         * Requirements:
         *
         * - `owner` cannot be the zero address.
         * - `spender` cannot be the zero address.
         */
        function _approve(address owner, address spender, uint256 value) internal {
            require(owner != address(0), "ERC20: approve from the zero address");
            require(spender != address(0), "ERC20: approve to the zero address");
    
            _allowances[owner][spender] = value;
            emit Approval(owner, spender, value);
        }
    
        /**
         * @dev Destoys `amount` tokens from `account`.`amount` is then deducted
         * from the caller's allowance.
         *
         * See `_burn` and `_approve`.
         */
        function _burnFrom(address account, uint256 amount) internal {
            _burn(account, amount);
            _approve(account, msg.sender, _allowances[account][msg.sender].sub(amount));
        }
    }
    
    // File: contracts/openzeppelin-solidity/access/Roles.sol
    
    pragma solidity ^0.5.0;
    
    /**
     * @title Roles
     * @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: contracts/openzeppelin-solidity/access/roles/MinterRole.sol
    
    pragma solidity ^0.5.0;
    
    
    contract MinterRole {
        using Roles for Roles.Role;
    
        event MinterAdded(address indexed account);
        event MinterRemoved(address indexed account);
    
        Roles.Role private _minters;
    
        constructor () internal {
            _addMinter(msg.sender);
        }
    
        modifier onlyMinter() {
            require(isMinter(msg.sender), "MinterRole: caller does not have the Minter role");
            _;
        }
    
        function isMinter(address account) public view returns (bool) {
            return _minters.has(account);
        }
    
        function addMinter(address account) public onlyMinter {
            _addMinter(account);
        }
    
        function renounceMinter() public {
            _removeMinter(msg.sender);
        }
    
        function _addMinter(address account) internal {
            _minters.add(account);
            emit MinterAdded(account);
        }
    
        function _removeMinter(address account) internal {
            _minters.remove(account);
            emit MinterRemoved(account);
        }
    }
    
    // File: contracts/openzeppelin-solidity/token/ERC20/ERC20Mintable.sol
    
    pragma solidity ^0.5.0;
    
    
    
    /**
     * @dev Extension of `ERC20` that adds a set of accounts with the `MinterRole`,
     * which have permission to mint (create) new tokens as they see fit.
     *
     * At construction, the deployer of the contract is the only minter.
     */
    contract ERC20Mintable is ERC20, MinterRole {
        /**
         * @dev See `ERC20._mint`.
         *
         * Requirements:
         *
         * - the caller must have the `MinterRole`.
         */
        function mint(address account, uint256 amount) public onlyMinter returns (bool) {
            _mint(account, amount);
            return true;
        }
    }
    
    // File: contracts/openzeppelin-solidity/ownership/Secondary.sol
    
    pragma solidity ^0.5.0;
    
    /**
     * @dev A Secondary contract can only be used by its primary account (the one that created it).
     */
    contract Secondary {
        address private _primary;
    
        /**
         * @dev Emitted when the primary contract changes.
         */
        event PrimaryTransferred(
            address recipient
        );
    
        /**
         * @dev Sets the primary account to the one that is creating the Secondary contract.
         */
        constructor () internal {
            _primary = msg.sender;
            emit PrimaryTransferred(_primary);
        }
    
        /**
         * @dev Reverts if called from any account other than the primary.
         */
        modifier onlyPrimary() {
            require(msg.sender == _primary, "Secondary: caller is not the primary account");
            _;
        }
    
        /**
         * @return the address of the primary.
         */
        function primary() public view returns (address) {
            return _primary;
        }
    
        /**
         * @dev Transfers contract to a new primary.
         * @param recipient The address of new primary.
         */
        function transferPrimary(address recipient) public onlyPrimary {
            require(recipient != address(0), "Secondary: new primary is the zero address");
            _primary = recipient;
            emit PrimaryTransferred(_primary);
        }
    }
    
    // File: contracts/TONVault.sol
    
    pragma solidity ^0.5.0;
    
    
    
    
    contract TONVault is Secondary {
        using SafeMath for uint256;
    
        ERC20Mintable public ton;
    
        constructor (ERC20Mintable tonToken) public {
            ton = tonToken;
        }
    
        function setApprovalAmount(address approval, uint256 amount) public onlyPrimary {
            ton.approve(approval, amount);
        }
        
        function withdraw(uint256 amount, address recipient) public onlyPrimary {
            ton.transfer(recipient, amount);
        }
    }

    File 4 of 4: TON
    // File: openzeppelin-solidity/contracts/GSN/Context.sol
    
    pragma solidity ^0.5.0;
    
    /*
     * @dev Provides information about the current execution context, including the
     * sender of the transaction and its data. While these are generally available
     * via msg.sender and msg.data, they should not be accessed in such a direct
     * manner, since when dealing with GSN meta-transactions the account sending and
     * paying for execution may not be the actual sender (as far as an application
     * is concerned).
     *
     * This contract is only required for intermediate, library-like contracts.
     */
    contract Context {
        // Empty internal constructor, to prevent people from mistakenly deploying
        // an instance of this contract, which should be used via inheritance.
        constructor () internal { }
        // solhint-disable-previous-line no-empty-blocks
    
        function _msgSender() internal view returns (address payable) {
            return msg.sender;
        }
    
        function _msgData() internal view returns (bytes memory) {
            this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
            return msg.data;
        }
    }
    
    // File: openzeppelin-solidity/contracts/ownership/Ownable.sol
    
    pragma solidity ^0.5.0;
    
    /**
     * @dev Contract module which provides a basic access control mechanism, where
     * there is an account (an owner) that can be granted exclusive access to
     * specific functions.
     *
     * This module is used through inheritance. It will make available the modifier
     * `onlyOwner`, which can be applied to your functions to restrict their use to
     * the owner.
     */
    contract Ownable is Context {
        address private _owner;
    
        event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
    
        /**
         * @dev Initializes the contract setting the deployer as the initial owner.
         */
        constructor () internal {
            address msgSender = _msgSender();
            _owner = msgSender;
            emit OwnershipTransferred(address(0), msgSender);
        }
    
        /**
         * @dev Returns the address of the current owner.
         */
        function owner() public view returns (address) {
            return _owner;
        }
    
        /**
         * @dev Throws if called by any account other than the owner.
         */
        modifier onlyOwner() {
            require(isOwner(), "Ownable: caller is not the owner");
            _;
        }
    
        /**
         * @dev Returns true if the caller is the current owner.
         */
        function isOwner() public view returns (bool) {
            return _msgSender() == _owner;
        }
    
        /**
         * @dev Leaves the contract without owner. It will not be possible to call
         * `onlyOwner` functions anymore. Can only be called by the current owner.
         *
         * NOTE: Renouncing ownership will leave the contract without an owner,
         * thereby removing any functionality that is only available to the owner.
         */
        function renounceOwnership() public onlyOwner {
            emit OwnershipTransferred(_owner, address(0));
            _owner = address(0);
        }
    
        /**
         * @dev Transfers ownership of the contract to a new account (`newOwner`).
         * Can only be called by the current owner.
         */
        function transferOwnership(address newOwner) public onlyOwner {
            _transferOwnership(newOwner);
        }
    
        /**
         * @dev Transfers ownership of the contract to a new account (`newOwner`).
         */
        function _transferOwnership(address newOwner) internal {
            require(newOwner != address(0), "Ownable: new owner is the zero address");
            emit OwnershipTransferred(_owner, newOwner);
            _owner = newOwner;
        }
    }
    
    // File: openzeppelin-solidity/contracts/token/ERC20/IERC20.sol
    
    pragma solidity ^0.5.0;
    
    /**
     * @dev Interface of the ERC20 standard as defined in the EIP. Does not include
     * the optional functions; to access them see {ERC20Detailed}.
     */
    interface IERC20 {
        /**
         * @dev Returns the amount of tokens in existence.
         */
        function totalSupply() external view returns (uint256);
    
        /**
         * @dev Returns the amount of tokens owned by `account`.
         */
        function balanceOf(address account) external view returns (uint256);
    
        /**
         * @dev Moves `amount` tokens from the caller's account to `recipient`.
         *
         * Returns a boolean value indicating whether the operation succeeded.
         *
         * Emits a {Transfer} event.
         */
        function transfer(address recipient, uint256 amount) external returns (bool);
    
        /**
         * @dev Returns the remaining number of tokens that `spender` will be
         * allowed to spend on behalf of `owner` through {transferFrom}. This is
         * zero by default.
         *
         * This value changes when {approve} or {transferFrom} are called.
         */
        function allowance(address owner, address spender) external view returns (uint256);
    
        /**
         * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
         *
         * Returns a boolean value indicating whether the operation succeeded.
         *
         * IMPORTANT: Beware that changing an allowance with this method brings the risk
         * that someone may use both the old and the new allowance by unfortunate
         * transaction ordering. One possible solution to mitigate this race
         * condition is to first reduce the spender's allowance to 0 and set the
         * desired value afterwards:
         * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
         *
         * Emits an {Approval} event.
         */
        function approve(address spender, uint256 amount) external returns (bool);
    
        /**
         * @dev Moves `amount` tokens from `sender` to `recipient` using the
         * allowance mechanism. `amount` is then deducted from the caller's
         * allowance.
         *
         * Returns a boolean value indicating whether the operation succeeded.
         *
         * Emits a {Transfer} event.
         */
        function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
    
        /**
         * @dev Emitted when `value` tokens are moved from one account (`from`) to
         * another (`to`).
         *
         * Note that `value` may be zero.
         */
        event Transfer(address indexed from, address indexed to, uint256 value);
    
        /**
         * @dev Emitted when the allowance of a `spender` for an `owner` is set by
         * a call to {approve}. `value` is the new allowance.
         */
        event Approval(address indexed owner, address indexed spender, uint256 value);
    }
    
    // File: openzeppelin-solidity/contracts/math/SafeMath.sol
    
    pragma solidity ^0.5.0;
    
    /**
     * @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.
         *
         * _Available since v2.4.0._
         */
        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.
         *
         * _Available since v2.4.0._
         */
        function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
            // Solidity only automatically asserts when dividing by 0
            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.
         *
         * _Available since v2.4.0._
         */
        function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
            require(b != 0, errorMessage);
            return a % b;
        }
    }
    
    // File: openzeppelin-solidity/contracts/token/ERC20/ERC20.sol
    
    pragma solidity ^0.5.0;
    
    
    
    
    /**
     * @dev Implementation of the {IERC20} interface.
     *
     * This implementation is agnostic to the way tokens are created. This means
     * that a supply mechanism has to be added in a derived contract using {_mint}.
     * For a generic mechanism see {ERC20Mintable}.
     *
     * TIP: For a detailed writeup see our guide
     * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
     * to implement supply mechanisms].
     *
     * We have followed general OpenZeppelin guidelines: functions revert instead
     * of returning `false` on failure. This behavior is nonetheless conventional
     * and does not conflict with the expectations of ERC20 applications.
     *
     * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
     * This allows applications to reconstruct the allowance for all accounts just
     * by listening to said events. Other implementations of the EIP may not emit
     * these events, as it isn't required by the specification.
     *
     * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
     * functions have been added to mitigate the well-known issues around setting
     * allowances. See {IERC20-approve}.
     */
    contract ERC20 is Context, IERC20 {
        using SafeMath for uint256;
    
        mapping (address => uint256) private _balances;
    
        mapping (address => mapping (address => uint256)) private _allowances;
    
        uint256 private _totalSupply;
    
        /**
         * @dev See {IERC20-totalSupply}.
         */
        function totalSupply() public view returns (uint256) {
            return _totalSupply;
        }
    
        /**
         * @dev See {IERC20-balanceOf}.
         */
        function balanceOf(address account) public view returns (uint256) {
            return _balances[account];
        }
    
        /**
         * @dev See {IERC20-transfer}.
         *
         * Requirements:
         *
         * - `recipient` cannot be the zero address.
         * - the caller must have a balance of at least `amount`.
         */
        function transfer(address recipient, uint256 amount) public returns (bool) {
            _transfer(_msgSender(), recipient, amount);
            return true;
        }
    
        /**
         * @dev See {IERC20-allowance}.
         */
        function allowance(address owner, address spender) public view returns (uint256) {
            return _allowances[owner][spender];
        }
    
        /**
         * @dev See {IERC20-approve}.
         *
         * Requirements:
         *
         * - `spender` cannot be the zero address.
         */
        function approve(address spender, uint256 amount) public returns (bool) {
            _approve(_msgSender(), spender, amount);
            return true;
        }
    
        /**
         * @dev See {IERC20-transferFrom}.
         *
         * Emits an {Approval} event indicating the updated allowance. This is not
         * required by the EIP. See the note at the beginning of {ERC20};
         *
         * Requirements:
         * - `sender` and `recipient` cannot be the zero address.
         * - `sender` must have a balance of at least `amount`.
         * - the caller must have allowance for `sender`'s tokens of at least
         * `amount`.
         */
        function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) {
            _transfer(sender, recipient, amount);
            _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
            return true;
        }
    
        /**
         * @dev Atomically increases the allowance granted to `spender` by the caller.
         *
         * This is an alternative to {approve} that can be used as a mitigation for
         * problems described in {IERC20-approve}.
         *
         * Emits an {Approval} event indicating the updated allowance.
         *
         * Requirements:
         *
         * - `spender` cannot be the zero address.
         */
        function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
            _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
            return true;
        }
    
        /**
         * @dev Atomically decreases the allowance granted to `spender` by the caller.
         *
         * This is an alternative to {approve} that can be used as a mitigation for
         * problems described in {IERC20-approve}.
         *
         * Emits an {Approval} event indicating the updated allowance.
         *
         * Requirements:
         *
         * - `spender` cannot be the zero address.
         * - `spender` must have allowance for the caller of at least
         * `subtractedValue`.
         */
        function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
            _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
            return true;
        }
    
        /**
         * @dev Moves tokens `amount` from `sender` to `recipient`.
         *
         * This is internal function is equivalent to {transfer}, and can be used to
         * e.g. implement automatic token fees, slashing mechanisms, etc.
         *
         * Emits a {Transfer} event.
         *
         * Requirements:
         *
         * - `sender` cannot be the zero address.
         * - `recipient` cannot be the zero address.
         * - `sender` must have a balance of at least `amount`.
         */
        function _transfer(address sender, address recipient, uint256 amount) internal {
            require(sender != address(0), "ERC20: transfer from the zero address");
            require(recipient != address(0), "ERC20: transfer to the zero address");
    
            _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
            _balances[recipient] = _balances[recipient].add(amount);
            emit Transfer(sender, recipient, amount);
        }
    
        /** @dev Creates `amount` tokens and assigns them to `account`, increasing
         * the total supply.
         *
         * Emits a {Transfer} event with `from` set to the zero address.
         *
         * Requirements
         *
         * - `to` cannot be the zero address.
         */
        function _mint(address account, uint256 amount) internal {
            require(account != address(0), "ERC20: mint to the zero address");
    
            _totalSupply = _totalSupply.add(amount);
            _balances[account] = _balances[account].add(amount);
            emit Transfer(address(0), account, amount);
        }
    
        /**
         * @dev Destroys `amount` tokens from `account`, reducing the
         * total supply.
         *
         * Emits a {Transfer} event with `to` set to the zero address.
         *
         * Requirements
         *
         * - `account` cannot be the zero address.
         * - `account` must have at least `amount` tokens.
         */
        function _burn(address account, uint256 amount) internal {
            require(account != address(0), "ERC20: burn from the zero address");
    
            _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
            _totalSupply = _totalSupply.sub(amount);
            emit Transfer(account, address(0), amount);
        }
    
        /**
         * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens.
         *
         * This is internal function is equivalent to `approve`, and can be used to
         * e.g. set automatic allowances for certain subsystems, etc.
         *
         * Emits an {Approval} event.
         *
         * Requirements:
         *
         * - `owner` cannot be the zero address.
         * - `spender` cannot be the zero address.
         */
        function _approve(address owner, address spender, uint256 amount) internal {
            require(owner != address(0), "ERC20: approve from the zero address");
            require(spender != address(0), "ERC20: approve to the zero address");
    
            _allowances[owner][spender] = amount;
            emit Approval(owner, spender, amount);
        }
    
        /**
         * @dev Destroys `amount` tokens from `account`.`amount` is then deducted
         * from the caller's allowance.
         *
         * See {_burn} and {_approve}.
         */
        function _burnFrom(address account, uint256 amount) internal {
            _burn(account, amount);
            _approve(account, _msgSender(), _allowances[account][_msgSender()].sub(amount, "ERC20: burn amount exceeds allowance"));
        }
    }
    
    // File: openzeppelin-solidity/contracts/access/Roles.sol
    
    pragma solidity ^0.5.0;
    
    /**
     * @title Roles
     * @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: openzeppelin-solidity/contracts/access/roles/MinterRole.sol
    
    pragma solidity ^0.5.0;
    
    
    
    contract MinterRole is Context {
        using Roles for Roles.Role;
    
        event MinterAdded(address indexed account);
        event MinterRemoved(address indexed account);
    
        Roles.Role private _minters;
    
        constructor () internal {
            _addMinter(_msgSender());
        }
    
        modifier onlyMinter() {
            require(isMinter(_msgSender()), "MinterRole: caller does not have the Minter role");
            _;
        }
    
        function isMinter(address account) public view returns (bool) {
            return _minters.has(account);
        }
    
        function addMinter(address account) public onlyMinter {
            _addMinter(account);
        }
    
        function renounceMinter() public {
            _removeMinter(_msgSender());
        }
    
        function _addMinter(address account) internal {
            _minters.add(account);
            emit MinterAdded(account);
        }
    
        function _removeMinter(address account) internal {
            _minters.remove(account);
            emit MinterRemoved(account);
        }
    }
    
    // File: openzeppelin-solidity/contracts/token/ERC20/ERC20Mintable.sol
    
    pragma solidity ^0.5.0;
    
    
    
    /**
     * @dev Extension of {ERC20} that adds a set of accounts with the {MinterRole},
     * which have permission to mint (create) new tokens as they see fit.
     *
     * At construction, the deployer of the contract is the only minter.
     */
    contract ERC20Mintable is ERC20, MinterRole {
        /**
         * @dev See {ERC20-_mint}.
         *
         * Requirements:
         *
         * - the caller must have the {MinterRole}.
         */
        function mint(address account, uint256 amount) public onlyMinter returns (bool) {
            _mint(account, amount);
            return true;
        }
    }
    
    // File: openzeppelin-solidity/contracts/token/ERC20/ERC20Detailed.sol
    
    pragma solidity ^0.5.0;
    
    
    /**
     * @dev Optional functions from the ERC20 standard.
     */
    contract ERC20Detailed is IERC20 {
        string private _name;
        string private _symbol;
        uint8 private _decimals;
    
        /**
         * @dev Sets the values for `name`, `symbol`, and `decimals`. All three of
         * these values are immutable: they can only be set once during
         * construction.
         */
        constructor (string memory name, string memory symbol, uint8 decimals) public {
            _name = name;
            _symbol = symbol;
            _decimals = decimals;
        }
    
        /**
         * @dev Returns the name of the token.
         */
        function name() public view returns (string memory) {
            return _name;
        }
    
        /**
         * @dev Returns the symbol of the token, usually a shorter version of the
         * name.
         */
        function symbol() public view returns (string memory) {
            return _symbol;
        }
    
        /**
         * @dev Returns the number of decimals used to get its user representation.
         * For example, if `decimals` equals `2`, a balance of `505` tokens should
         * be displayed to a user as `5,05` (`505 / 10 ** 2`).
         *
         * Tokens usually opt for a value of 18, imitating the relationship between
         * Ether and Wei.
         *
         * NOTE: This information is only used for _display_ purposes: it in
         * no way affects any of the arithmetic of the contract, including
         * {IERC20-balanceOf} and {IERC20-transfer}.
         */
        function decimals() public view returns (uint8) {
            return _decimals;
        }
    }
    
    // File: openzeppelin-solidity/contracts/introspection/ERC165Checker.sol
    
    pragma solidity ^0.5.10;
    
    /**
     * @dev Library used to query support of an interface declared via {IERC165}.
     *
     * Note that these functions return the actual result of the query: they do not
     * `revert` if an interface is not supported. It is up to the caller to decide
     * what to do in these cases.
     */
    library ERC165Checker {
        // As per the EIP-165 spec, no interface should ever match 0xffffffff
        bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;
    
        /*
         * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7
         */
        bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;
    
        /**
         * @dev Returns true if `account` supports the {IERC165} interface,
         */
        function _supportsERC165(address account) internal view returns (bool) {
            // Any contract that implements ERC165 must explicitly indicate support of
            // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid
            return _supportsERC165Interface(account, _INTERFACE_ID_ERC165) &&
                !_supportsERC165Interface(account, _INTERFACE_ID_INVALID);
        }
    
        /**
         * @dev Returns true if `account` supports the interface defined by
         * `interfaceId`. Support for {IERC165} itself is queried automatically.
         *
         * See {IERC165-supportsInterface}.
         */
        function _supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {
            // query support of both ERC165 as per the spec and support of _interfaceId
            return _supportsERC165(account) &&
                _supportsERC165Interface(account, interfaceId);
        }
    
        /**
         * @dev Returns true if `account` supports all the interfaces defined in
         * `interfaceIds`. Support for {IERC165} itself is queried automatically.
         *
         * Batch-querying can lead to gas savings by skipping repeated checks for
         * {IERC165} support.
         *
         * See {IERC165-supportsInterface}.
         */
        function _supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {
            // query support of ERC165 itself
            if (!_supportsERC165(account)) {
                return false;
            }
    
            // query support of each interface in _interfaceIds
            for (uint256 i = 0; i < interfaceIds.length; i++) {
                if (!_supportsERC165Interface(account, interfaceIds[i])) {
                    return false;
                }
            }
    
            // all interfaces supported
            return true;
        }
    
        /**
         * @notice Query if a contract implements an interface, does not check ERC165 support
         * @param account The address of the contract to query for support of an interface
         * @param interfaceId The interface identifier, as specified in ERC-165
         * @return true if the contract at account indicates support of the interface with
         * identifier interfaceId, false otherwise
         * @dev Assumes that account contains a contract that supports ERC165, otherwise
         * the behavior of this method is undefined. This precondition can be checked
         * with the `supportsERC165` method in this library.
         * Interface identification is specified in ERC-165.
         */
        function _supportsERC165Interface(address account, bytes4 interfaceId) private view returns (bool) {
            // success determines whether the staticcall succeeded and result determines
            // whether the contract at account indicates support of _interfaceId
            (bool success, bool result) = _callERC165SupportsInterface(account, interfaceId);
    
            return (success && result);
        }
    
        /**
         * @notice Calls the function with selector 0x01ffc9a7 (ERC165) and suppresses throw
         * @param account The address of the contract to query for support of an interface
         * @param interfaceId The interface identifier, as specified in ERC-165
         * @return success true if the STATICCALL succeeded, false otherwise
         * @return result true if the STATICCALL succeeded and the contract at account
         * indicates support of the interface with identifier interfaceId, false otherwise
         */
        function _callERC165SupportsInterface(address account, bytes4 interfaceId)
            private
            view
            returns (bool, bool)
        {
            bytes memory encodedParams = abi.encodeWithSelector(_INTERFACE_ID_ERC165, interfaceId);
            (bool success, bytes memory result) = account.staticcall.gas(30000)(encodedParams);
            if (result.length < 32) return (false, false);
            return (success, abi.decode(result, (bool)));
        }
    }
    
    // File: contracts/stake/interfaces/SeigManagerI.sol
    
    pragma solidity ^0.5.12;
    
    
    interface SeigManagerI {
      function registry() external view returns (address);
      function depositManager() external view returns (address);
      function ton() external view returns (address);
      function wton() external view returns (address);
      function powerton() external view returns (address);
      function tot() external view returns (address);
      function coinages(address rootchain) external view returns (address);
      function commissionRates(address rootchain) external view returns (uint256);
    
      function lastCommitBlock(address rootchain) external view returns (uint256);
      function seigPerBlock() external view returns (uint256);
      function lastSeigBlock() external view returns (uint256);
      function pausedBlock() external view returns (uint256);
      function unpausedBlock() external view returns (uint256);
      function DEFAULT_FACTOR() external view returns (uint256);
    
      function deployCoinage(address rootchain) external returns (bool);
      function setCommissionRate(address rootchain, uint256 commission, bool isCommissionRateNegative) external returns (bool);
    
      function uncomittedStakeOf(address rootchain, address account) external view returns (uint256);
      function stakeOf(address rootchain, address account) external view returns (uint256);
      function additionalTotBurnAmount(address rootchain, address account, uint256 amount) external view returns (uint256 totAmount);
    
      function onTransfer(address sender, address recipient, uint256 amount) external returns (bool);
      function onCommit() external returns (bool);
      function onDeposit(address rootchain, address account, uint256 amount) external returns (bool);
      function onWithdraw(address rootchain, address account, uint256 amount) external returns (bool);
    
    }
    
    // File: openzeppelin-solidity/contracts/introspection/IERC165.sol
    
    pragma solidity ^0.5.0;
    
    /**
     * @dev Interface of the ERC165 standard, as defined in the
     * https://eips.ethereum.org/EIPS/eip-165[EIP].
     *
     * Implementers can declare support of contract interfaces, which can then be
     * queried by others ({ERC165Checker}).
     *
     * For an implementation, see {ERC165}.
     */
    interface IERC165 {
        /**
         * @dev Returns true if this contract implements the interface defined by
         * `interfaceId`. See the corresponding
         * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
         * to learn more about how these ids are created.
         *
         * This function call must use less than 30 000 gas.
         */
        function supportsInterface(bytes4 interfaceId) external view returns (bool);
    }
    
    // File: openzeppelin-solidity/contracts/introspection/ERC165.sol
    
    pragma solidity ^0.5.0;
    
    
    /**
     * @dev Implementation of the {IERC165} interface.
     *
     * Contracts may inherit from this and call {_registerInterface} to declare
     * their support of an interface.
     */
    contract ERC165 is IERC165 {
        /*
         * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7
         */
        bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;
    
        /**
         * @dev Mapping of interface ids to whether or not it's supported.
         */
        mapping(bytes4 => bool) private _supportedInterfaces;
    
        constructor () internal {
            // Derived contracts need only register support for their own interfaces,
            // we register support for ERC165 itself here
            _registerInterface(_INTERFACE_ID_ERC165);
        }
    
        /**
         * @dev See {IERC165-supportsInterface}.
         *
         * Time complexity O(1), guaranteed to always use less than 30 000 gas.
         */
        function supportsInterface(bytes4 interfaceId) external view returns (bool) {
            return _supportedInterfaces[interfaceId];
        }
    
        /**
         * @dev Registers the contract as an implementer of the interface defined by
         * `interfaceId`. Support of the actual ERC165 interface is automatic and
         * registering its interface id is not required.
         *
         * See {IERC165-supportsInterface}.
         *
         * Requirements:
         *
         * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).
         */
        function _registerInterface(bytes4 interfaceId) internal {
            require(interfaceId != 0xffffffff, "ERC165: invalid interface id");
            _supportedInterfaces[interfaceId] = true;
        }
    }
    
    // File: contracts/stake/tokens/OnApprove.sol
    
    pragma solidity ^0.5.12;
    
    
    contract OnApprove is ERC165 {
      constructor() public {
        _registerInterface(OnApprove(this).onApprove.selector);
      }
    
      function onApprove(address owner, address spender, uint256 amount, bytes calldata data) external returns (bool);
    }
    
    // File: contracts/stake/tokens/ERC20OnApprove.sol
    
    pragma solidity ^0.5.12;
    
    
    
    
    
    contract ERC20OnApprove is ERC20 {
      function approveAndCall(address spender, uint256 amount, bytes memory data) public returns (bool) {
        require(approve(spender, amount));
        _callOnApprove(msg.sender, spender, amount, data);
        return true;
      }
    
      function _callOnApprove(address owner, address spender, uint256 amount, bytes memory data) internal {
        bytes4 onApproveSelector = OnApprove(spender).onApprove.selector;
    
        require(ERC165Checker._supportsInterface(spender, onApproveSelector),
          "ERC20OnApprove: spender doesn't support onApprove");
    
        (bool ok, bytes memory res) = spender.call(
          abi.encodeWithSelector(
            onApproveSelector,
            owner,
            spender,
            amount,
            data
          )
        );
    
        // check if low-level call reverted or not
        require(ok, string(res));
    
        assembly {
          ok := mload(add(res, 0x20))
        }
    
        // check if OnApprove.onApprove returns true or false
        require(ok, "ERC20OnApprove: failed to call onApprove");
      }
    
    }
    
    // File: contracts/stake/tokens/AuthController.sol
    
    pragma solidity ^0.5.12;
    
    
    
    interface MinterRoleRenounceTarget {
      function renounceMinter() external;
    }
    
    interface PauserRoleRenounceTarget {
      function renouncePauser() external;
    }
    
    interface OwnableTarget {
      function renounceOwnership() external;
      function transferOwnership(address newOwner) external;
    }
    
    contract AuthController is Ownable {
      function renounceMinter(address target) public onlyOwner {
        MinterRoleRenounceTarget(target).renounceMinter();
      }
    
      function renouncePauser(address target) public onlyOwner {
        PauserRoleRenounceTarget(target).renouncePauser();
      }
    
      function renounceOwnership(address target) public onlyOwner {
        OwnableTarget(target).renounceOwnership();
      }
    
      function transferOwnership(address target, address newOwner) public onlyOwner {
        OwnableTarget(target).transferOwnership(newOwner);
      }
    }
    
    // File: contracts/stake/tokens/SeigToken.sol
    
    pragma solidity ^0.5.12;
    
    
    
    
    
    
    
    contract SeigToken is ERC20, Ownable, ERC20OnApprove, AuthController {
      SeigManagerI public seigManager;
      bool public callbackEnabled;
    
      function enableCallback(bool _callbackEnabled) external onlyOwner {
        callbackEnabled = _callbackEnabled;
      }
    
      function setSeigManager(SeigManagerI _seigManager) external onlyOwner {
        seigManager = _seigManager;
      }
    
      //////////////////////
      // Override ERC20 functions
      //////////////////////
    
      function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) {
        require(msg.sender == sender || msg.sender == recipient, "SeigToken: only sender or recipient can transfer");
        return super.transferFrom(sender, recipient, amount);
      }
    
      function _transfer(address sender, address recipient, uint256 amount) internal {
        super._transfer(sender, recipient, amount);
        if (callbackEnabled && address(seigManager) != address(0)) {
          require(seigManager.onTransfer(sender, recipient, amount));
        }
      }
    
      function _mint(address account, uint256 amount) internal {
        super._mint(account, amount);
        if (callbackEnabled && address(seigManager) != address(0)) {
          require(seigManager.onTransfer(address(0), account, amount));
        }
      }
    
      function _burn(address account, uint256 amount) internal {
        super._burn(account, amount);
        if (callbackEnabled && address(seigManager) != address(0)) {
          require(seigManager.onTransfer(account, address(0), amount));
        }
      }
    }
    
    // File: contracts/stake/tokens/TON.sol
    
    pragma solidity ^0.5.12;
    
    
    
    
    
    
    
    
    /**
     * @dev Current implementations is just for testing seigniorage manager.
     */
    contract TON is Ownable, ERC20Mintable, ERC20Detailed, SeigToken {
      constructor() public ERC20Detailed("Tokamak Network Token", "TON", 18) {}
    
      function setSeigManager(SeigManagerI _seigManager) external {
        revert("TON: TON doesn't allow setSeigManager");
      }
    }