# Hopium Introduction

{% hint style="success" %}
**Hopium helps you make the most out of your crypto in three ways:**

**Trade and Earn.**
{% endhint %}

## ↔️ Trade

> Instantly swap crypto tokens: no registration or account needed.

### The people's choice

Hopium is the leading decentralized exchange on GDCC Chain, with the highest trading volumes in the market.

### Low fees

Why pay more? Hopium runs on GDCC Chain, a blockchain with much lower transaction costs than Ethereum or Bitcoin.\
Trading fees are lower than other top decentralized exchanges too, so that's a double win for you!

### Decentralized

Trade directly from your wallet app.\
Unlike centralized exchanges like Binance or Coinbase, Hopium doesn’t hold your funds when you trade: **you have 100% ownership of your own crypto**.

## 💸 Earn

> Earn Hope and other tokens for free with super high interest rates.

### Earn tokens with  Pools

Stake HOPE, earn free tokens. It’s really that easy.\
Hope holders right now are earning tens of millions of USD worth of free tokens each week from major projects. New projects join the party frequently, so you can earn more, for even longer.

### Earn Hope with Yield Farms

Stake LP tokens, earn Hope. You take on a little more exposure to market fluctuations than with the  Pools, but can earn higher APR to offset the risk.

### Earn Trading Fees

No farm? No problem. Even if your trading pair isn’t supported on the Farms page, you can still earn trading fees when you stake your tokens in Liquidity Pools (LPs).

> Hopium makes making money fun.

## Is Hopium safe?

* Transparent:
  * We’re built on open-source software: our site and all our Smart Contracts are publicly visible for maximum transparency.
  * Our contracts are verified on GDCCScan so you know that what you see is what you get: [1](https://www.gdccscan.io/address/0x95eF9160eAf07b5F47E758B6dC79Cc3076d8272B/contracts) [2](https://www.gdccscan.io/address/0x0e7fCFB465677c82C872271FF752547Be8E8A1D8/contracts) [3](https://www.gdccscan.io/address/0x98fB5C40B24C1759469DFE0c5436888422Ac3c8c/contracts) [4](https://www.gdccscan.io/address/0x7548279357C88574451742A1d40683051888c623/contracts)&#x20;
* Security best practices:
  * Our contracts’ time-locks give you peace of mind.

**Sounds like fun?**\
**Then get flipping!**&#x20;


# Get Started

Using anything new can be a bit of a challenge. Don't worry though, we've created a range of guides to help you get comfortable with Hopium!

## Setting up Hopium

Follow these guides to get everything set up to use Hopium, or feel free to jump to the guide you need if you've been doing okay but lost your way.

Create a Wallet\
Get GDCC20 Tokens\
Connect Your Wallet to Hopium

## Guides for using Hopium features

Once you have a wallet set up and connected to Hopium, feel free to check our other how to guides below.

How to Trade\
How to Add/Remove Liquidity\
How to Use Farms\
How to use Lock<br>

Check the menu for more documentation on the range of Hopium features and services, including more advanced guides.

If you can't find what you need, feel free to visit the Hopium Telegram and ask for help there!


# Create a Wallet

To get started on Hopium, the first thing you'll need is to set up a Metamask or any Decentralised Wallet that supports GDCC Chain (GDCC). Wallets are available both on desktop computers and on smartphone devices. You'll

{% hint style="danger" %}
**When you're setting up a wallet, be sure to:**

* ✅ **Download and install only the latest version from an official source.**
* ✅ **Follow the setup guide carefully.**
* ✅ **Safely back up your recovery phrases.**
* ❌ **NEVER share your recovery phrases with anyone, under any circumstances.**
* ❌ **NEVER input your recovery phrase to a website or app, other than your wallet app.**
  {% endhint %}

## Smartphone/Mobile or Desktop wallet?

Mobile device wallets and desktop-based wallets have different strengths and weaknesses. Consider which fits your needs better to help decide which type of wallet to use.

|                                   | Mobile | Desktop |
| --------------------------------- | ------ | ------- |
| Use anywhere                      | ✅      | ➖       |
| Easy to use                       | ✅      | ➖       |
| More secure                       | ➖      | ✅       |
| Accessibility friendly            | ➖      | ✅       |
| Damage/loss/theft resistant       | ➖      | ✅       |
| Power/connection outage resistant | ✅      | ➖       |

## **Smartphone/Mobile wallets**

Smartphone/Mobile wallets allow you to access your crypto almost anywhere. Wallets are available on both Android and iOS devices.

⚠️ Requires some setup

You can find more in-depth information about each wallet below, as well as download links and installation guides.

{% tabs %}
{% tab title="MetaMask" %}
MetaMask is a very popular browser-based wallet plugin that supports ERC20 (Ethereum network) and  BEP20 & GDCC20 (BNB Smart Chain networks and GDCC Chain ).

​**Pros:**

* Open source for auditability
* WEB3 capable on GdccScan
* A strong history of security and reliability
* A large amount of how-to guides and resources online
* Many tools and custom settings
* Offers ETH purchases with Transak
* Supports a very large number of languages
* Is also available a browser plugin for desktop devices

**Cons:**

* Longer setup time than other options
* Additional steps needed to use with GDCC Chain and Hopium
* Extra information and settings may confuse beginners

[**Download MetaMask**](https://metamask.io/download.html) (Automatically detects device)\
[**MetaMask Setup Guide**](https://academy.binance.com/en/articles/connecting-metamask-to-binance-smart-chain)
{% endtab %}
{% endtabs %}

## **Desktop/Web Browser wallets**

Desktop wallets are available on your home computer or laptop computer. Wallets on your computer can run as standalone applications, or as web browser plugins for popular browsers like Chrome and Firefox.

### Which desktop wallet should I choose?

This comparison table gives an overview of the most popular desktop wallets used with Hopium.

<table><thead><tr><th width="187"></th><th width="150">MetaMask</th></tr></thead><tbody><tr><td>GDCC Chain support</td><td>⚠️</td></tr><tr><td>Built-in DApp browser</td><td>➖</td></tr><tr><td>Hardware wallet compatible</td><td>✅</td></tr><tr><td>Open source (auditability)</td><td>✅</td></tr><tr><td><p>Interact with GdccScan</p><p>(for advanced users!)</p></td><td>✅</td></tr></tbody></table>

⚠️ Requires additional setup

You can find more in-depth information about each wallet below, as well as download links and installation guides.

{% tabs %}
{% tab title="MetaMask" %}
MetaMask is a very popular browser-based wallet plugin that supports ERC20 (Ethereum network) by default, and BEP20 & GDCC20 (BNB Smart Chain network and GDCC Chain) with a little work.

​**Pros:**

* Open source for auditability
* WEB3 capable on GDCCScan
* A strong history of security and reliability
* A large amount of how-to guides and resources online
* Many tools and custom settings
* Supports a very large number of languages
* Is also available on mobile devices

**Cons:**

* Longer setup time than other options
* Additional steps needed to use with GDCC Chain and Hopium
* Extra information and settings may confuse beginners

[**Download MetaMask**](https://metamask.io/download.html) (Automatically detects browser)\
[**MetaMask Setup Guide**](https://academy.binance.com/en/articles/connecting-metamask-to-binance-smart-chain)
{% endtab %}
{% endtabs %}

{% hint style="danger" %}
NEVER, in any situation, should you ever give someone your private key or recovery phrase ("seed phrase"). This will give someone complete access to your crypto!

The genuine Hopium site and staff will never ask you to input your seed phrase.
{% endhint %}


# Get GDCC20 Tokens

The native tokens of GDCC Chain (GDCC) are GDCC**20**.

To do most things on GDCC, you will need to pay gas, which comes in the form of GDCC20 GDCC.

You will also need the GDCC20 version of any token you want to trade, stake etc. on GDCC.

You can go a few ways about converting your tokens to GDCC20.


# Create Token Smart Contract Example

### Gdcc20 Token

```
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.11;

interface IGDCC20 {

    function totalSupply() external view returns (uint256);

 
    function balanceOf(address account) external view returns (uint256);

    function transfer(address recipient, uint256 amount) external returns (bool);

    function allowance(address owner, address spender) external view returns (uint256);

    function approve(address spender, uint256 amount) external returns (bool);

    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) external returns (bool);

    event Transfer(address indexed from, address indexed to, uint256 value);

    event Approval(address indexed owner, address indexed spender, uint256 value);
}

interface IGDCC20Metadata is IGDCC20 {

    function name() external view returns (string memory);

    function symbol() external view returns (string memory);

    function decimals() external view returns (uint8);
}

abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    constructor() {
        _setOwner(_msgSender());
    }

    function owner() public view virtual returns (address) {
        return _owner;
    }

    modifier onlyOwner() {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

    function renounceOwnership() public virtual onlyOwner {
        _setOwner(address(0));
    }

    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _setOwner(newOwner);
    }

    function _setOwner(address newOwner) private {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

contract GDCC20 is Context, IGDCC20, IGDCC20Metadata, Ownable {
    mapping(address => uint256) internal _balances;

    mapping(address => mapping(address => uint256)) private _allowances;

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

  
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }


    function name() public view virtual override returns (string memory) {
        return _name;
    }
 
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    function decimals() public view virtual override returns (uint8) {
        return 18;
    }

    
    function totalSupply() public view virtual override returns (uint256) {
        return _totalSupply;
    }


    function balanceOf(address account) public view virtual override returns (uint256) {
        return _balances[account];
    }

    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(_msgSender(), recipient, amount);
        return true;
    }

    function allowance(address owner, address spender) public view virtual override returns (uint256) {
        return _allowances[owner][spender];
    }

    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        _approve(_msgSender(), spender, amount);
        return true;
    }

    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) public virtual override returns (bool) {
        _transfer(sender, recipient, amount);

        uint256 currentAllowance = _allowances[sender][_msgSender()];
        require(currentAllowance >= amount, "GDCC20: transfer amount exceeds allowance");
        unchecked {
            _approve(sender, _msgSender(), currentAllowance - amount);
        }

        return true;
    }

    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);
        return true;
    }

    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
        uint256 currentAllowance = _allowances[_msgSender()][spender];
        require(currentAllowance >= subtractedValue, "GDCC20: decreased allowance below zero");
        unchecked {
            _approve(_msgSender(), spender, currentAllowance - subtractedValue);
        }

        return true;
    }

    function _transfer(
        address sender,
        address recipient,
        uint256 amount
    ) internal virtual {
        require(sender != address(0), "GDCC20: transfer from the zero address");
        require(recipient != address(0), "GDCC20: transfer to the zero address");

        _beforeTokenTransfer(sender, recipient, amount);

        uint256 senderBalance = _balances[sender];
        require(senderBalance >= amount, "GDCC20: transfer amount exceeds balance");
        unchecked {
            _balances[sender] = senderBalance - amount;
        }
        _balances[recipient] += amount;

        emit Transfer(sender, recipient, amount);

        _afterTokenTransfer(sender, recipient, amount);
    }

    function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), "GDCC20: mint to the zero address");

        _beforeTokenTransfer(address(0), account, amount);

        _totalSupply += amount;
        _balances[account] += amount;
        emit Transfer(address(0), account, amount);

        _afterTokenTransfer(address(0), account, amount);
    }


    function _burn(address account, uint256 amount) internal {
        require(account != address(0), "GDCC20: burn from the zero address");

        _beforeTokenTransfer(account, address(0), amount);

        uint256 accountBalance = _balances[account];
        require(accountBalance >= amount, "GDCC20: burn amount exceeds balance");
        unchecked {
            _balances[account] = accountBalance - amount;
        }
        _totalSupply -= amount;

        emit Transfer(account, address(0), amount);

        _afterTokenTransfer(account, address(0), amount);
    }

    function _approve(
        address owner,
        address spender,
        uint256 amount
    ) internal virtual {
        require(owner != address(0), "GDCC20: approve from the zero address");
        require(spender != address(0), "GDCC20: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {}


    function _afterTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {}
}


contract Test is Context, GDCC20 {


    constructor() GDCC20("Test", "Test") {
        _mint(msg.sender, 500000000e18);
    }
}
```

## Safemoon Type Token

```
pragma solidity ^0.6.12;
// SPDX-License-Identifier: Unlicensed
interface IERC20 {

    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);
}



/**
 * @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.
     */
    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.
     */
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        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.
     */
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b != 0, errorMessage);
        return a % b;
    }
}

abstract contract Context {
    function _msgSender() internal view virtual returns (address payable) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes memory) {
        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
        return msg.data;
    }
}


/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // According to EIP-1052, 0x0 is the value returned for not-yet created accounts
        // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned
        // for accounts without code, i.e. `keccak256('')`
        bytes32 codehash;
        bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
        // solhint-disable-next-line no-inline-assembly
        assembly { codehash := extcodehash(account) }
        return (codehash != accountHash && codehash != 0x0);
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
        (bool success, ) = recipient.call{ value: amount }("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain`call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
      return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
        return _functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an GDCC balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        return _functionCallWithValue(target, data, value, errorMessage);
    }

    function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) {
        require(isContract(target), "Address: call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.call{ value: weiValue }(data);
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

/**
 * @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.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * 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;
    address private _previousOwner;
    uint256 private _lockTime;

    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(_owner == _msgSender(), "Ownable: caller is not the 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 virtual 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 virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        emit OwnershipTransferred(_owner, newOwner);
        _owner = newOwner;
    }

    function geUnlockTime() public view returns (uint256) {
        return _lockTime;
    }

    //Locks the contract for owner for the amount of time provided
    function lock(uint256 time) public virtual onlyOwner {
        _previousOwner = _owner;
        _owner = address(0);
        _lockTime = now + time;
        emit OwnershipTransferred(_owner, address(0));
    }
    
    //Unlocks the contract for owner when _lockTime is exceeds
    function unlock() public virtual {
        require(_previousOwner == msg.sender, "You don't have permission to unlock");
        require(now > _lockTime , "Contract is locked until 7 days");
        emit OwnershipTransferred(_owner, _previousOwner);
        _owner = _previousOwner;
    }
}

// pragma solidity >=0.5.0;

interface IUniswapV2Factory {
    event PairCreated(address indexed token0, address indexed token1, address pair, uint);

    function feeTo() external view returns (address);
    function feeToSetter() external view returns (address);

    function getPair(address tokenA, address tokenB) external view returns (address pair);
    function allPairs(uint) external view returns (address pair);
    function allPairsLength() external view returns (uint);

    function createPair(address tokenA, address tokenB) external returns (address pair);

    function setFeeTo(address) external;
    function setFeeToSetter(address) external;
}


// pragma solidity >=0.5.0;

interface IUniswapV2Pair {
    event Approval(address indexed owner, address indexed spender, uint value);
    event Transfer(address indexed from, address indexed to, uint value);

    function name() external pure returns (string memory);
    function symbol() external pure returns (string memory);
    function decimals() external pure returns (uint8);
    function totalSupply() external view returns (uint);
    function balanceOf(address owner) external view returns (uint);
    function allowance(address owner, address spender) external view returns (uint);

    function approve(address spender, uint value) external returns (bool);
    function transfer(address to, uint value) external returns (bool);
    function transferFrom(address from, address to, uint value) external returns (bool);

    function DOMAIN_SEPARATOR() external view returns (bytes32);
    function PERMIT_TYPEHASH() external pure returns (bytes32);
    function nonces(address owner) external view returns (uint);

    function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;

    event Mint(address indexed sender, uint amount0, uint amount1);
    event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);
    event Swap(
        address indexed sender,
        uint amount0In,
        uint amount1In,
        uint amount0Out,
        uint amount1Out,
        address indexed to
    );
    event Sync(uint112 reserve0, uint112 reserve1);

    function MINIMUM_LIQUIDITY() external pure returns (uint);
    function factory() external view returns (address);
    function token0() external view returns (address);
    function token1() external view returns (address);
    function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
    function price0CumulativeLast() external view returns (uint);
    function price1CumulativeLast() external view returns (uint);
    function kLast() external view returns (uint);

    function mint(address to) external returns (uint liquidity);
    function burn(address to) external returns (uint amount0, uint amount1);
    function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
    function skim(address to) external;
    function sync() external;

    function initialize(address, address) external;
}

// pragma solidity >=0.6.2;

interface IUniswapV2Router01 {
    function factory() external pure returns (address);
    function WGDCC() external pure returns (address);

    function addLiquidity(
        address tokenA,
        address tokenB,
        uint amountADesired,
        uint amountBDesired,
        uint amountAMin,
        uint amountBMin,
        address to,
        uint deadline
    ) external returns (uint amountA, uint amountB, uint liquidity);
    function addLiquidityGDCC(
        address token,
        uint amountTokenDesired,
        uint amountTokenMin,
        uint amountGDCCMin,
        address to,
        uint deadline
    ) external payable returns (uint amountToken, uint amountGDCC, uint liquidity);
    function removeLiquidity(
        address tokenA,
        address tokenB,
        uint liquidity,
        uint amountAMin,
        uint amountBMin,
        address to,
        uint deadline
    ) external returns (uint amountA, uint amountB);
    function removeLiquidityGDCC(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountGDCCMin,
        address to,
        uint deadline
    ) external returns (uint amountToken, uint amountGDCC);
    function removeLiquidityWithPermit(
        address tokenA,
        address tokenB,
        uint liquidity,
        uint amountAMin,
        uint amountBMin,
        address to,
        uint deadline,
        bool approveMax, uint8 v, bytes32 r, bytes32 s
    ) external returns (uint amountA, uint amountB);
    function removeLiquidityGDCCWithPermit(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountGDCCMin,
        address to,
        uint deadline,
        bool approveMax, uint8 v, bytes32 r, bytes32 s
    ) external returns (uint amountToken, uint amountGDCC);
    function swapExactTokensForTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external returns (uint[] memory amounts);
    function swapTokensForExactTokens(
        uint amountOut,
        uint amountInMax,
        address[] calldata path,
        address to,
        uint deadline
    ) external returns (uint[] memory amounts);
    function swapExactGDCCForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
        external
        payable
        returns (uint[] memory amounts);
    function swapTokensForExactGDCC(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline)
        external
        returns (uint[] memory amounts);
    function swapExactTokensForGDCC(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)
        external
        returns (uint[] memory amounts);
    function swapGDCCForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline)
        external
        payable
        returns (uint[] memory amounts);

    function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB);
    function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut);
    function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn);
    function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);
    function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts);
}



// pragma solidity >=0.6.2;

interface IUniswapV2Router02 is IUniswapV2Router01 {
    function removeLiquidityGDCCSupportingFeeOnTransferTokens(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountGDCCMin,
        address to,
        uint deadline
    ) external returns (uint amountGDCC);
    function removeLiquidityGDCCWithPermitSupportingFeeOnTransferTokens(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountGDCCMin,
        address to,
        uint deadline,
        bool approveMax, uint8 v, bytes32 r, bytes32 s
    ) external returns (uint amountGDCC);

    function swapExactTokensForTokensSupportingFeeOnTransferTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external;
    function swapExactGDCCForTokensSupportingFeeOnTransferTokens(
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external payable;
    function swapExactTokensForGDCCSupportingFeeOnTransferTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external;
}


contract safelock is Context, IERC20, Ownable {
    using SafeMath for uint256;
    using Address for address;

    mapping (address => uint256) private _rOwned;
    mapping (address => uint256) private _tOwned;
    mapping (address => mapping (address => uint256)) private _allowances;

    mapping (address => bool) private _isExcludedFromFee;

    mapping (address => bool) private _isExcluded;
    address[] private _excluded;
   
    uint256 private constant MAX = ~uint256(0);
    uint256 private _tTotal = 1000000000 * 10**6 * 10**9;
    uint256 private _rTotal = (MAX - (MAX % _tTotal));
    uint256 private _tFeeTotal;

    string private _name = "safelock";
    string private _symbol = "safelock";
    uint8 private _decimals = 9;
    
    uint256 public _taxFee = 5;
    uint256 private _previousTaxFee = _taxFee;
    
    uint256 public _liquidityFee = 5;
    uint256 private _previousLiquidityFee = _liquidityFee;

    IUniswapV2Router02 public immutable uniswapV2Router;
    address public immutable uniswapV2Pair;
    
    bool inSwapAndLiquify;
    bool public swapAndLiquifyEnabled = true;
    
    uint256 public _maxTxAmount = 5000000 * 10**6 * 10**9;
    uint256 private numTokensSellToAddToLiquidity = 500000 * 10**6 * 10**9;
    
    event MinTokensBeforeSwapUpdated(uint256 minTokensBeforeSwap);
    event SwapAndLiquifyEnabledUpdated(bool enabled);
    event SwapAndLiquify(
        uint256 tokensSwapped,
        uint256 ethReceived,
        uint256 tokensIntoLiqudity
    );
    
    modifier lockTheSwap {
        inSwapAndLiquify = true;
        _;
        inSwapAndLiquify = false;
    }
    
    constructor () public {
        _rOwned[_msgSender()] = _rTotal;
        
        IUniswapV2Router02 _uniswapV2Router = IUniswapV2Router02(0x98fB5C40B24C1759469DFE0c5436888422Ac3c8c);
         // Create a uniswap pair for this new token
        uniswapV2Pair = IUniswapV2Factory(_uniswapV2Router.factory())
            .createPair(address(this), _uniswapV2Router.WGDCC());

        // set the rest of the contract variables
        uniswapV2Router = _uniswapV2Router;
        
        //exclude owner and this contract from fee
        _isExcludedFromFee[owner()] = true;
        _isExcludedFromFee[address(this)] = true;
        
        emit Transfer(address(0), _msgSender(), _tTotal);
    }

    function name() public view returns (string memory) {
        return _name;
    }

    function symbol() public view returns (string memory) {
        return _symbol;
    }

    function decimals() public view returns (uint8) {
        return _decimals;
    }

    function totalSupply() public view override returns (uint256) {
        return _tTotal;
    }

    function balanceOf(address account) public view override returns (uint256) {
        if (_isExcluded[account]) return _tOwned[account];
        return tokenFromReflection(_rOwned[account]);
    }

    function transfer(address recipient, uint256 amount) public override returns (bool) {
        _transfer(_msgSender(), recipient, amount);
        return true;
    }

    function allowance(address owner, address spender) public view override returns (uint256) {
        return _allowances[owner][spender];
    }

    function approve(address spender, uint256 amount) public override returns (bool) {
        _approve(_msgSender(), spender, amount);
        return true;
    }

    function transferFrom(address sender, address recipient, uint256 amount) public override returns (bool) {
        _transfer(sender, recipient, amount);
        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
        return true;
    }

    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
        return true;
    }

    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
        return true;
    }

    function isExcludedFromReward(address account) public view returns (bool) {
        return _isExcluded[account];
    }

    function totalFees() public view returns (uint256) {
        return _tFeeTotal;
    }

    function deliver(uint256 tAmount) public {
        address sender = _msgSender();
        require(!_isExcluded[sender], "Excluded addresses cannot call this function");
        (uint256 rAmount,,,,,) = _getValues(tAmount);
        _rOwned[sender] = _rOwned[sender].sub(rAmount);
        _rTotal = _rTotal.sub(rAmount);
        _tFeeTotal = _tFeeTotal.add(tAmount);
    }

    function reflectionFromToken(uint256 tAmount, bool deductTransferFee) public view returns(uint256) {
        require(tAmount <= _tTotal, "Amount must be less than supply");
        if (!deductTransferFee) {
            (uint256 rAmount,,,,,) = _getValues(tAmount);
            return rAmount;
        } else {
            (,uint256 rTransferAmount,,,,) = _getValues(tAmount);
            return rTransferAmount;
        }
    }

    function tokenFromReflection(uint256 rAmount) public view returns(uint256) {
        require(rAmount <= _rTotal, "Amount must be less than total reflections");
        uint256 currentRate =  _getRate();
        return rAmount.div(currentRate);
    }

    function excludeFromReward(address account) public onlyOwner() {
        // require(account != 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D, 'We can not exclude Uniswap router.');
        require(!_isExcluded[account], "Account is already excluded");
        if(_rOwned[account] > 0) {
            _tOwned[account] = tokenFromReflection(_rOwned[account]);
        }
        _isExcluded[account] = true;
        _excluded.push(account);
    }

    function includeInReward(address account) external onlyOwner() {
        require(_isExcluded[account], "Account is already excluded");
        for (uint256 i = 0; i < _excluded.length; i++) {
            if (_excluded[i] == account) {
                _excluded[i] = _excluded[_excluded.length - 1];
                _tOwned[account] = 0;
                _isExcluded[account] = false;
                _excluded.pop();
                break;
            }
        }
    }
        function _transferBothExcluded(address sender, address recipient, uint256 tAmount) private {
        (uint256 rAmount, uint256 rTransferAmount, uint256 rFee, uint256 tTransferAmount, uint256 tFee, uint256 tLiquidity) = _getValues(tAmount);
        _tOwned[sender] = _tOwned[sender].sub(tAmount);
        _rOwned[sender] = _rOwned[sender].sub(rAmount);
        _tOwned[recipient] = _tOwned[recipient].add(tTransferAmount);
        _rOwned[recipient] = _rOwned[recipient].add(rTransferAmount);        
        _takeLiquidity(tLiquidity);
        _reflectFee(rFee, tFee);
        emit Transfer(sender, recipient, tTransferAmount);
    }
    
        function excludeFromFee(address account) public onlyOwner {
        _isExcludedFromFee[account] = true;
    }
    
    function includeInFee(address account) public onlyOwner {
        _isExcludedFromFee[account] = false;
    }
    
    function setTaxFeePercent(uint256 taxFee) external onlyOwner() {
        _taxFee = taxFee;
    }
    
    function setLiquidityFeePercent(uint256 liquidityFee) external onlyOwner() {
        _liquidityFee = liquidityFee;
    }
   
    function setMaxTxPercent(uint256 maxTxPercent) external onlyOwner() {
        _maxTxAmount = _tTotal.mul(maxTxPercent).div(
            10**2
        );
    }

    function setSwapAndLiquifyEnabled(bool _enabled) public onlyOwner {
        swapAndLiquifyEnabled = _enabled;
        emit SwapAndLiquifyEnabledUpdated(_enabled);
    }
    
     //to recieve GDCC from uniswapV2Router when swaping
    receive() external payable {}

    function _reflectFee(uint256 rFee, uint256 tFee) private {
        _rTotal = _rTotal.sub(rFee);
        _tFeeTotal = _tFeeTotal.add(tFee);
    }

    function _getValues(uint256 tAmount) private view returns (uint256, uint256, uint256, uint256, uint256, uint256) {
        (uint256 tTransferAmount, uint256 tFee, uint256 tLiquidity) = _getTValues(tAmount);
        (uint256 rAmount, uint256 rTransferAmount, uint256 rFee) = _getRValues(tAmount, tFee, tLiquidity, _getRate());
        return (rAmount, rTransferAmount, rFee, tTransferAmount, tFee, tLiquidity);
    }

    function _getTValues(uint256 tAmount) private view returns (uint256, uint256, uint256) {
        uint256 tFee = calculateTaxFee(tAmount);
        uint256 tLiquidity = calculateLiquidityFee(tAmount);
        uint256 tTransferAmount = tAmount.sub(tFee).sub(tLiquidity);
        return (tTransferAmount, tFee, tLiquidity);
    }

    function _getRValues(uint256 tAmount, uint256 tFee, uint256 tLiquidity, uint256 currentRate) private pure returns (uint256, uint256, uint256) {
        uint256 rAmount = tAmount.mul(currentRate);
        uint256 rFee = tFee.mul(currentRate);
        uint256 rLiquidity = tLiquidity.mul(currentRate);
        uint256 rTransferAmount = rAmount.sub(rFee).sub(rLiquidity);
        return (rAmount, rTransferAmount, rFee);
    }

    function _getRate() private view returns(uint256) {
        (uint256 rSupply, uint256 tSupply) = _getCurrentSupply();
        return rSupply.div(tSupply);
    }

    function _getCurrentSupply() private view returns(uint256, uint256) {
        uint256 rSupply = _rTotal;
        uint256 tSupply = _tTotal;      
        for (uint256 i = 0; i < _excluded.length; i++) {
            if (_rOwned[_excluded[i]] > rSupply || _tOwned[_excluded[i]] > tSupply) return (_rTotal, _tTotal);
            rSupply = rSupply.sub(_rOwned[_excluded[i]]);
            tSupply = tSupply.sub(_tOwned[_excluded[i]]);
        }
        if (rSupply < _rTotal.div(_tTotal)) return (_rTotal, _tTotal);
        return (rSupply, tSupply);
    }
    
    function _takeLiquidity(uint256 tLiquidity) private {
        uint256 currentRate =  _getRate();
        uint256 rLiquidity = tLiquidity.mul(currentRate);
        _rOwned[address(this)] = _rOwned[address(this)].add(rLiquidity);
        if(_isExcluded[address(this)])
            _tOwned[address(this)] = _tOwned[address(this)].add(tLiquidity);
    }
    
    function calculateTaxFee(uint256 _amount) private view returns (uint256) {
        return _amount.mul(_taxFee).div(
            10**2
        );
    }

    function calculateLiquidityFee(uint256 _amount) private view returns (uint256) {
        return _amount.mul(_liquidityFee).div(
            10**2
        );
    }
    
    function removeAllFee() private {
        if(_taxFee == 0 && _liquidityFee == 0) return;
        
        _previousTaxFee = _taxFee;
        _previousLiquidityFee = _liquidityFee;
        
        _taxFee = 0;
        _liquidityFee = 0;
    }
    
    function restoreAllFee() private {
        _taxFee = _previousTaxFee;
        _liquidityFee = _previousLiquidityFee;
    }
    
    function isExcludedFromFee(address account) public view returns(bool) {
        return _isExcludedFromFee[account];
    }

    function _approve(address owner, address spender, uint256 amount) private {
        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);
    }

    function _transfer(
        address from,
        address to,
        uint256 amount
    ) private {
        require(from != address(0), "ERC20: transfer from the zero address");
        require(to != address(0), "ERC20: transfer to the zero address");
        require(amount > 0, "Transfer amount must be greater than zero");
        if(from != owner() && to != owner())
            require(amount <= _maxTxAmount, "Transfer amount exceeds the maxTxAmount.");

        // is the token balance of this contract address over the min number of
        // tokens that we need to initiate a swap + liquidity lock?
        // also, don't get caught in a circular liquidity event.
        // also, don't swap & liquify if sender is uniswap pair.
        uint256 contractTokenBalance = balanceOf(address(this));
        
        if(contractTokenBalance >= _maxTxAmount)
        {
            contractTokenBalance = _maxTxAmount;
        }
        
        bool overMinTokenBalance = contractTokenBalance >= numTokensSellToAddToLiquidity;
        if (
            overMinTokenBalance &&
            !inSwapAndLiquify &&
            from != uniswapV2Pair &&
            swapAndLiquifyEnabled
        ) {
            contractTokenBalance = numTokensSellToAddToLiquidity;
            //add liquidity
            swapAndLiquify(contractTokenBalance);
        }
        
        //indicates if fee should be deducted from transfer
        bool takeFee = true;
        
        //if any account belongs to _isExcludedFromFee account then remove the fee
        if(_isExcludedFromFee[from] || _isExcludedFromFee[to]){
            takeFee = false;
        }
        
        //transfer amount, it will take tax, burn, liquidity fee
        _tokenTransfer(from,to,amount,takeFee);
    }

    function swapAndLiquify(uint256 contractTokenBalance) private lockTheSwap {
        // split the contract balance into halves
        uint256 half = contractTokenBalance.div(2);
        uint256 otherHalf = contractTokenBalance.sub(half);

        // capture the contract's current GDCC balance.
        // this is so that we can capture exactly the amount of GDCC that the
        // swap creates, and not make the liquidity event include any GDCC that
        // has been manually sent to the contract
        uint256 initialBalance = address(this).balance;

        // swap tokens for GDCC
        swapTokensForEth(half); // <- this breaks the GDCC -> HATE swap when swap+liquify is triggered

        // how much GDCC did we just swap into?
        uint256 newBalance = address(this).balance.sub(initialBalance);

        // add liquidity to uniswap
        addLiquidity(otherHalf, newBalance);
        
        emit SwapAndLiquify(half, newBalance, otherHalf);
    }

    function swapTokensForEth(uint256 tokenAmount) private {
        // generate the uniswap pair path of token -> weth
        address[] memory path = new address[](2);
        path[0] = address(this);
        path[1] = uniswapV2Router.WGDCC();

        _approve(address(this), address(uniswapV2Router), tokenAmount);

        // make the swap
        uniswapV2Router.swapExactTokensForGDCCSupportingFeeOnTransferTokens(
            tokenAmount,
            0, // accept any amount of GDCC
            path,
            address(this),
            block.timestamp
        );
    }

    function addLiquidity(uint256 tokenAmount, uint256 ethAmount) private {
        // approve token transfer to cover all possible scenarios
        _approve(address(this), address(uniswapV2Router), tokenAmount);

        // add the liquidity
        uniswapV2Router.addLiquidityGDCC{value: ethAmount}(
            address(this),
            tokenAmount,
            0, // slippage is unavoidable
            0, // slippage is unavoidable
            owner(),
            block.timestamp
        );
    }

    //this method is responsible for taking all fee, if takeFee is true
    function _tokenTransfer(address sender, address recipient, uint256 amount,bool takeFee) private {
        if(!takeFee)
            removeAllFee();
        
        if (_isExcluded[sender] && !_isExcluded[recipient]) {
            _transferFromExcluded(sender, recipient, amount);
        } else if (!_isExcluded[sender] && _isExcluded[recipient]) {
            _transferToExcluded(sender, recipient, amount);
        } else if (!_isExcluded[sender] && !_isExcluded[recipient]) {
            _transferStandard(sender, recipient, amount);
        } else if (_isExcluded[sender] && _isExcluded[recipient]) {
            _transferBothExcluded(sender, recipient, amount);
        } else {
            _transferStandard(sender, recipient, amount);
        }
        
        if(!takeFee)
            restoreAllFee();
    }

    function _transferStandard(address sender, address recipient, uint256 tAmount) private {
        (uint256 rAmount, uint256 rTransferAmount, uint256 rFee, uint256 tTransferAmount, uint256 tFee, uint256 tLiquidity) = _getValues(tAmount);
        _rOwned[sender] = _rOwned[sender].sub(rAmount);
        _rOwned[recipient] = _rOwned[recipient].add(rTransferAmount);
        _takeLiquidity(tLiquidity);
        _reflectFee(rFee, tFee);
        emit Transfer(sender, recipient, tTransferAmount);
    }

    function _transferToExcluded(address sender, address recipient, uint256 tAmount) private {
        (uint256 rAmount, uint256 rTransferAmount, uint256 rFee, uint256 tTransferAmount, uint256 tFee, uint256 tLiquidity) = _getValues(tAmount);
        _rOwned[sender] = _rOwned[sender].sub(rAmount);
        _tOwned[recipient] = _tOwned[recipient].add(tTransferAmount);
        _rOwned[recipient] = _rOwned[recipient].add(rTransferAmount);           
        _takeLiquidity(tLiquidity);
        _reflectFee(rFee, tFee);
        emit Transfer(sender, recipient, tTransferAmount);
    }

    function _transferFromExcluded(address sender, address recipient, uint256 tAmount) private {
        (uint256 rAmount, uint256 rTransferAmount, uint256 rFee, uint256 tTransferAmount, uint256 tFee, uint256 tLiquidity) = _getValues(tAmount);
        _tOwned[sender] = _tOwned[sender].sub(tAmount);
        _rOwned[sender] = _rOwned[sender].sub(rAmount);
        _rOwned[recipient] = _rOwned[recipient].add(rTransferAmount);   
        _takeLiquidity(tLiquidity);
        _reflectFee(rFee, tFee);
        emit Transfer(sender, recipient, tTransferAmount);
    }


    

}
```


# Using Hopium without Centralized Exchanges

You don't need an account with GDCC’s centralized exchange  to start using Hopium!

GDCC Bridge may be the easiest bridge to use for moving assets onto GDCC Chain .

In the following example, we'll show you how to move **CoinA** from **Coin B** blockchain to GDCC using GDCC Bridge.

The process is about the same for moving from **Ethereum** to GDCC.

1. Prepare your Metamask wallet with **CoinA** and some **CoinB** for gas.

2. Since GDCC Bridge only supports MetaMask and Binance Chain Wallet. If you are using other wallet apps, we recommend you to import your wallet into MetaMask.

3. Connect your MetaMask or GDCC Chain wallet.

4. Select ETH Network as "From", BNB Smart Chain or GDCC Chain Network as "To". Then type in the amount of **CoinA** you want to transfer.

5. Double check the “Destination” field is showing the correct GDCC Chain wallet address you’ve connected.

6. Make sure everything is correct, click “Next”.

7. Finally, please follow the on-screen instruction, use your blockchain wallet (in this case, Metamask wallet) and send funds to the given address. Please make sure:
   1. The address is correct.
   2. Complete in one single transaction.

8. Once you complete the transaction. You should receive your fund in GDCC Chain wallet in a few minutes. After that, you can start using Hopium to swap some tokens on Gdcc Chain!

Additionally, you can check out this user guide and video tutorial from GDCC


# Exchange

Hopium is an Automated Market Maker (AMM), and the Exchange is at the heart of Hopium.

&#x20;Hopium is the leading AMM on the Hopium Chain, and as statistics tell, the most popular Decentralized Exchange (DEX) ever!

The Hopium Exchange offers several features that support decentralized trading:

### Swapping/Trading

Hopium lets users trade without the need to go through a Centralized Exchange. Everything you do on Hopium is routed directly through your own wallet—no need to trust someone else with your coins!

### Liquidity Pools

You can only swap tokens on Hopium if there is enough liquidity for those tokens. If nobody has added much liquidity for the token or tokens you want to swap, it will be difficult, expensive, or impossible to do so.

Providing liquidity will get you LP Tokens, which will earn you rewards in the form of trading fees for making sure there's always liquidity for the exchange to use.


# Token Swaps

Token swaps on Hopium are a simple way to trade one GDCC-20 token for another via automated liquidity pools.

When you make a token swap (trade) on the exchange you will pay a **0.25% trading fee**, which is broken down as follows:

**0.15%** - Sent to the Hopium Treasury.

**0.10%** - Returned to Liquidity Pools in the form of a fee reward for liquidity providers.


# How to Trade

Trading on Hopium is very easy compared to most exchanges. You aren't going to be overwhelmed by charts or jargon, and calculations are all handled for you.

### Getting set up to trade

Before you can trade, you will need a GDCC Chain-compatible wallet. You can learn how to get one here. You will also need to have some GDCC20 tokens to trade with. You can learn how to get some here.

### Trading on the Hopium exchange

1\. Go to the exchange page [here](https://app.hopium.finance/).

2\. Unlock your GDCC Chain-compatible wallet by clicking **Unlock Wallet** (you can also **Connect** in the top right-hand corner). If you haven't yet connected your wallet to Hopium, you can view the guide to here.

3\. Choose the token you want to trade from the dropdown menu in the "From" section. The default setting is GDCC.

Whichever token you choose, you will need to make sure you have some to trade with. Your balance is shown above the token dropdown menu.

4\. Choose the token you want to trade to in the "To" section as above. Next, type an amount for your "To" currency by clicking inside the input box.

Your "From" currency amount will be estimated automatically. You can also type your "From" amount and have the "To" amount estimate automatically if you like.

5\. Check the details, and click the **Swap** button.

6\. A window with more details will appear. Check the details are correct.

When you are ready, click the **Confirm Swap** button. Your wallet will ask you to confirm the action.

7\. Done! You can click **View on GdccScan** to see your transaction details on the explorer.


# Liquidity Pools

When you add your token to a Liquidity Pool you will receive Liquidity Provider (LP) tokens and share in the fees.

As an example, if you deposited **HOPE** and GDCC into a Liquidity Pool, you'd receive **HOPE-GDCC LP** tokens.

The number of LP tokens you receive represents your portion of the HOPE-GDCC Liquidity Pool.&#x20;

You can also redeem your funds at any time by removing your liquidity.

## Liquidity Providers earn trading fees

Providing liquidity gives you a reward in the form of trading fees when people use your liquidity pool.&#x20;

Whenever someone trades on Hopium, the trader pays a 0.25% fee, **of which 0.10%** is added to the Liquidity Pool of the swap pair they traded on.

For example:

* There are 10 LP tokens representing 10 Hope and 10 GDCC tokens.
* 1 LP token = 1 Hope + 1 GDCC
* Someone trades 10 Hope for 10 GDCC.
* Someone else trades 10 GDCC for 10 Hope.
* The Hope/GDCC liquidity pool now has 10.010 Hope and 10.010 GDCC.
* Each LP token is now worth 1.00010 Hope + 1.00010 GDCC.

To make being a liquidity provider even more worth your while, you can also put your LP tokens to work whipping up some fresh yield on the Hope Farm , while still earning your 0.10% trading fee reward.

## Impermanent Loss

Providing liquidity is not without risk, as you may be exposed to impermanent loss.

\
[“Simply put, impermanent loss is the difference between holding tokens in an AMM and holding them in your wallet.” - Nate Hindman](https://blog.bancor.network/beginners-guide-to-getting-rekt-by-impermanent-loss-7c9510cb2f22)


# How to Add/Remove Liquidity

"Liquidity" is central to how Hopium Exchange works. You can add liquidity for any token pair by staking both through the Liquidity page. In return for adding liquidity, you'll receive trading

## **Add Liquidity**

To provide liquidity, you’ll need to commit an amount of any token pair you like. Your lowest value (in USD) of the two tokens will be the limit to the liquidity you can provide.

You can easily trade for any tokens you need. Visit our How to Trade on Hopium guide if you need to.

In this example, we will add liquidity using GDCC and Hope.<br>

1\. Visit the [Liquidity page](https://app.hopium.finance/).

2\. Click the **Add Liquidity** button.

3\. For the top Input, click 'Select a currency'. Then choose one of the token in the liquidity pair you want to add liquidity to. Here, we are gong to use GDCC as an example.

4\. For the bottom input, click ‘Select a currency’. And choose the other token in the liquidity pair you want to add liquidity to. Here, we are gong to use Hope as an example.

5\. Enter an amount on one of the tokens under “Input”. The other should be calculated and filled automatically.

(If one of the token does not have enough balance. You will see an error and the button being greyed out. Please enter a lower amount to proceed.)

6\. Click the **Enable Hope** button. If you are adding liquidity against tokens other than GDCC, you might need to click enable twice for each token in your pair. Your wallet will ask you to confirm the action.

7\. The **Supply** button will then light up. Click to proceed.

8\. Your wallet will ask you for confirmation. Confirm your transaction from your wallet.

9\. Soon after, you will see your LP Token balance at the bottom of the page.

You can repeat the above steps to add more liquidity, or add liquidity to different pairs.

### **Removing liquidity**

To remove liquidity.

1\. Visit the [Liquidity page](https://app.hopium.finance/)**.**

2\. Click on the pair you want to remove liquidity from under “Your Liquidity".

3\. Click **Remove**. A new modal will appear.

4\. Use the buttons or slider to choose how much liquidity you want to remove. Choose **MAX** to remove all of your liquidity from this pair.

5\. Click **Enable**. Your wallet will ask you to sign the actio&#x6E;**.**

6\. The **Remove** button will light up. Click to proceed.

7\. A window will appear showing how much token you will receive. Click **Confirm**. Your wallet will ask you to confirm the action.

8\. After the transaction is confirmed. You will receive two of the tokens from your pair. And if you haven't remove all of your liquidity, your remaining liquidity value will be updated on "My Liquidity" page.


# Hopium Locker

Hopium Locker is the most affordable, secure and intuitive liquidity locker for GDCC / GDCC-20 tokens. It can be used to easily lock liquidity created on Hopium.

### Connecting Wallet

Wallets like Metamask will be detected and connected to automatically. For other wallets, please click on "Connect Wallet" button.

![](/files/emRuHlHFsYx6xhJTBRki)

Once connected, it will show the connected account. In case of problems, please refresh the page.

![](/files/nU0e6OBfR2tgnuf4VrAB)

### Lock

You can lock your liquidity on Hopium for GDCC/ GDCC-20 tokens easily using Hopium Locker. Please ensure that your wallet is connected (see previous section)

![](/files/GoifI7dpUs0JTxb4u7zy)

![](/files/JH84zpjgPTS4aMWMa9jB)

![](/files/RD4UPEjNuEMzTT1TJ9zI)

### Hopium Locks

You can withdraw, increase, extend and transfer your locked liquidity in an amazingly simple way with [Hopium Locker](https://app.hopium.finance/locker)

![](/files/BKInZyaEle0zmAqMopnz)

#### Unlock

You can unlock and withdraw your LP tokens once the unlock time is reached. There is no fee for unlocking tokens.

![](/files/RvfTDIvHxqs1u9nJKTYf)

#### Extend Lock Time

You can extend your lock period by setting a new time. There is no fee for extending lock period.

![](/files/fiIIYqUUfZnXIBs5RPNh)

#### Increase Lock Amount

You can increase the amount of LP tokens locked.

![](/files/feRD2GNlJG42QmBcfSQ3)

#### Transfer Ownership.

You can transfer the lock ownership. The new owner will be able to manage the lock. You will no longer be able to manage it.

![](/files/RVBbMNYshYqkDDWMWLGL)

### Manage Locks

You can browse through all the tokens that are currently locked with Manage Locker.

### FAQs

#### &#x20;Is Hopium LP Locker secure?

Absolutely, 100+ projects are using the Hopium LP locker, you can [browse](https://app.hopium.finance/) through all the current locks.

#### &#x20;What is the advantage of Hopium LP Locker?

Hopium Locker is the most affordable solution in the market. It has the most intuitive user interface to create and your manage lock. It is very secure and has no hidden agenda like promoting a utility token that many other lock providers have.

#### &#x20;Is there a way to withdraw liquidity before unlock time?

There is absolutely no way to withdraw liquidity before unlock time from Hopium Locker.

#### &#x20;What will happen when a new version of Hopium is released?

Hopium Locker supports migration to a new version of Hopium.

#### &#x20;What is the recommended lock period?

Hopium Locker recommends at least an 24 hours and ideally a 1 - or 2 -year lock period to provide necessary confidence to the investors.

#### &#x20;What is the recommended lock amount?

Hopium Locker recommends at least 80% of liquidity is locked.

#### &#x20;Why liquidity should be locked at all?

Locking liquidity provides the confidence to the investors that the token developers will not withdraw and run away with the liquidity money. This is now a standard practice that all token developers follow.


# Smart Contracts

This page provides links or locations for Hopium's smart contracts.

## Factory Contract info

**Contract name:** HopiumFactory\
**Contract address:** 0x95eF9160eAf07b5F47E758B6dC79Cc3076d8272B

View HopiumFactory.sol on GitHub.

View the Hopium: Factory contract on [GdccScan](https://www.gdccscan.io/address/0x95eF9160eAf07b5F47E758B6dC79Cc3076d8272B/contracts).

## Router Contract info

Hopium is based on pancake. Read the hopium documentation.\
For more in-depth information on the core contract logic, read the Hopium Core whitepaper.

**Contract name:** HopiumRouter\
**Contract address:** 0x98fB5C40B24C1759469DFE0c5436888422Ac3c8c

View HopiumRouter.sol on GitHub.

View the Hopium: Router contract on [GdccScan](https://www.gdccscan.io/address/0x98fB5C40B24C1759469DFE0c5436888422Ac3c8c/contracts).

## Lockup Contract info

**Contract name:** Lockup\
**Contract address:** 0x7548279357C88574451742A1d40683051888c623

View Lockup.sol on GitHub.

View the Hopium : Lockup contract on [GdccScan](https://www.gdccscan.io/address/0x7548279357C88574451742A1d40683051888c623/contracts).


# Contact Us

#### Business Contacts

### List a Token

### Apply for an Token&#x20;

<https://docs.google.com/forms/d/e/1FAIpQLSclLThETy0CKcuQS1K7-1DY5ypeB5dLk6f-oNR9tc0LiNxU8w/viewform>

### Apply for NFT marketplace

<https://gdcc-nft-user.netlify.app/#/>

####

####


# Brand & Logos

Guidlines and downloadable assets like the Hopium logo SVG

## Intro <a href="#intro" id="intro"></a>

Hopium logo downloads are at the bottom of this page, but please be sure to read these guidelines first.

> Although Hopium distributes some of its technology under open-source licenses, **the Hopium and Hope brands are not distributed under the same licenses.**

The following Hopium "Brand Assets" are copyrighted material, and you may only use them in accordance with the policy detailed below:

* The Hopium and Hope logos, wordmark, icon
* The Hopium name
* Other visual assets produced by Hopium including but not limited to illustrations and 3d models

## What you may do <a href="#what-you-may-do" id="what-you-may-do"></a>

You may use Hopium's Brand Assets when you are:

* 👌 Referring to our products and services
* 👌 Linking to our official site or products, such as "Trade our token on Hopium"
* 👌 Announcing an official partnership, but only if you have **official approval** by a qualified member of the Hopium team

For information on other uses of our Brand Assets, please reach out at <info@hopium.com>

## What you may not do <a href="#what-you-may-not-do" id="what-you-may-not-do"></a>

While we strongly believe in and follow the open source ethos, **protecting the Hopium brand is extremely important for our users' security,** so that users know what is a genuine product/endorsement and what isn't.Here are a few examples of forbidden uses of our Brand Assets:

* ⛔️ **Don't use our Brand Assets in your products' name, logo, NFTs, etc.**
  * For example, making an app called "Hopium Engine" or "HOPE Child" are not allowed.
  * Don't use the Hopium logo in whole or in part as part of your products' logos, marketing material, website, or other.
  * Logos with a strong resemblence to the Hopium Icon are also forbidden.
* ⛔️ **Don't use our Brand Assets to create digital or physcial products for sale, including but not limited to**
  * Merchandise ("Swag")
  * NFTs
  * Other products
* ⛔️ **Don't create derivative names that imply official endorsement** For example, don't make a social media group called "Hopium Italy" - this sounds official. "Hopium Fans of Italy" may be permitted.
* ⛔️ **Don't change or adapt our Brand Assets in any way** Use the logos and other assets exactly as provided. Do not change the colors, reassemble, abbreviate, or change these assets in any way.

Use your common sense and creativity. If you want to make something relating to the Hopium ecosystem, make it your own.Have fun making a unique brand that's clearly yours -- if your product is strong, you won't need to rely on remixing Hopium's brand.


# Social Accounts & Communities

Here you'll find a list of Hopium's official Social media channels and communities. If English is not your first language, we have a number of non-English communities that would love to have you join

## 🐦 Twitter

<https://twitter.com/HopiumFinance>

## 🤳 Instagram

<https://www.instagram.com/hopiumfinance/>

## 📰Facebook

<https://www.facebook.com/HopiumFinance/>


# Customer Support

There is NO customer support for Hopium.

If you're experiencing issues,

1. First check the troubleshooting page for your error code
2. If you can't find a solution, try reaching out in your local Telegram group.

{% hint style="danger" %}
Admins will NEVER send you a direct message. If anybody approaches you directly on e.g. Telegram pretending to represent customer support, please block them and report as spam.
{% endhint %}

{% hint style="danger" %}
**NEVER, under any situation, should you ever give someone your private key or recovery phrases. Immediately block and report anyone that asks for them.**
{% endhint %}


# Troubleshooting Errors

Sometimes you may find yourself facing a problem that doesn't have a clear solution. These troubleshooting tips may help you solve problems you run into.

## **Issues on the Exchange**

### **INSUFFICIENT\_OUTPUT\_AMOUNT**

> The transaction cannot succeed due to error: HopiumRouter: INSUFFICIENT\_OUTPUT\_AMOUNT. This is probably an issue with one of the tokens you are swapping.
>
> the transaction cannot succeed due to error: execution reverted: Hopiumrouter: insufficient\_output\_amount.

You're trying to swap tokens, but your slippage tolerance is too low or liquidity is too low.

{% tabs %}
{% tab title="Solution" %}

1. Refresh your page and try again later.
2. Try trading a smaller amount at one time.
3. Increase your slippage tolerance:
   1. Tap the settings icon on the liquidity page.
   2. Increase your slippage tolerance a little and try again.&#x20;
4. Lastly, try inputting an amount with fewer decimal places.
   {% endtab %}

{% tab title="Reason" %}
**This usually happens when trading tokens with low liquidity.**

That means there isn't enough of one of the tokens you're trying to swap in the Liquidity Pool: it's probably a small-cap token that few people are trading.

However, there's also the chance that you're trying to trade a scam token which cannot be sold. In this case, Hopium isn't able to block a token or return funds.
{% endtab %}
{% endtabs %}

### **INSUFFICIENT\_A\_AMOUNT or INSUFFICIENT\_B\_AMOUNT**

> Fail with error 'HopiumRouter: INSUFFICIENT\_A\_AMOUNT'\
> or\
> Fail with error 'HopiumRouter: INSUFFICIENT\_B\_AMOUNT'

You're trying to add/remove liquidity from a liquidity pool (LP), but there isn't enough of one of the two tokens in the pair.

{% tabs %}
{% tab title="Solution" %}
**Refresh your page and try again, or try again later.**

Still doesn't work?

1. Tap the settings icon on the liquidity page.
2. Increase your slippage tolerance a little and try again.
   {% endtab %}

{% tab title="Reason" %}
The error is caused by trying to add or remove liquidity for a liquidity pool (LP) with an insufficient amount of token A or token B (one of the tokens in the pair).

It might be the case that prices are updating too fast when and your slippage tolerance is too low.

![](https://lh5.googleusercontent.com/T1KMtz2ILDVHljGw1iLbIv0W1KVl7qXL8zU2nLFHkUvDb5oMw9mpUzzBwWmIBz15XDsxZ5w7wsaqAwCs_pxdobz_kY_7BhcZhYtpqWuQGFs23DZq98-SVInlfsS07WzxFPLIYXHt)

![](https://lh5.googleusercontent.com/7aspaCCvDjzxbJxngqwgeq737LB3OUNcAs592QqlEkyrAOTfKsrt_FAwpEylaIJhff5ZcYlzB_r0v1JZwfj3j8Ah6jlUbRoMrAqVfTb3cwDI7B1i5HJtZSQOsTPrv7l7SaclC3BV)
{% endtab %}

{% tab title="Solution for nerds" %}
OK, so you're really determined to fix this. We really don't recommend doing this unless you know what you're doing.

There currently isn't a simple way to solve this issue from the Hopium website: you'll need to interact with the contract directly. You can add liquidity directly via the Router contract, while setting amount A Min to a small amount, then withdrawing all liquidity.

#### **Approve the LP contract**

Head to the contract of the LP token you're trying to approve.\
For example, here's the TokenA/WGdcc pair:&#x20;

1. Select **Write Contract**, then **Connect to Web3** and connect your wallet.&#x20;
2. In **section "1. approve",** approve the LP token for the router by entering
   1. spender (address): enter the contract address of the LP token you're trying to interact with
   2. value (uint256): -1

#### Query "balanceOf"

1. Switch to **Read Contract.**
2. In **5. balanceOf**, input your wallet address and hit **Query**.
3. Keep track of the number that's exported. It shows your balance within the LP in the uint256 format, which you'll need in the next step.

#### Add or Remove Liquidity

Head to the router contract

1. Select **Write Contract** and **Connect to Web3** as above.
2. Find **addLiquidity** or **removeLiquidity** (whichever one you're trying to do)
3. Enter the token addresses of both of the tokens in the LP.
4. In **liquidity (uint256),** enter the uint256 number which you got from "balanceOf" above.
5. Set a low **amountAMin** or **amountBMin**: try 1 for both.
6. Add your wallet address in **to (address)**.
7. Deadline must be an epoch time greater than the time the tx is executed.

{% hint style="warning" %}
This can cause very high slippage, and can cause the user to lose some funds if frontrun
{% endhint %}
{% endtab %}
{% endtabs %}

### HopiumRouter: EXPIRED

> The transaction cannot succeed due to error: HopiumRouter: EXPIRED. This is probably an issue with one of the tokens you are swapping.

Try again, but confirm (sign and broadcast) the transaction as soon as you generate it.

This happened because you started making a transaction, but you didn't sign and broadcast it until it was past the deadline. That means you didn't hit "Confirm" quickly enough.

### Hopium: K

> The transaction cannot succeed due to error: Hopium: K. This is probably an issue with one of the tokens you are swapping.

Try modifying the amount on “To” field. Therefore putting "(estimated)" symbol on “From”. Then initiate the swap immediately.

This usually happen when you are trying to swap a token with its own fee.

### Hopium: TRANSFER\_FAILED

> The transaction cannot succeed due to error: execution reverted: Hopium: TRANSFER\_FAILED.

Make sure you have 30% more tokens in your wallet than you intend to trade, or try to trade a lower amount. If you want to sell the maximum possible, try 70% or 69% instead of 100%.\
Caused by the design of Restorative Rebase tokens like coinA or CoinB.\
Understand how restorative rebase tokens work.

Another possible cause of this issue is the malicious token issuer just suspended the trading for their token. Or they made selling action only possible for selected wallet addresses. Please always do your own research to avoid any potential fraud. If the token you are trying to swap but failed with this error code is coming from an airdrop, that is most likely a scam. Please do not perform any token approval or follow any links, your fund may be at risk if you try to do so.

### Transaction cannot succeed

Try trading a smaller amount, or increase slippage tolerance via the settings icon and try again. This is caused by low liquidity.

### **Price Impact too High**

Try trading a smaller amount, or increase slippage tolerance via the settings icon and try again. This is caused by low liquidity.

### estimateGas failed

> This transaction would fail. Please contact support

{% tabs %}
{% tab title="Solution" %}
**If you got this error while removing liquidity from a BNB pair:**

Please select "Receive WBNB" and retry.

**If you got this error while trying to swap:**

Please contact the project team of the token you're trying to swap. \*\*\*\* This issue must be resolved by the project team.
{% endtab %}

{% tab title="Reason" %}
**This issue (while swapping) is caused by tokens which have hard-coded the Hopium router into their contract.**

While this practice is ill-advised at best, the reason for these projects having done this appears to be due to their tokenomics, in which each purchase sends a % of the token to LPs.

The projects affected will likely not work with the  router: they will most likely need to create new versions of their tokens pointing to our new router address, and migrate any existing token holders to their new token.

We recommend that any projects which created such tokens should also make efforts to prevent their users from adding them to  LP.
{% endtab %}
{% endtabs %}

### **Execution reverted: TransferHelper: TRANSFER\_FROM\_FAILED.**

> The transaction cannot succeed due to error: execution reverted: TransferHelper: TRANSFER\_FROM\_FAILED.

When trying to swap tokens, the transaction fails and this error message is displayed. This error has been reported across platforms.

{% tabs %}
{% tab title="Solution" %}

1. Check to make sure you have sufficient funds available.
2. Ensure you have given the contract allowance to spend the amount of funds you're attempting to trade with.
   {% endtab %}

{% tab title="Reason" %}
This error happens when trading tokens with insufficient allowance, or when a wallet has insufficient funds.\
If you're trading tokens with Restorative Rebase like tau assets coinA or coinB, make sure you understand how they work first with this guide to Rebase tokens.
{% endtab %}
{% endtabs %}


# Career

Interested in joining the Hopium team? If you're passionate, dedicated, and a fan of all things , we'd love to hear from you!

Check out the positions available for more information. Nothing there that suits your talents? Check back later. We'll have more openings in the future.&#x20;


