UmiaUmia Docs

Spot Market Fees

How swap fees are collected and shared on Uniswap V4 pools

When a CCA auction completes and the Uniswap V4 pool goes live, every swap on that pool can charge a protocol fee. This fee is collected automatically by a V4 hook attached to the pool and sent to a configurable recipient.

Fee parameters

Two parameters control the fee, both set at qOrg creation and immutable after deployment:

ParameterWhat it controlsConstraints
feeBpsFee rate in basis points, applied to swap output0–100 bps (0–1%)
feeRecipientAddress that receives all collected feesCannot be address(0)

Setting feeBps to 0 disables fee collection entirely — the hook becomes a no-op on swaps.

How fees are collected

The pool's hook implements Uniswap V4's afterSwap callback. On every swap:

  1. The hook calculates the fee as a percentage of the unspecified token amount (output for exact-input swaps, input for exact-output swaps)
  2. The fee is minted as an ERC6909 claim inside the Uniswap V4 PoolManager
  3. Claims accumulate until someone triggers a withdrawal

For exact-input swaps the fee is taken from the output side; for exact-output swaps the fee is taken from the input side.

Claiming fees

Anyone can call claimFees(currency) on the LBP contract at any time. This:

  1. Burns the accumulated ERC6909 claims from the PoolManager
  2. Transfers the underlying tokens to feeRecipient
  3. Emits a FeesCollected event

There is no access control on claiming — it's a permissionless operation that always sends to the same recipient.

Fee sharing between Umia and projects

Since feeRecipient is a single address, fee sharing is handled at the recipient level rather than in the hook itself. The recommended approach:

  1. Deploy a revenue-splitting contract (e.g. 0xSplits) with the desired split between Umia and the project
  2. Set that splitter contract as the feeRecipient when creating the qOrg
  3. Fees flow to the splitter, which distributes according to its configured ratios

This keeps the hook simple and gas-efficient while allowing arbitrary split configurations — 50/50, 80/20, or any other ratio — without requiring changes to the core contracts.

Fees vs. qOrg share

These are two separate revenue streams that should not be confused:

Revenue typeSourceWhen it appliesParameter
qOrg shareCurrency raised in the CCAOnce, at pool migrationqorgBps
Swap feesOngoing trading volumeEvery swap after launchfeeBps

The qOrg share is a one-time cut of the auction proceeds, transferred directly to the qOrg treasury when the pool is created. Swap fees are ongoing and flow to feeRecipient (which may or may not be the qOrg itself).

Setting up fees

When creating a qOrg through UmiaHub, include the fee parameters in CreateQOrgParams:

CreateQOrgParams({
    // ... other params
    feeRecipient: 0x..., // splitter contract or direct recipient
    feeBps: 50,          // 0.5% of swap output
    // ...
})

These values are forwarded through the LBP factory to the hook contract and cannot be changed after deployment. Choose carefully — the fee rate and recipient are permanent for the lifetime of the pool.