contract XMT is Token {
    // The address of Pair contract
    PairContract public pairInstance;
    /// @notice revoking rate precise
    /// @notice for example: RATE_PRECISE is 3, meaning that the revoking fee ratio is 3/10000
    uint public rate = 10000;  // default rate is 1:1
    uint public constant RATE_PRECISE = 10000;

    // events
    event ExchangePair(address indexed from, uint256 value);
    event SetPairContract(address PairToken);
    event RateChanged(uint256 previousOwner,uint256 newRate);

    /**
     * @dev Throws if called by any account other than the Pair contract
     */
    modifier onlyPairContract() {
        require(msg.sender == address(pairInstance));
        _;
    }

    /**
     * @dev Sets the address of pair contract
     */
    function setPairContract(address pairAddress) public onlyOwner {
        require(pairAddress != address(0));
        pairInstance = PairContract(pairAddress);
        emit SetPairContract(pairAddress);
    }

    /**
     * @dev Function Set the exchange rate of pair token.
     * for example: RATE_PRECISE is 300, means that the rate is 300/10000: 1 PT = 0.003 XMT
     * for example: RATE_PRECISE is 30000, means that the rate is 30000/10000: 1 PT = 3 XMT
     */
     function setRate(uint256 _newRate) public onlyOwner {
        require(_newRate > 0);
        emit RateChanged(rate,_newRate);
        rate = _newRate;
     }

    /**
     * @dev Transfers token to a specified address.
     *      If the target address of transferring is Pair contract, the operation of changing Pair tokens will be executed.
     * @param to The target address of transfer, which may be the  contract
     * @param value The amount of tokens transferred
     */
    function transfer(address to, uint value) public returns (bool) {
        super.transfer(to, value); // Transfers tokens to address 'to'
        if(to == address(pairInstance)) {
            pairInstance.tokenFallback(msg.sender, value, bytes("")); // Calls 'tokenFallback' function in Pair contract to exchange tokens
            emit ExchangePair(msg.sender, value);
        }
        return true;
    }

    /**
     * @dev Transfers tokens from one address to another.
     *      If the target address of transferring is  Pair contract, the operation of changing Pair tokens will be executed.
     * @param from The address which you want to send tokens from
     * @param to The address which you want to transfer to
     * @param value The amount of tokens to be transferred
     */
    function transferFrom(address from, address to, uint value) public returns (bool) {
        super.transferFrom(from, to, value); // Transfers token to address 'to'
        if(to == address(pairInstance)) {
            pairInstance.tokenFallback(from, value, bytes("")); // Calls 'tokenFallback' function in Pair contract to exchange tokens
            emit ExchangePair(from, value);
        }
        return true;
    }

    /**
     * @dev Function that is called by the Pair contract to exchange 'XMT' tokens
     */
    function tokenFallback(address from, uint256 value, bytes calldata) external onlyPairContract {
        require(from != address(0));
        require(value != uint256(0));
        require(pairInstance.transfer(owner,value)); // Transfers Pair tokens belonging to this contract to 'owner'
        uint256 XMTValue = value.mul(10**uint256(decimals)).mul(rate).div(RATE_PRECISE).div(10**uint256(pairInstance.decimals())); // Calculates the number of 'XMT' tokens that can be exchanged
        require(XMTValue <= balances[owner]);
        balances[owner] = balances[owner].sub(XMTValue);
        balances[from] = balances[from].add(XMTValue); 
        emit Transfer(owner, from, XMTValue);
    }
    
    /**
     * @dev Function that is used to withdraw the 'Pair' tokens in this contract
     */
    function withdrawToken(uint256 value) public onlyOwner {
        require(pairInstance.transfer(owner,value));
    }    
}
function transfer(address to, uint value) public returns (bool) {
    super.transfer(to, value); // Transfers tokens to address 'to'
    if(to == address(pairInstance)) {
        pairInstance.tokenFallback(msg.sender, value, bytes("")); // Calls 'tokenFallback' function in Pair contract to exchange tokens
        emit ExchangePair(msg.sender, value);
    }
    return true;
}

/**
 * @dev Transfers token to a specified address.
 *      If the target address of transferring is Pair contract, the operation of changing Pair tokens will be executed.
 * @param to The target address of transfer, which may be the  contract
 * @param value The amount of tokens transferred
 */