contract DGT is Ownable, IERC20, MinterRole, ERC20Detailed {
    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.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 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));
    }

    using SafeMath for uint;
    uint public txFeePerMillion = 0;
    uint256 public INITIAL_SUPPLY = 1000000*(10**8);
    DgtFeePool public feePool;

    constructor() public ERC20Detailed("Digold Token", "DGT", 8) {
        _totalSupply = INITIAL_SUPPLY;
        _balances[msg.sender] = INITIAL_SUPPLY;
    }

    modifier onlySender(address _sender) {
        require(msg.sender == _sender);
        _;
    }

    function setTxFee(uint _value) external onlyOwner returns (bool) {
        txFeePerMillion = _value;
        return true;
    }

    /**
    * @dev Set the fee pool to a specified address
    * @param _feePool The FeePool contract address
    */

    function setFeePool(address _feePool) external onlyOwner returns (bool) {
        require(_feePool != address(0));

        feePool = DgtFeePool(_feePool);
        return true;
    }

    /**
    * @dev Change the fee pool to a specified address. Transfer the balance of current fee pool to the new one.
    * @param _newFeePool The new FeePool contract address
    */

    function changeFeePool(address _newFeePool) external onlyOwner returns (bool) {
        require(address(feePool) != address(0), "no FeePool set yet");
        require(_newFeePool != address(0));
        require(_balances[_newFeePool] == 0);

        uint256 currentPoolBalance = _balances[address(feePool)];
        delete _balances[address(feePool)];
        feePool = DgtFeePool(_newFeePool);
        _balances[_newFeePool] = currentPoolBalance;

        return true;
    }

    // Fee pool transfer doesn't pay fee again.
    function feePoolTransfer(address _to, uint256 _value) external onlySender(address(feePool)) returns (bool) {
        require(_to != address(0));
        require(_value <= _balances[msg.sender]);

        _transfer(msg.sender, _to, _value);
        return true;
    }


    /**
    * @dev Transfer tokens to a specified address after diverting a fee to a central account.
    * @param _to The receiving address.
    * @param _value The number of tokens to transfer.
    */
    function transfer(address _to, uint256 _value) public returns (bool) {
        require(_to != address(0));
        require(_value <= _balances[msg.sender]);

        uint256 fee = _value.mul(txFeePerMillion).div(10**6);
        uint256 taxedValue = _value.sub(fee);

        // SafeMath.sub will throw if there is not enough balance.
        _transfer(msg.sender, _to, taxedValue);

        if (address(feePool) != address(0)) {
            _balances[address(feePool)] = _balances[address(feePool)].add(fee);
            emit Transfer(msg.sender, address(feePool), fee);
            if (msg.sender != owner()) {
                feePool.notifyTx(msg.sender, _value);
            } 
        }
        return true;
    }


    /**
    * @dev Transfer tokens from one address to another
    * @param _from address The address which you want to send tokens from
    * @param _to address The address which you want to transfer to
    * @param _value uint256 the amount of tokens to be transferred
    */
    function transferFrom(
        address _from,
        address _to,
        uint256 _value
    )
        public
        returns (bool)
    {
        require(_to != address(0));
        require(_value <= _balances[_from]);
        require(_value <= _allowances[_from][msg.sender]);

        uint256 fee = _value.mul(txFeePerMillion).div(10**6);
        uint256 taxedValue = _value.sub(fee);

        _balances[_from] = _balances[_from].sub(_value);
        _balances[_to] = _balances[_to].add(taxedValue);
        _allowances[_from][msg.sender] = _allowances[_from][msg.sender].sub(_value);
        emit Transfer(_from, _to, _value);
        
        if (address(feePool) != address(0)) {
            _balances[address(feePool)] = _balances[address(feePool)].add(fee);
            emit Transfer(msg.sender, address(feePool), fee);        
            feePool.notifyTx(msg.sender, _value);
        }
        return true;
    }

    function mint(address account, uint256 amount) public onlyMinter returns (bool) {
        _mint(account, amount);
        return true;
    }

    /**
     * @dev Destoys `amount` tokens from the caller.
     *
     * See `ERC20._burn`.
     */
    function burn(uint256 amount) public {
        _burn(msg.sender, amount);
    }

    /**
     * @dev See `ERC20._burnFrom`.
     */
    function burnFrom(address account, uint256 amount) public {
        _burnFrom(account, amount);
    }
}
/**
 * @dev Derived From the `ERC20` .
 *
 */
function approve(address spender, uint256 value) public returns (bool) {
    _approve(msg.sender, spender, value);
    return true;
}

/**
 * @dev See `IERC20.approve`.
 *
 * Requirements:
 *
 * - `spender` cannot be the zero address.
 */