> ## 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 HBAR for Tokens

> Swap HBAR for HTS fungible tokens

Below are two methods available to swap HBAR for tokens:

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

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

<Note>
  Consider the token's decimal places when determining the output amount.
</Note>

<Note>
  The output values should 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>

<Warning>
  Ensure that the "**to**" account has the output token id associated prior to executing the swap. Failure to do so will result in a TOKEN\_NOT\_ASSOCIATED\_TO\_ACCOUNT error.
</Warning>

<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 HBAR for Tokens

Swap an exact amount of HBAR for a minimum token amount

Solidity function name:  **exactInput**

| Struct Parameter Name | Description                                                 |
| --------------------- | ----------------------------------------------------------- |
| *bytes path*          | A bytes array representing a route path including fees data |
| *recipient*           | EVM address of the token recipient                          |
| *deadline*            | Deadline in Unix seconds                                    |
| *amountIn*            | The exact input token amount in its smallest unit           |
| *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>
  It is recommended to include **refundETH** in the multicall in case excess HBAR was sent to the contract.
</Tip>

<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 (500) for a 0.05% fee.
</Tip>

### Code Overview

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

    * [SaucerSwap deployed contract IDs](/developerx/contract-deployments)
    * [Hedera JavaScript SDK](https://github.com/hashgraph/hedera-sdk-js)
    * [Ethers.js docs (v6)](https://docs.ethers.org/v6/)
    * [Associate tokens to an account](https://docs.hedera.com/hedera/sdks-and-apis/sdks/token-service/associate-tokens-to-an-account)

    *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 {
      ContractExecuteTransaction,
      TokenAssociateTransaction, 
      .. 
    } from '@hashgraph/sdk';

    //Client pre-checks:
    // - Output token is associated

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

    //ExactInputParams
    const params = {
      path: routeDataWithFee, //'0x...'
      recipient: recipientAddress, //'0x...' - user's recipient address
      deadline: deadline, //Unix seconds
      amountIn: inputTinybar, //in Tinybar
      amountOutMinimum: outputAmountMin//in token's smallest unit
    };

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

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

    //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()
     .setPayableAmount(Hbar.from(inputTinybar, HbarUnit.Tinybar))
     .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
    ```
  </Tab>
</Tabs>

***

## Swap HBAR for Exact Tokens

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

Solidity function name: **exactOutput**

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

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

  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>
  Ensure that the **refundETH** is included in the multicall so that any excess payable HBAR amount, up to the maximum amount, is refunded to the sender.
</Warning>

<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>

### 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)
    * [Associate tokens to an account](https://docs.hedera.com/hedera/sdks-and-apis/sdks/token-service/associate-tokens-to-an-account)

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

    //Client pre-checks:
    // - Output token is associated

    //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: recipientAddress, //'0x...' - user's recipient address
      deadline: deadline, //Unix seconds
      amountOut: outputAmount, //in token's smallest unit
      amountInMaximum: inputTinybarMax //in Tinybar
    };

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

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

    //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()
     .setPayableAmount(Hbar.from(inputTinybarMax, HbarUnit.Tinybar))
     .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>

###
