Adding Liquidity

Add liquidity to an existing HBAR/token liquidity pool.

Outlined below are two methods to add liquidity to an existing pool on SaucerSwap:

To create a new liquidity pool, see Creating a new liquidity pool.

Ensure that the client has the LP token associated before adding liquidity.

A spender allowance for the Router contract is required for HTS tokens.

Both addLiquidityETH and addLiquidity support HTS tokens containing custom fees.


Adding HBAR/Token Liquidity

Add more liquidity to an existing HBAR/token liquidity pool.

Function name: addLiquidityETH

Recommended gas: 240,000 gwei (~ $0.020 USD)

Parameter NameDescription

address token

EVM address of the token to pool with HBAR

uint amountTokenDesired

The maximum token amount in its smallest unit

uint amountTokenMin

The minimum token amount in its smallest unit

uint amountETHMin

The minimum HBAR amount in its smallest unit

address to

EVM address to receive the liquidity tokens

uint deadline

Deadline in Unix seconds

Solidity Interface & Function Body
//IUniswapV2Router01.sol

function addLiquidityETH(
  address token,
  uint amountTokenDesired,
  uint amountTokenMin,
  uint amountETHMin,
  address to,
  uint deadline
) external payable returns (uint amountToken, uint amountETH, uint liquidity);
//UniswapV2Router02.sol

function addLiquidityETH(
  address token,
  uint amountTokenDesired,
  uint amountTokenMin,
  uint amountETHMin,
  address to,
  uint deadline
) external virtual override payable ensure(deadline) returns (uint amountToken, uint amountETH, uint liquidity) {
  (amountToken, amountETH) = _addLiquidity(
    token,
    whbar,
    amountTokenDesired,
    msg.value,
    amountTokenMin,
    amountETHMin
  );

  address pair = IUniswapV2Factory(factory).getPair(token, whbar);
  require(pair != address(0), "UniswapV2Router: PAIR DOES NOT EXIST");

  safeTransferToken(
    token, msg.sender, pair, amountToken
  );
  IWHBAR(WHBAR).deposit{value: amountETH}(msg.sender, pair);
  liquidity = IUniswapV2Pair(pair).mint(to);
  // refund dust eth, if any
  if (msg.value > amountETH) TransferHelper.safeTransferETH(msg.sender, msg.value - amountETH);
}

The addLiquidityETH function operates in HBAR but derives its name from Uniswap on Ethereum. This name was kept to simplify integration for developers versed in Uniswap tools.

Code Overview

Resources:

import { 
  ContractFunctionParameters, 
  ContractExecuteTransaction,
  AccountAllowanceApproveTransaction,
  TokenAssociateTransaction,
  .. 
} from '@hashgraph/sdk';

//Client pre-checks:
// - Output NFT token is associated
// - Router contract has spender allowance for the input token

const params = new ContractFunctionParameters();
params.addAddress(tokenAddress); //address token
params.addUint256(amountTokenDesired); //uint amountTokenDesired
params.addUint256(amountTokenMin); //uint amountTokenMin
params.addUint256(amountHBARMin); //uint amountETHMin
params.addAddress(toAddress); //address to
params.addUint256(deadline); //uint deadline
    
const response = await new ContractExecuteTransaction()
 .setPayableAmount(inputHbar)
 .setContractId(routerContractId)
 .setGas(gasLim)
 .setFunction('addLiquidityETH', params)
 .execute(client);
 
const record = await response.getRecord(client);
const result = record.contractFunctionResult!;
const values = result.getResult(['uint','uint','uint']);
const amountToken = values[0]; //uint amountToken
const amountHBAR = values[1]; //uint amountETH
const liqudity = values[2]; //uint liquidity

Adding Token/Token Liquidity

Add more liquidity to an existing token/token liquidity pool.

Function name: addLiquidity

Recommended gas: 240,000 gwei (~ $0.020 USD)

Parameter NameDescription

address tokenA

EVM address of the first HTS token

address tokenB

EVM address of the second HTS token

uint amountADesired

The maximum amount for the first token in its smallest unit

uint amountBDesired

The maximum amount for the second token in its smallest unit

uint amountAMin

The minimum amount for the first token in its smallest unit

uint amountBMin

The minimum amount for the second token in its smallest unit

address to

EVM address to receive the liquidity tokens

uint deadline

Deadline in Unix seconds

Solidity Interface & Function Body
//IUniswapV2Router01.sol

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);
//UniswapV2Router02.sol

function addLiquidityNewPool(
  address tokenA,
  address tokenB,
  uint amountADesired,
  uint amountBDesired,
  uint amountAMin,
  uint amountBMin,
  address to,
  uint deadline
) external virtual payable override ensure(deadline) returns (uint amountA, uint amountB, uint liquidity) {
  
  require (IUniswapV2Factory(factory).getPair(tokenA, tokenB) == address(0), "UniswapV2Router: POOL ALREADY EXISTS");
  address pair = IUniswapV2Factory(factory).createPair{value: msg.value}(tokenA, tokenB);
  
  (amountA, amountB) = _addLiquidity(tokenA, tokenB, amountADesired, amountBDesired, amountAMin, amountBMin);

  safeTransferToken(
    tokenA, msg.sender, pair, amountA
  );
  safeTransferToken(
    tokenB, msg.sender, pair, amountB
  );
  liquidity = IUniswapV2Pair(pair).mint(to);
}

Code Overview

Resources:

import { 
  ContractFunctionParameters, 
  ContractExecuteTransaction,
  AccountAllowanceApproveTransaction,
  TokenAssociateTransaction,
  .. 
} from '@hashgraph/sdk';

//Client pre-checks:
// - Output NFT token is associated
// - Router contract has spender allowance for the input tokens

const params = new ContractFunctionParameters();
params.addAddress(tokenAAddress); //address tokenA
params.addAddress(tokenBAddress); //address tokenB
params.addUint256(amountADesired); //uint amountADesired
params.addUint256(amountBDesired); //uint amountBDesired
params.addUint256(amountAMin); //uint amountAMin
params.addUint256(amountBMin); //uint amountBMin
params.addAddress(toAddress); //address to
params.addUint256(deadline); //uint deadline
    
const response = await new ContractExecuteTransaction()
 .setContractId(routerContractId)
 .setGas(gasLim)
 .setFunction('addLiquidity', params)
 .execute(client);
 
const record = await response.getRecord(client);
const result = record.contractFunctionResult!;
const values = result.getResult(['uint','uint','uint']);
const amountA = values[0]; //uint amountA
const amountB = values[1]; //uint amountB
const liquidity = values[2]; //uint liquidity

Last updated