> For the complete documentation index, see [llms.txt](https://docs.unstable.run/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.unstable.run/under-the-hood/fees-and-rewards.md).

# Fees & creator rewards

The Unstable business model is simple:

* Every swap on a launched token's pool pays a **1% fee** to the pool's LP position.
* That LP position lives in the **Unstable LP Locker**, so nobody can withdraw the underlying tokens.
* When anyone calls `collectFees(token)`, the accrued fees are pulled out and split **80% to the creator**, **20% to the platform treasury** — on both the token side and the USDT0 side.

That's it. There is no protocol fee stacked on top, no launch tax, no admin skim beyond the split. If nobody trades your token, the creator earns nothing. If your token becomes the busiest pool on Stable, the creator earns 0.8% of every dollar that changes hands, forever.

## The split, verified on-chain

The 80/20 ratio is stored as an **immutable** constant on the LP Locker contract:

```solidity
uint16 public immutable CREATOR_BPS;   // 8000 = 80%
uint16 public constant BPS_DENOM = 10_000;
```

Set once at locker deployment, provable via a single `cast call`:

```bash
cast call 0xbB027B8210E98a19d7B90929B8baA77Ec09F0f96 "CREATOR_BPS()(uint16)"
# → 8000
```

There is no setter. The split cannot be changed on the deployed locker.

## Anatomy of a collection

`collectFees(address token)` is a **permissionless** function — anyone can call it, no auth needed. The caller pays gas; the caller gets nothing extra. The funds still route to the token's fee recipient (creator slot) and the treasury slot.

Inside a single transaction:

1. **Pull.** The locker calls `NFPM.collect(...)` on the token's position, pulling every accrued fee (both USDT0 and the token itself) into the locker.
2. **Split.** For each side:
   * `creator_share = amount * 8000 / 10000`
   * `treasury_share = amount - creator_share` (absorbs rounding dust)
3. **Route.** The locker `safeTransfer`s each share to the address stored in the position's `creator` and `treasury` slots.
4. **Emit.** A `FeesCollected(token, usdtAmount, tokenAmount, creatorUsdt, creatorToken)` event lands in the tx log.

Everyone gets paid in one transaction, no escrow, no "claim window", no vesting.

## Claiming

Two ways to trigger a collection:

### As a UI user

If you're the creator or the treasury, log into the app and open the token page. In the future release, a **Claim fees** card next to the trade panel will show:

* Pending USDT0 & token amounts for each side (creator and treasury)
* A single button that fires the `collectFees` transaction

Anyone can watch that button and click it — the funds route to your on-chain slots regardless of who paid the gas.

### As a bot / script

```bash
# Preview split without touching state
cast call 0xbB027B8210E98a19d7B90929B8baA77Ec09F0f96 \
  "collectFees(address)(uint256,uint256,uint256,uint256)" \
  0xYOUR_TOKEN

# Actually claim
cast send 0xbB027B8210E98a19d7B90929B8baA77Ec09F0f96 \
  "collectFees(address)" 0xYOUR_TOKEN \
  --private-key $YOUR_PK
```

You can also automate periodic collections via a cron job or an on-chain trigger. Because the function is permissionless, a keeper doesn't need any special role.

## Changing the fee recipient

You can point the creator side at a different address at any time — for example, to a multisig, a treasury contract, or a fresh personal wallet:

```solidity
function updateCreator(address token, address newCreator) external;
```

Only the **current** creator slot can call it. Once you update, the new address gets every future collection.

```bash
cast send 0xbB027B8210E98a19d7B90929B8baA77Ec09F0f96 \
  "updateCreator(address,address)" \
  0xYOUR_TOKEN 0xNEW_RECIPIENT \
  --private-key $CURRENT_CREATOR_PK
```

The treasury side has the same mechanism (`updateTreasury(token, newTreasury)`), but that's controlled by the platform, not you.

## Rounding & dust

Because the split is integer BPS math, the creator side occasionally undershoots by 1 wei; that wei is included in the treasury side (which is computed as `amount - creator_share`). Over thousands of collections it's a rounding error worth pennies at most.

## Fee recipient at launch time

The `feeRecipient` argument on `launchToken(…)`:

* Set to `address(0)` (the default) → the creator slot becomes `msg.sender` (your wallet).
* Set to a specific address → that address becomes the creator slot from block one.

You can always update it later via `updateCreator` — the initial value just picks who receives the first collection.

## What "80% forever" actually means

* **No time limit.** The split ratio is immutable. There is no "creator fee sunset" like some launchers implement.
* **No lock-up.** Every collection settles instantly to your wallet. No vesting.
* **No dependency on Unstable's future.** Even if unstable.run went offline tomorrow, `collectFees` still works. Anyone can call it directly on the locker contract. Your fee stream is on-chain, permissionless, self-serve.

## Next

* [LP position lock](/under-the-hood/lp-lock.md) — how the LP NFT is held
* [Contract addresses](/on-chain-reference/contracts.md) — exact deployment info
* [FAQ](/resources/faq.md) — common questions about the fee model


---

# 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.unstable.run/under-the-hood/fees-and-rewards.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.
