> For the complete documentation index, see [llms.txt](https://hinkal-team.gitbook.io/hinkal/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://hinkal-team.gitbook.io/hinkal/protocol/transactions/swaps.md).

# Swaps

Hinkal Swaps allow users to swap ERC-20 tokens discreetly. To achieve this functionality, Hinkal uses relayers and the [LI.FI](https://li.fi/) aggregator API on EVM chains and on Solana, plus the [OKX](https://www.okx.com/web3/dex) DEX API on Solana. LI.FI routes each swap across the underlying DEXs and aggregators itself. Shielded Solana swaps go through OKX; Solana swaps from a Public (Proxy) account can use either LI.FI or OKX, whichever quotes better.

When a user wants to swap assets, they generate a zk-proof that they are eligible to swap a given amount of the first asset in return for the incoming amount of the second asset. From the viewpoint of outsiders, the swap transaction will be submitted from the relayer's public Ethereum address to Hinkal Pool smart contract.

In the transaction, Hinkal Pool will call the [LI.FI](https://li.fi/) router smart contract (on Solana, the LI.FI or [OKX](https://www.okx.com/web3/dex) route is executed by the Solana program) in order to swap the assets. If, for any reason, the swap fails, then the whole transaction will be reverted, so no additional commitments and nullifiers will be created.

Since the protocol implements UTXO-based model of commitments and nullifiers, the swapped amount should be known at the time of zk-proof generation. At the time of the swap transaction submission, it is unknown how many other swap transactions will be submitted in the current block.

This factor generates unpredictable slippage from the viewpoint of the user and relayer. Slippage is relative to the transaction value, whereas gas fees are not. For example, paying $1 out of $10 in gas fees amounts to 10%, but paying $1 out of $1000 is only 0.1%.\
\
Check out Hinkal's current [fee structure](broken://pages/sgX0WvO2Y3IRFQ3g6rKh) used to fairly compensate for the costs.

To tackle the following risks:

* slippage
* gas costs
* smart-contract parameter change affecting payoffs (e.g. CRV emission rate)

the Unexpected Payoffs are compensated to the user using [<mark style="color:purple;">**stealth addresses**</mark>](https://github.com/Hinkal-Protocol/Hinkal-Protocol/blob/gitdocs/docs/technical-description/smart-contracts/unexpected-relay-costs-accounting-stealth-addresses.md) generated before the transaction is submitted.

Important to mention, relayers do not have custody of the swapped assets.

The swapping process in Hinkal is similar to deposits and withdrawals but with a few notable differences. Instead of using the `SwapperM1x2x1.circom` circuit, users initiate the `SwapperM` circuit, which handles multiple tokens. Additionally, rather than calling the `_internalTransact()` function, the protocol calls `_internalRunExternalAction()`. This forwards the swap operation to `ExternalActionSwap:runAction()`. This function performs the token swap and returns the output UTXOs, which cannot be calculated off-chain due to the real-time fluctuations in token prices.

Once the UTXOs are generated, the corresponding output commitments are created on-chain and added to Hinkal’s Merkle tree. Unlike deposits and withdrawals, where output commitments are generated off-chain as part of the ZKP process, swap-related commitments are computed directly on-chain after the swap has been completed.
