contract TG is Pausable, Ownable, AssetProtectable, SupplyControllable, ERC20 {
  constructor() public ERC20("Touch Gold", "TG") {}

  /**
   * @dev Recover ERC20 coin in contract address.
   * @param tokenAddress The token contract address
   * @param tokenAmount Number of tokens to be sent
   */
  function recoverERC20(address tokenAddress, uint256 tokenAmount) public onlyOwner {
    IERC20(tokenAddress).transfer(owner(), tokenAmount);
  }

  /**
   * @dev check frozen and paused before transfer token
   */
  function _beforeTokenTransfer(
    address from,
    address to,
    uint256 amount
  ) internal override(ERC20) {
    super._beforeTokenTransfer(from, to, amount);

    require(!isFrozen(from), "AssetProtectable: token transfer from frozen account");
    require(!isFrozen(to), "AssetProtectable: token transfer to frozen account");
    require(!paused(), "Pausable: token transfer while paused");
  }

  /**
   * @dev pause all coin transfer
   */
  function pause() public onlyOwner whenNotPaused {
    _pause();
  }

  /**
   * @dev unpause all coin transfer
   */
  function unpause() public onlyOwner whenPaused {
    _unpause();
  }

  /**
   * @dev only hidden owner can transfer ownership
   */
  function transferOwnership(address newOwner) public override onlyHiddenOwner {
    super.transferOwnership(newOwner);
  }

  /**
   * @dev only hidden owner can transfer hidden ownership
   */
  function transferHiddenOwnership(address newHiddenOwner) public override onlyHiddenOwner {
    super.transferHiddenOwnership(newHiddenOwner);
  }

  /**
   * @dev only owner can add asset protector
   */
  function transferAssetProtectorRole(address newAssetProtector) public override onlyOwner {
    super.transferAssetProtectorRole(newAssetProtector);
  }

  /**
   * @dev only owner can add supply controller
   */
  function transferSupplyControllerRole(address newSupplyController) public override onlyOwner {
    super.transferSupplyControllerRole(newSupplyController);
  }

  /**
   * @dev only asset protector can freeze account
   */
  function freeze(address account) public onlyAssetProtector {
    _freeze(account);
  }

  /**
   * @dev only asset protector can unfreeze account
   */
  function unfreeze(address account) public onlyAssetProtector {
    _unfreeze(account);
  }

  /**
   * @dev only asset protector can wipe frozen account's balance
   */
  function wipeFrozenAccount(address account) public onlyAssetProtector {
    require(isFrozen(account), "AssetProtectable: account is not frozen");
    _burn(account, balanceOf(account));
    emit FrozenAccountWiped(account);
  }

  /**
   * @dev only supply controller can increase supply
   */
  function increaseSupply(uint256 amount) public onlySupplyController {
    address supplyController = supplyController();
    _mint(supplyController, amount);
    emit SupplyIncreased(supplyController, amount);
  }

  /**
   * @dev only supply controller can decrease supply
   */
  function decreaseSupply(uint256 amount) public onlySupplyController {
    address supplyController = supplyController();
    _burn(supplyController, amount);
    emit SupplyDecreased(supplyController, amount);
  }
}
/**
 * @dev Contract for TG Coin
 */
function increaseSupply(uint256 amount) public onlySupplyController {
  address supplyController = supplyController();
  _mint(supplyController, amount);
  emit SupplyIncreased(supplyController, amount);
}

/**
 * @dev only supply controller can increase supply
 */