> For the complete documentation index, see [llms.txt](https://docs.hann.finance/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.hann.finance/mechanics/deep-dives/stableswap.md).

# StableSwap

The two-asset StableSwap curve, dynamic fees, execution limits, and LP value during a depeg.

The Hann StableSwap pool holds USDHN and USDT. Near balanced reserves, its amplification parameter reduces price impact for trades between the two assets. As a trade consumes one side of the pool, its price impact increases. A quote reflects the current reserves, amplification, fee settings, and token precision.

## Reserves and amplification

The pool normalizes token balances to 18 decimal places before applying its two-asset invariant. USDT has 6 decimals and USDHN has 18, so their raw token amounts must be normalized before they are compared.

For positive normalized reserves `x` and `y`, let `A` be the value returned by `currentA()` and `D` the invariant. Ignoring integer rounding, the invariant used by Hann's solver satisfies:

$$
2A(x+y)+D=2AD+\frac{D^3}{4xy}
$$

At equal reserves, `D = x + y`. For a swap, the contract increases the input reserve and solves for the output reserve that preserves `D`, then applies the swap fee and token rounding.

Higher amplification makes the curve flatter near balanced reserves. It does not replenish a scarce output asset or preserve a one-to-one rate after a depeg. The pool's current `A` can also change through its configured amplification ramp.

## Dynamic fees

The base swap fee is `swapFee`; the imbalance multiplier is `offpegFeeMultiplier`. Fees use a denominator of `10,000` basis points. A `4` bps fee equals `0.04%`, but the app reads the pool's current fee rather than treating this example as a fixed rate.

When the multiplier exceeds `10,000`, the dynamic fee grows as the reserves used for the calculation move away from balance. With `f` as the base fee, `m` as the multiplier, `B = 10,000`, and `x`, `y` as the calculation's normalized balances, the continuous form is:

$$
f\_{dynamic}=\frac{mf}{B+(m-B)\frac{4xy}{(x+y)^2}}
$$

At `x = y`, the fraction `4xy/(x+y)^2` is one and the fee returns to `f`. As one side becomes small, that fraction decreases and the fee approaches `mf/B`. The contract evaluates the trade's balances with integer arithmetic; the quote includes that calculation. If `m ≤ B` or the base fee is zero, it uses the base fee.

The admin fee is a share of the swap fee. The remaining fee accrues to pool liquidity. An imbalanced deposit also incurs an imbalance fee before its LP amount is calculated.

## Exact input and exact output

The app's USDHN/USDT route has one pool hop. It supports two order types:

| Order        | Fixed amount    | Bound checked on-chain                         |
| ------------ | --------------- | ---------------------------------------------- |
| Exact input  | Amount spent    | Actual output must be at least `amountOutMin`. |
| Exact output | Amount received | Actual input must not exceed `amountInMax`.    |

For an exact-input quote of `995` tokens and a slippage tolerance of `0.5%` (`50` bps):

$$
minOut\approx995\left(1-\frac{50}{10{,}000}\right)=990.025
$$

For exact output, the corresponding maximum input is calculated by increasing the quoted input by the tolerance. Both limits are converted to the token's decimal precision. Fees are already part of the quote; the slippage setting permits movement between that quote and execution.

The router validates factory registration, token order, and its allowed-token policy. That policy applies to router quotes, swaps, and deposits. Direct pool calls have their own pool rules; the router's allowlist is not a restriction on every contract interaction.

## Deadlines and transaction failure

A deadline is the latest timestamp at which the swap or liquidity transaction can execute. An expired deadline, an unmet output/input bound, a paused pool, insufficient liquidity, or an unsupported transfer-fee token makes the relevant transaction revert.

A quote does not reserve liquidity. Other trades can change balances before your transaction executes. A deadline limits the time window; a minimum output or maximum input limits the permitted execution result.

Reversion rolls back the transaction's pool changes and token transfers. An approval confirmed in an earlier transaction remains set, and the failed transaction consumes network gas.

## What LP tokens represent

LP tokens represent a share of the pool's balances after fee accounting. If you hold fraction `s` of the LP supply, a proportional withdrawal returns approximately `s` times each available reserve, subject to token rounding and the minimum amounts you supplied.

The app's withdrawal burns LP tokens and returns both USDHN and USDT. A contract-level one-coin withdrawal is a different operation with curve and fee effects; the app's proportional withdrawal does not select a single asset. Proportional removal remains available when the pool is paused.

The pool's virtual price is derived from `D` per LP token. It measures normalized pool value under the invariant, not the assets' external dollar prices. It cannot guarantee a dollar value during a depeg.

Staked LP tokens keep this pool exposure. RewardStaker tracks the staked balance and accrued rewards; claiming rewards does not change the pool assets represented by those LP tokens.

## How a depeg changes the pool

If USDHN trades below USDT in the wider market, traders can buy the cheaper USDHN elsewhere and sell it into the pool for USDT. USDHN reserves rise and USDT reserves fall. LPs hold more of the weaker asset.

If USDHN trades above USDT, traders can buy USDHN from the pool with USDT and sell it elsewhere. USDHN reserves fall and USDT reserves rise. LPs hold less of the asset that has appreciated.

### Two pool-balance examples

Start with `1,000,000` USDHN and `1,000,000` USDT, each priced at `$1`. A `10%` LP share represents `100,000` of each token, worth `$200,000`.

The following calculations use the stated ending balances and a fixed `10%` share. Those balances are example inputs, not a curve-derived trade forecast; fees and other LP deposits or withdrawals are excluded.

| Value                                | USDHN falls to `$0.90`                      | USDHN rises to `$1.05`                      |
| ------------------------------------ | ------------------------------------------- | ------------------------------------------- |
| Ending pool balances                 | `1,800,000` USDHN + `200,000` USDT          | `200,000` USDHN + `1,800,000` USDT          |
| Your `10%` share                     | `180,000` USDHN + `20,000` USDT             | `20,000` USDHN + `180,000` USDT             |
| Value of the share                   | `180,000 × $0.90 + 20,000 × $1 = $182,000`  | `20,000 × $1.05 + 180,000 × $1 = $201,000`  |
| Value of holding the original tokens | `100,000 × $0.90 + 100,000 × $1 = $190,000` | `100,000 × $1.05 + 100,000 × $1 = $205,000` |
| Difference from holding              | `−$8,000`                                   | `−$4,000`                                   |

The difference comes from the change in token composition. A withdrawal's minimum token amounts limit quantities, not their market prices. Pool fees and staking rewards must be evaluated alongside that exposure.

For the actual app steps, see [Swap, bridge, and liquidity](/protocol/stableswap-dex.md). [Zappers](/protocol/zapper.md) covers authorization and combined LP operations.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.hann.finance/mechanics/deep-dives/stableswap.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
