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

# Fees

> Swap, flash, vault and farming fees: the units, the splits, and how to compute what a trade paid

## Two denominators, and they are not the same

| Quantity                                         | Units               | Denominator                      | Bound in the contracts                   |
| ------------------------------------------------ | ------------------- | -------------------------------- | ---------------------------------------- |
| The **swap fee** (and the flash fee)             | hundredths of a bip | `1,000,000` — so `3000` is 0.30% | under `1,000,000`; **no policy ceiling** |
| The **protocol share** of that fee               | basis points        | `10,000`                         | up to `10,000` — the **whole** fee       |
| A **vault's** operator share                     | basis points        | `10,000`                         | hard-capped at `2,000` (20%)             |
| The **farmed-fee share** on the position manager | basis points        | `10,000`                         | up to `10,000` — the whole fee           |

The rates themselves are governance parameters per deployment and per pool: read them, never hardcode them.

## The swap fee

**It lives in the pool**, as `slot0.fee`, and it is uniform across pool types:

```solidity theme={null}
function slot0() external view
    returns (uint160 sqrtPriceX96, int24 tick, uint24 fee, uint16 feeProtocol0, uint16 feeProtocol1);
function feeInfo() external view returns (uint24 fee, bool isDynamic);
```

<Warning>
  **On a dynamic pool, `fee` is what the last swap charged, not what the next one will.** The plugin resolves the rate once per swap and the pool writes it into `slot0` **without an event** — `FeeChanged` is emitted only when governance calls `setFee`. An indexer cannot follow a dynamic pool's rate from logs: read `feeInfo()`, or ask the plugin's `currentFee()` for what the next swap would pay.
</Warning>

When the default plugin's dynamic-fee module is enabled, the rate moves between two governance-set bounds with measured volatility: at zero volatility it is `baseFee`, at or above `sensitivity` it is `maxFee`, and in between it interpolates linearly. A window shorter than 60 seconds of history charges `baseFee`. The whole curve — `baseFee`, `maxFee`, `sensitivity`, `twapPeriod` — is readable as `feeCurve()` on the plugin.

## The fee coin

A pool takes its fee either in whatever coin the trade pays, or always in one named coin of the pair:

```solidity theme={null}
enum FeeToken { Paid, Token0, Token1 }   // feeToken()
```

`Paid` is the upstream behaviour and every pool's default. Under `Token0` or `Token1`, a trade selling the named coin pays the fee on its **input**, and a trade buying it pays on its **output** — so fee growth and protocol fees for that pool accrue on one side only. A pool born on non-default terms emits `FeeTokenChanged` at creation, so an indexer never has to assume.

**The `Swap` event carries no fee field** — it is byte-identical to V3's. Derive what was paid, using `feeInfo().fee` as the rate `f`:

| Mode                   | The event's amount                         | The fee paid                                       |
| ---------------------- | ------------------------------------------ | -------------------------------------------------- |
| Fee on the input side  | the positive delta is the **gross** input  | `≈ grossIn · f / 1,000,000`, in the input token    |
| Fee on the output side | the negative delta is the **net** received | `≈ net · f / (1,000,000 − f)`, in the output token |

Both are approximations of a per-step sum on concentrated pools, and every step rounds the fee up — so the exact figure is at or slightly above the rate, never below.

## The protocol share

**`feeProtocol0` and `feeProtocol1` are a share of the fee, not of the trade.** A quarter of a 0.30% fee is `2500`, and leaves traders paying 0.30%.

* **Which of the two applies is decided by the fee coin**, not by the input coin: the fee accrues on one side, and that side's share is the one charged.
* **The maximum is the whole fee.** There is no half-the-fee ceiling — a governance call can route all of it away from liquidity providers, which is why the per-pool setter sits behind the slow governance key rather than a role.
* **A pool copies the factory default once, when it is created.** Changing the default moves later pools only; an existing pool changes only through `setFeeProtocol` on that pool, which emits `SetFeeProtocol`.

<Note>
  `SetFeeProtocol` is the **one event whose signature differs from Uniswap V3's**: four `uint16` fields where V3 has four `uint8`. Every other pool event — `Swap`, `Mint`, `Burn`, `Collect`, `Flash`, `Initialize` — is byte-identical. See [Events](/developers/dex/events).
</Note>

**The LP side** accrues into `feeGrowthGlobal0X128` / `feeGrowthGlobal1X128` and reaches a position the V3 way: poke with `burn(lower, upper, 0)`, then `collect`. A step that crosses with **no in-range liquidity** credits no position — that fee simply stays in the pool.

**The protocol side** accrues in `protocolFees` and leaves through:

```solidity theme={null}
function collectProtocol(address recipient, uint128 amount0Requested, uint128 amount1Requested)
    external returns (uint128 amount0, uint128 amount1);
```

The caller must hold the factory's `FEE_COLLECTOR` role, or be the factory owner, and the recipient is an argument rather than a stored treasury. **Draining a side pays one unit less** so the storage slot is never cleared — the returned and emitted amounts already reflect that, so reconcile against `CollectProtocol`, not against your own subtraction.

## Flash loans

The fee is the pool's current rate, rounded up: `fee = ceil(amount · f / 1,000,000)` per token, with the dynamic plugin consulted the same way it is for a swap.

Repayment is checked by balance delta, so a borrower may return **more** than principal plus fee — and the surplus is split exactly like the fee. `Flash` carries `paid0` and `paid1`, which is the honest figure to index; the protocol's share comes off what was actually paid, and the rest becomes fee growth for the LPs.

## Limit orders

**The module takes no fee of its own** — placing, cancelling and claiming move principal only, and an order fills at its tick price.

A resting order is a pool position owned by the plugin, so while the price sits on it, it earns ordinary swap fees. Those are **not** paid to the order's owner: anything above the escrowed principal is protocol revenue, swept by the `FEE_COLLECTOR` role through `sweepOrderFees`, and auditable from outside with `escrowedFor(fillTick, sellingToken0, spacing)`.

## Managed vaults

A vault charges its operator share **only on the swap fees its position earned and that actually arrived** — never on principal, deposits, withdrawals, or the balance over time. It is taken when the vault rebalances or compounds, booked rather than pushed, and pulled later with `claimFee(token, to)`.

* **Capped at 20%** by the vault contract itself.
* **The share and its recipient belong to the vault's own owner**, not to protocol governance; governance sets only what new vaults are born with.
* Read `feeShare()`, `feeRecipient()` and `feesOwed(recipient, token)`; watch `FeeChanged`, `FeeTaken` and `FeeClaimed`.
* **A vault takes no cut of farming rewards** — those are paid to holders in full.

## Farming

**Nothing takes a share of reward emissions.** A claim pays what the programme owes, and a reward token that charges its own transfer fee simply funds less.

What farming costs instead is fees: while a position is enrolled, the position manager keeps a governance-set share — `farmedFeeShare`, in basis points, up to the whole fee — of the swap fees that position earns.

* **Charged on collection, on a range move, and on leaving the farm**, so no ordering avoids it.
* **Only fees credited while enrolled** are ever in scope; principal never is.
* **A cut a token refuses is deferred, not reverted**: it stays in the pool position and is fetched later by a permissionless call. Read what is outstanding with `deferredFarmedFee(pool, tickLower, tickUpper, token)`.
* Events: `FarmedFeeTaken`, `FarmedFeeDeferred`, `FarmedFeeCollected`, and `FarmedFeeChanged` when governance retunes it.

## Where to read each rate

| Rate                                            | Getter                                                            |
| ----------------------------------------------- | ----------------------------------------------------------------- |
| A pool's current fee, and whether it is dynamic | `pool.feeInfo()`, `pool.slot0()`                                  |
| What the next swap would pay on a dynamic pool  | `plugin.currentFee()`, bounds in `plugin.feeCurve()`              |
| The fee coin                                    | `pool.feeToken()`                                                 |
| The protocol's share, per pool                  | `pool.slot0()` → `feeProtocol0`, `feeProtocol1`                   |
| What new pools are born with                    | `factory.defaultsOf(poolType)`, `factory.defaultProtocolShares()` |
| Uncollected protocol fees                       | `pool.protocolFees()`                                             |
| A vault's operator share                        | `vault.feeShare()`, `vault.feeRecipient()`                        |
| The farmed-fee cut                              | `positionManager.farmedFeeShare()`, `.farmedFeeRecipient()`       |

Two trust statements the contracts make plainly, worth carrying into any risk write-up: **a plugin and governance together can set a fee just short of the whole trade**, and **the protocol share can be set to the entire fee**. Both live behind governance keys, and both are readable at any moment from the getters above.
