> ## Documentation Index
> Fetch the complete documentation index at: https://docs.saucerswap.finance/llms.txt
> Use this file to discover all available pages before exploring further.

# Swap Tokens for HBAR

> Swap HTS fungible tokens for HBAR

Below are two methods available to swap tokens for HBAR:

* [Swap exact tokens for HBAR](/v/developer/saucerswap-v2/swap-operations/swap-tokens-for-hbar#swap-exact-tokens-for-hbar)
* [Swap tokens for exact HBAR](/v/developer/saucerswap-v2/swap-operations/swap-tokens-for-hbar#swap-tokens-for-exact-hbar)

<Info>
  **Contract ID:** [SaucerSwapV2SwapRouter](https://hashscan.io/mainnet/contract/0.0.3949434)
</Info>

<Note>
  Consider the token's decimal places when determining input and output values.

  Input and output amounts passed to the solidity function should all be in the token's smallest unit. For the SAUCE token, which has 6 decimal places, an input of 123.45 SAUCE should be entered as 123450000 (123.45 multiplied by 10^6).
</Note>

<Note>
  Granting an spender allowance to the router contract **is required** when the input token is not native HBAR for security reasons enforced at the native code layer. Ensure that the allowance amount is in token's smallest unit.
</Note>

<Tip>
  When providing HBAR in the path array, use the Wrapped HBAR token ID ([WHBAR](https://hashscan.io/mainnet/token/0.0.1456986)).
</Tip>

***

## Swap Exact Tokens for HBAR

Swap an exact amount of tokens for a minimum HBAR amount.

Solidity function name: **exactInput**

| Struct Parameter Name      | Description                                                 |
| -------------------------- | ----------------------------------------------------------- |
| *bytes path*               | A bytes array representing a route path including fees data |
| *address recipient*        | EVM address of the token recipient                          |
| *uint256 deadline*         | Deadline in Unix seconds                                    |
| *uint256 amountIn*         | The exact input token amount in its smallest unit           |
| *uint256 amountOutMinimum* | The minimum token amount to receive in its smallest unit    |

<CodeGroup>
  ```solidity ISwapRouter.sol theme={null}
  struct ExactInputParams {
    bytes path;
    address recipient;
    uint256 deadline;
    uint256 amountIn;
    uint256 amountOutMinimum;
  }

  function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);
  ```

  ```solidity SwapRouter.sol theme={null}
  /// @inheritdoc ISwapRouter
  function exactInput(ExactInputParams memory params)
    external
    payable
    override
    checkDeadline(params.deadline)
    returns (uint256 amountOut)
  {
    address payer = msg.sender; // msg.sender pays for the first hop

    while (true) {
      bool hasMultiplePools = params.path.hasMultiplePools();

      // the outputs of prior swaps become the inputs to subsequent ones
      params.amountIn = exactInputInternal(
        params.amountIn,
        hasMultiplePools ? address(this) : params.recipient, // for intermediate swaps, this contract custodies
        0,
        SwapCallbackData({
          path: params.path.getFirstPool(), // only the first pool in the path is necessary
          payer: payer
        })
      );

      // decide whether to continue or terminate
      if (hasMultiplePools) {
        payer = address(this); // at this point, the caller has paid
        params.path = params.path.skipToken();
      } else {
        amountOut = params.amountIn;
        break;
      }
    }

    require(amountOut >= params.amountOutMinimum, 'Too little received');
  }
  ```
</CodeGroup>

<Warning>
  Set the minimum output token amount (**amountOutMinimum**) with caution.

  A high minimum might lead to a swap failure due to insufficient liquidity or rapid price movements. Conversely, setting the minimum too low can expose you to significant slippage, potentially resulting in a financial loss as you might receive far fewer tokens than expected.
</Warning>

<Tip>
  The data passed to the 'path' parameter follows this format: \[token, fee, token, fee, token, ...], with each 'token' in the route being 20 bytes long and each 'fee' being 3 bytes long. Example, 0x0001F4 for a 0.05% fee.
</Tip>

<Tip>
  Include **unwrapWHBAR** function in your call to convert the Wrapped HBAR (WHBAR) output token back into the native HBAR cryptocurrency following the swap.
</Tip>

<Note>
  For the ExactInputParams **recipient**, use the SwapRouter contract address. This is required for unwrapWHBAR to function correctly. The unwrapped HBAR will then be sent to the user's recipient address.

  When the output token is not HBAR, use the user's address as the **recipient** instead.
</Note>

### Code Overview

<Tabs>
  <Tab title="JavaScript SDK">
    **Resources:**

    * [SaucerSwap deployed contract IDs](/developerx/contract-deployments)
    * [Ethers.js docs (v6)](https://docs.ethers.org/v6/)
    * [Hedera JavaScript SDK](https://github.com/hashgraph/hedera-sdk-js)
    * [Token approve allowance](https://docs.hedera.com/hedera/sdks-and-apis/sdks/cryptocurrency/approve-an-allowance)

    *Note: The Hedera JavaScript SDK currently does not support passing complex contract function parameters. Instead, use Ethers.js or Web3.js to obtain the encoded function data and pass that data as a function parameter.*

    ```typescript Typescript theme={null}
    import * as ethers from 'ethers'; //V6
    //import {..} from @hashgraph/sdk

    //Client pre-checks:
    // - Router contract has spender allowance for the input token

    //load ABI data containing SwapRouter, PeripheryPayments and Multicall functions
    const abiInterfaces = new ethers.Interface(abi); 

    //ExactInputParams
    const params = {
      path: routeDataWithFee, //'0x...'
      recipient: swapRouterAddress, //'0x...' - use the SwapRouter id here for unwrapWHBAR to work
      deadline: deadline, //Unix seconds
      amountIn: inputAmount, //in token's smallest unit
      amountOutMinimum: outputTinybarMin //in Tinybar
    };

    //encode each function individually
    const swapEncoded = abiInterfaces.encodeFunctionData('exactInput', [params]);

    //Provide the user's address to receive the unwrapped HBAR
    const unwrapEncoded = abiInterfaces.encodeFunctionData('unwrapWHBAR', [0, recipient]); 

    //multi-call parameter: bytes[]
    const multiCallParam = [swapEncoded, unwrapEncoded];

    //get encoded data for the multicall involving both functions
    const encodedData = abiInterfaces.encodeFunctionData('multicall', [multiCallParam]);  

    //get encoded data as Uint8Array
    const encodedDataAsUint8Array = hexToUint8Array(encodedData);

    const response = await new ContractExecuteTransaction()
     .setContractId(swapRouterContractId)
     .setGas(gasLim)
     .setFunctionParameters(encodedDataAsUint8Array)
     .execute(client);
     
    const record = await response.getRecord(client);
    const result = record.contractFunctionResult!;
    const values = result.getResult(['uint256']);
    const amountOut = values[0]; //uint256 amountOut - Tinybar
    ```
  </Tab>
</Tabs>

***

## Swap Tokens for Exact HBAR

Swap a maximum amount of tokens to receive an exact HBAR amount.

Solidity function name: **exactOutput**

| Schema Parameter Name     | Description                                                 |
| ------------------------- | ----------------------------------------------------------- |
| *bytes path*              | A bytes array representing a route path including fees data |
| *address recipient*       | EVM address for the token recipient                         |
| *uint256 deadline*        | Deadline in Unix seconds                                    |
| *uint256 amountOut*       | The exact output amount to receive in its smallest unit     |
| *uint256 amountInMaximum* | The maximum allowed input amount in its smallest unit       |

<CodeGroup>
  ```solidity ISwapRouter.sol theme={null}
  struct ExactOutputParams {
    bytes path;
    address recipient;
    uint256 deadline;
    uint256 amountOut;
    uint256 amountInMaximum;
  }

  /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)
  /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata
  /// @return amountIn The amount of the input token
  function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);
  ```

  ```solidity SwapRouter.sol theme={null}
  /// @inheritdoc ISwapRouter
  function exactOutput(ExactOutputParams calldata params)
    external
    payable
    override
    checkDeadline(params.deadline)
    returns (uint256 amountIn)
  {
    // it's okay that the payer is fixed to msg.sender here, as they're only paying for the "final" exact output
    // swap, which happens first, and subsequent swaps are paid for within nested callback frames
    exactOutputInternal(
      params.amountOut,
      params.recipient,
      0,
      SwapCallbackData({path: params.path, payer: msg.sender})
    );

    amountIn = amountInCached;
    require(amountIn <= params.amountInMaximum, 'Too much requested');
    amountInCached = DEFAULT_AMOUNT_IN_CACHED;
  }
  ```
</CodeGroup>

<Warning>
  Set the maximum input token amount (**amountInMaximum**) with caution.

  A low maximum might lead to a swap failure if the required liquidity surpasses this limit or due to rapid price movements. Conversely, setting it too high can expose you to significant slippage, potentially leading to a financial loss as you might spend far more tokens than expected.
</Warning>

<Tip>
  The data passed to the 'path' parameter follows this format: \[token, fee, token, fee, token, ...], but **reversed** (i.e. the first token in the array should be output token), with each 'token' in the route being 20 bytes long and each 'fee' being 3 bytes long. Example, `0x000BB8 (3000)` for a 0.30% fee.
</Tip>

<Tip>
  Include **unwrapWHBAR** function in your call to convert the Wrapped HBAR output token back into the native HBAR cryptocurrency following the swap.
</Tip>

<Note>
  For the ExactInputParams **recipient**, use the SwapRouter contract address. This is required for unwrapWHBAR to function correctly. The unwrapped HBAR will then be sent to the user's recipient address.

  When the output token is not HBAR, use the user's address as the **recipient** instead.
</Note>

### Code Overview

<Tabs>
  <Tab title="JavaScript SDK">
    **Resources:**

    * [SaucerSwap deployed contract IDs](/developerx/contract-deployments)
    * [Ethers.js docs (v6)](https://docs.ethers.org/v6/)
    * [Hedera JavaScript SDK](https://github.com/hashgraph/hedera-sdk-js)
    * [Token approve allowance](https://docs.hedera.com/hedera/sdks-and-apis/sdks/cryptocurrency/approve-an-allowance)

    *Note: The Hedera JavaScript SDK currently does not support passing complex contract function parameters. Instead, use Ethers.js or Web3.js to obtain the encoded function data and pass that data as a function parameter.*

    ```typescript Typescript theme={null}
    import * as ethers from 'ethers'; //V6
    //import {..} from @hashgraph/sdk

    //Client pre-checks:
    // - Router contract has spender allowance for the input token

    //load ABI data containing SwapRouter, PeripheryPayments and Multicall functions
    const abiInterfaces= new ethers.Interface(abi); 

    //ExactOutputParams
    const params = {
      path: routeDataWithFee, //'0x...' (reversed route path)
      recipient: swapRouterAddress, //'0x...' - use the SwapRouter id here for unwrapWHBAR to work
      deadline: deadline, //Unix seconds
      amountOut: outputTinybar, //in Tinybar
      amountInMaximum: inputAmountMax //in token's smallest unit
    };

    //encode each function individually
    const swapEncoded = abiInterfaces.encodeFunctionData('exactOutput', [params]);

    //Provide the user's address to receive the unwrapped HBAR
    const unwrapEncoded = abiInterfaces.encodeFunctionData('unwrapWHBAR', [0, recipient]);

    //multi-call parameter: bytes[]
    const multiCallParam = [swapEncoded, unwrapEncoded];

    //get encoded data for the multicall involving both functions
    const encodedData = abiInterfaces.encodeFunctionData('multicall', [multiCallParam]);  

    //get encoded data as Uint8Array
    const encodedDataAsUint8Array = hexToUint8Array(encodedData);

    const response = await new ContractExecuteTransaction()
     .setContractId(swapRouterContractId)
     .setGas(gasLim)
     .setFunctionParameters(encodedDataAsUint8Array)
     .execute(client);
     
    const record = await response.getRecord(client);
    const result = record.contractFunctionResult!;
    const values = result.getResult(['uint256']);
    const amountIn = values[0]; //uint256 amountIn
    ```
  </Tab>
</Tabs>
