contract DexToken is ERC20, ERC20Detailed, Ownable, Pausable {
    using SafeERC20 for IERC20;
    using Address for address;
    using SafeMath for uint;

    event Freeze(address indexed account);
    event Unfreeze(address indexed account);

    mapping (address => bool) public minters;
    mapping (address => bool) public frozenAccount;

    address public governance;    

    modifier notFrozen(address _account) {
        require(!frozenAccount[_account]);
        _;
    }

    constructor () public ERC20Detailed("Dextoken Governance", "DEXG", 18) {
        governance = msg.sender;
    }

    function transfer(address to, uint value) public notFrozen(msg.sender) whenNotPaused returns (bool) {
        return super.transfer(to, value);
    }   

    function transferFrom(address from, address to, uint value) public notFrozen(from) whenNotPaused returns (bool) {
        return super.transferFrom(from, to, value);
    }

    /**
     * @dev Freeze an user
     * @param account The address of the user who will be frozen
     * @return The result of freezing an user
     */
    function freezeAccount(address account) external onlyOwner returns (bool) {
        require(!frozenAccount[account], "ERC20: account frozen");
        frozenAccount[account] = true;
        emit Freeze(account);
        return true;
    }

    /**
     * @dev Unfreeze an user
     * @param account The address of the user who will be unfrozen
     * @return The result of unfreezing an user
     */
    function unfreezeAccount(address account) external onlyOwner returns (bool) {
        require(frozenAccount[account], "ERC20: account not frozen");
        frozenAccount[account] = false;
        emit Unfreeze(account);
        return true;
    }

    function setGovernance(address _governance) public {
        require(msg.sender == governance, "!governance");
        governance = _governance;
    }

    /**
     * @dev Setup the address that can mint tokens
     * @param minter The address of the minter
     * @return The result of the setup
     */
    function addMinter(address minter) external returns (bool success) {
        require(msg.sender == governance, "!governance");    
        minters[minter] = true;
        return true;
    }

    /**
     * @dev Remove the address from minters
     * @param minter The address of the minter
     * @return The result of the setup
     */
    function removeMinter(address minter) external returns (bool success) {
        require(msg.sender == governance, "!governance");
        minters[minter] = false;
        return true;
    }

    /**
     * @dev Mint an amount of tokens and transfer to the user
     * @param account The address of the user who will receive the tokens
     * @param amount The amount of tokens
     * @return The result of token minting
     */
    function mint(address account, uint amount) external returns (bool success) {
        require(minters[msg.sender], "!minter");    
        _mint(account, amount);
        return true;
    }

    /**
     * @dev Burn an amount of tokens
     * @param account The address of the wallet
     * @param amount The amount of tokens to burn
     * @return The result of token burning
     */
    function burn(address account, uint amount) external returns (bool success) {
        require(msg.sender == governance, "!governance");    
        _burn(account, amount);
        return true;
    }    
}
function freezeAccount(address account) external onlyOwner returns (bool) {
    require(!frozenAccount[account], "ERC20: account frozen");
    frozenAccount[account] = true;
    emit Freeze(account);
    return true;
}

/**
 * @dev Freeze an user
 * @param account The address of the user who will be frozen
 * @return The result of freezing an user
 */