> For the complete documentation index, see [llms.txt](https://degen-games-2.gitbook.io/degen-games-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://degen-games-2.gitbook.io/degen-games-docs/developers/fees-claims-rewards.md).

# Fees, Claims & Rewards

Fee escrow claims, fee-recipient changes, buyback vesting and holder-reward epochs.

## How fees move

1. **Accrue.** Before graduation, a coin's fees accrue on its **curve**. After graduation, they accrue on the **meme hook**.
2. **Sweep.** A sweep splits accrued fees into protocol, buyback and creator shares, credits the **fee escrow**, and locks any bought-back tokens in the **buyback vault**. Sweeps that need an internal swap are run by the protocol's sweep operator and capped by the maximum price impact.
3. **Claim.** Recipients withdraw from the escrow whenever they like.

An escrow balance of zero doesn't mean a coin earned nothing. Fees may still be waiting to be swept. For a creator's true position before graduation, add the curve's `quoteFeeBalance()` and `creatorTaxBalance()` to their escrow balance.

## Claiming from the fee escrow

The escrow keeps a **native ledger** and a **per-token ledger**. ETH coins credit the native ledger. Coins raised in an ERC-20 credit that asset's ledger. Released buyback vests credit the coin's own ledger.

```js
import { parseAbi } from "viem";

const factory = "0xa8788400ECe2342F17Faf659E2793a06bc4ad140";

// Resolve the escrow from the launch factory.
const feeEscrow = await client.readContract({
  address: factory,
  abi: parseAbi(["function feeEscrow() view returns (address)"]),
  functionName: "feeEscrow",
});

const escrowAbi = parseAbi([
  "function balanceOf(address recipient) view returns (uint256)",
  "function balanceOfToken(address recipient, address token) view returns (uint256)",
  "function claim() returns (uint256 amount)",
  "function claimToken(address token) returns (uint256 amount)",
]);

const ethOwed = await client.readContract({
  address: feeEscrow, abi: escrowAbi, functionName: "balanceOf", args: [creator],
});
if (ethOwed > 0n) {
  await wallet.writeContract({ address: feeEscrow, abi: escrowAbi, functionName: "claim" });
}

// For a USDG or stock-raised coin, claim that asset's ledger.
const usdgOwed = await client.readContract({
  address: feeEscrow, abi: escrowAbi, functionName: "balanceOfToken", args: [creator, usdg],
});
if (usdgOwed > 0n) {
  await wallet.writeContract({ address: feeEscrow, abi: escrowAbi, functionName: "claimToken", args: [usdg] });
}
```

Index `CreditedToken` / `ClaimedToken` as well as `Credited` / `Claimed`. Every non-ETH payout and every released vest lands on the token ledger.

## Changing the fee recipient

```js
const recipientAbi = parseAbi([
  "function transferCreatorFeeRecipient(address token, address newRecipient)",
]);
```

* Only the **current** recipient can call it. Anyone else gets `NotCreatorFeeRecipient`.
* It takes effect immediately, before or after graduation, and moves the buyback-vest beneficiary with it.
* It doesn't move balances already credited to the escrow. Claim those first.

Protocol-proposed changes (community takeovers) go through a **3-day timelock** and must be executed within a **3-day window**. Too early reverts with `TimelockNotElapsed`, too late with `TimelockExpired`. Watch `CreatorFeeRecipientChangeProposed` and read `pendingCreatorFeeRecipient(token)` to warn holders ahead of time.

## Buyback vesting

For coins with buybacks enabled, bought-back tokens vest linearly over `VESTING_DURATION` (5 years) in the buyback vault. `vestingStart` is weighted and moves forward as new buybacks land, so compute progress from the live value.

```js
// Resolve the vault from the launch factory.
const buybackVault = await client.readContract({
  address: factory,
  abi: parseAbi(["function buybackVault() view returns (address)"]),
  functionName: "buybackVault",
});

const vaultAbi = parseAbi([
  "function totalLocked(address token) view returns (uint256)",
  "function totalReleased(address token) view returns (uint256)",
  "function vestedAmount(address token) view returns (uint256)",
  "function releasable(address token) view returns (uint256)",
  "function vestingStart(address token) view returns (uint256)",
  "function VESTING_DURATION() view returns (uint256)",
  "function release(address token) returns (uint256)",
]);
```

`release(token)` can be called by either beneficiary: the creator fee recipient or the protocol. Either call pays out **both** sides, crediting each in the escrow. Anyone else gets `NotVestBeneficiary`.

## Holder rewards

Coins that route their fees to holders use a per-coin **rewards distributor**, created by the rewards distributor factory.

A coin with holder rewards on has its rewards distributor as its fee recipient, so you can find it from the launch record: `getLaunchedToken(token).creatorFeeRecipient`. The distributor's `FACTORY()` returns the rewards distributor factory.

```js
const rfAbi = parseAbi([
  "function distributorOf(address token) view returns (address distributor)",
  "function createFor(address token) returns (address distributor)",
]);

const distributorAbi = parseAbi([
  "struct Epoch { bytes32 root; uint256 quoteAllocated; uint256 tokenAllocated; uint256 quoteClaimed; uint256 tokenClaimed; uint64 openedAt; uint64 snapshotBlock; bool rolledOver; bool cancelled; }",
  "function epochCount() view returns (uint256)",
  "function getEpoch(uint256 epochId) view returns (Epoch)",
  "function hasClaimed(uint256 epochId, address account) view returns (bool)",
  "function CLAIM_DELAY() view returns (uint64)",
  "function CLAIM_WINDOW() view returns (uint64)",
  "function claim(uint256 epochId, address account, uint256 quoteAmount, uint256 tokenAmount, bytes32[] proof)",
]);
```

**Turning it on** takes two transactions: `createFor(token)` deploys the vault, then the current fee recipient calls `transferCreatorFeeRecipient(token, distributor)`. It's permanent.

**Epochs:**

* The publisher opens an epoch with a Merkle `root`, the amounts allocated, and a `snapshotBlock`. It emits `EpochOpened`.
* Claims open `CLAIM_DELAY` (1 hour) after `openedAt` and close `CLAIM_WINDOW` (90 days) later. Early claims revert with `EpochNotClaimable`, and late ones with `EpochExpired`.
* Each leaf is `(epochId, account, quoteAmount, tokenAmount)`, and `leafFor(...)` on the distributor computes it. A bad proof reverts with `InvalidProof`. A second claim reverts with `AlreadyClaimed`.
* `claimMany` batches several epochs in one transaction.
* Unclaimed amounts from expired epochs are rolled back into the pot for future epochs.

Proofs are produced off-chain by the publisher and served through the Degen Games app. The on-chain root is what makes them verifiable.


---

# 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://degen-games-2.gitbook.io/degen-games-docs/developers/fees-claims-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.
