# Flaunch the token launchpad

Flaunch is a token launch protocol for creators, communities, and developers.

It gives users a fast way to launch tokens with fixed-price fair launch mechanics, creator revenue in ETH, and configurable treasury behavior. It also gives builders a clean foundation for launchpads and revenue products.

## Install The Flaunch Skill

For a single install target, install the top-level `flaunch` skill:

```bash
npx skills add https://github.com/flayerlabs/flaunch-skills --skill flaunch
```

## Choose Your Path

Use these entrypoints depending on what you are building:

* [AI Skills Quick Start](/a.i.-skills/vibe-guide)
* [SDK Package](https://www.npmjs.com/package/@flaunch/sdk)
* [API Reference](/references/api)
* [Custom Managers](/managers/custom-managers)

## What Flaunch Does

When a token is launched on Flaunch, the launch can include:

* A Fixed-Price Fair Launch Window
* Creator Revenue Paid In ETH
* Automatic Community Buybacks
* Optional Scheduling For A Future Launch Time
* Optional Treasury Manager Integration

This lets a single token act as both a launch event and a long-term onchain revenue primitive.

## Getting Started

{% content-ref url="/pages/KfBXNkoR9oVIlozPg1jy" %}
[What Is Flaunch?](/getting-started/why-flaunch)
{% endcontent-ref %}

{% content-ref url="/pages/ktCvruUTVUKV5eFyfc7x" %}
[Launch a Token](/getting-started/flaunch-a-coin)
{% endcontent-ref %}

{% content-ref url="/pages/KKanSI9loqloPkqKzc2C" %}
[Build a Launchpad](/getting-started/launch-a-launchpad)
{% endcontent-ref %}

## Who These Docs Are For

These docs are organized for three common goals:

* Understanding What Makes Flaunch Different
* Launching A Token Quickly
* Building A Launchpad Or Treasury Product On Top Of The Protocol

## Key Concepts

{% content-ref url="/pages/gZ0d91v2Tz7lVbdffFog" %}
[Creator Revenue](/features/creator-revenue)
{% endcontent-ref %}

{% content-ref url="/pages/JG1vP4adzyrSLJooFkRe" %}
[Fixed Price Fair Launch](/features/fixed-price-fair-launch)
{% endcontent-ref %}

{% content-ref url="/pages/bITGz1ygOGIFvT5EIedx" %}
[Auto Buybacks](/features/auto-buybacks)
{% endcontent-ref %}


# What Is Flaunch?

Flaunch is a protocol for launching tokens and routing the value they generate after launch.

It is built around three core mechanics:

1. Trading fees can be allocated to the creator.
2. Creator revenue is paid in ETH.
3. The rights to that revenue are represented by an NFT that can be held, transferred, or managed by another contract.

This means a Flaunch token is not only a token launch. It is also a revenue position that can be used by creators, launchpads, and treasury products.

## What Flaunch Does

When a token is launched on Flaunch, the creator can define:

* The Token Metadata
* The Starting Market Cap
* The Fair Launch Supply And Duration
* The Creator Revenue Allocation
* The Launch Time
* Whether Revenue Should Flow To A Wallet Or A Manager

After launch, fees continue to flow according to those settings.

## What Else It Enables

* Fixed-Price Fair Launches That Remove Early Price Risk
* Auto Buybacks That Follow The Price Upward
* Transferable Revenue Rights That Can Move To Better Stewards
* Community-Owned Structures Built Around Shared Fee Flows

## Why Builders Use It

Flaunch gives builders more than a token launcher.

It can be used to:

* Launch Tokens Quickly
* Build Launchpads On Top Of The API Or SDK
* Route Revenue Into Treasury Managers
* Build Products Around Tokenized Revenue Rights

## Continue Reading

{% content-ref url="/pages/ktCvruUTVUKV5eFyfc7x" %}
[Launch a Token](/getting-started/flaunch-a-coin)
{% endcontent-ref %}

{% content-ref url="/pages/KKanSI9loqloPkqKzc2C" %}
[Build a Launchpad](/getting-started/launch-a-launchpad)
{% endcontent-ref %}


# Launch a Token

Launching a token on Flaunch can be as simple or as configurable as you need.

At minimum, a launch only needs token metadata and a creator. From there, Flaunch lets you control fair launch settings, revenue allocation, scheduling, and treasury routing.

## Start With The Skill

If you are building this flow with an AI coding agent, start with the Flaunch skill first.

Install:

```bash
npx skills add https://github.com/flayerlabs/flaunch-skills --skill flaunch
```

Then prompt the agent with the token creation path:

```
Use flaunch: Launch a memecoin on Base with the fewest decisions possible.
```

The token creation skill defaults to the Web2 API fast path and only switches to the SDK path when direct launch control is needed.

## Fast Path

The fastest launch flow uses the default product settings:

* Token Name And Symbol
* Description And Image
* Creator Revenue Enabled
* Community Buybacks Enabled
* Standard Fair Launch Configuration

This is the best path when speed matters most.

## What You Can Configure

### Revenue split

When launching a token, the creator can choose how much of trading fee revenue they want to keep.

The default split is:

* Creator share: 80%
* Community buybacks: 20%

Anything not allocated to the creator is routed to [auto buybacks](/features/auto-buybacks).

{% hint style="info" %}
The creator share belongs to the holder of the revenue NFT. That can be a wallet, a multisig, a custom contract, or a treasury manager.
{% endhint %}

### Fee receivers

The creator side of revenue does not have to stay with a single wallet.

Flaunch supports:

* Direct Creator Ownership
* Multiple Fee Receivers
* Revenue Managers
* Treasury Managers

This makes it possible to launch for an individual, a team, or a product with custom revenue routing.

### Fair launch settings

Every token can start with a fixed-price fair launch.

The launch can define:

* How Much Supply Is Available During Fair Launch
* How Long The Fair Launch Lasts
* The Starting Market Cap
* Whether The Creator Prebuys Part Of The Fair Launch Supply
* Whether The Launch Starts Immediately Or At A Future Time

During the fair launch window, buyers trade at the same fixed price. When the window ends, the token moves into normal AMM trading.

### Sniper protection

Flaunch can apply bot-resistance during the fair launch period.

Using the [Flaunch app](https://flaunch.gg/), creators can enable CAPTCHA-based protection and per-wallet caps to support broader initial distribution.

{% hint style="success" %}
Sniper protection applies during the fair launch window, when launch quality matters most.
{% endhint %}

## Advanced Launches

Use advanced settings when the launch needs more direct control.

Common reasons:

* Launch At A Scheduled Time
* Set A Custom Market Cap
* Change Fair Launch Allocation
* Prebuy Part Of The Supply
* Route Revenue Into A Manager

## For Developers

If you are integrating Flaunch programmatically, use the SDK or API guides below.

{% content-ref url="/pages/iJzmKifT7hmngVRQt0Xn" %}
[SDK Guide: Flaunching a Coin](/guides/flaunching-a-coin)
{% endcontent-ref %}

{% content-ref url="<https://github.com/flayerlabs/flaunch-gitbook/tree/main/developer-resources/flaunch-memecoin-api.md>" %}
<https://github.com/flayerlabs/flaunch-gitbook/tree/main/developer-resources/flaunch-memecoin-api.md>
{% endcontent-ref %}

{% content-ref url="/pages/hgYrj53SZnNlZIzNr2tg" %}
[Token Images](/support/token-images)
{% endcontent-ref %}

## Related Concepts

{% content-ref url="/pages/JG1vP4adzyrSLJooFkRe" %}
[Fixed Price Fair Launch](/features/fixed-price-fair-launch)
{% endcontent-ref %}

{% content-ref url="/pages/gZ0d91v2Tz7lVbdffFog" %}
[Creator Revenue](/features/creator-revenue)
{% endcontent-ref %}


# Build a Launchpad

Build a token launch experience on top of Flaunch.

Flaunch can power a launchpad in two ways.

1. Use the existing Flaunch launch flow and build your own product, onboarding, and brand on top of it.
2. Add custom onchain policy with a manager or wrapper when your launchpad needs rules that standard Flaunch launches do not enforce.

For most teams, the first path is the right one.

## Start With The Skill

If you are building a launchpad with an AI coding agent, start with the Flaunch skill first.

Install:

```bash
npx skills add https://github.com/flayerlabs/flaunch-skills --skill flaunch
```

Then prompt the agent with the launchpad path:

```
Use flaunch: Help me choose whether this launchpad should use the API, SDK, or a custom manager.
```

The launchpad skill classifies the build path first, then routes into the API, SDK, manager, or wrapper path as needed.

## Choose the Right Path

### Basic launchpad

Use the basic path when you want to launch tokens through Flaunch without writing new protocol contracts.

This path is best for:

* Standard Token Launch Flows
* Creator Launchpads
* Branded Consumer Apps
* Backend-Assisted Launch Flows
* Products That Want To Launch Into An Existing Revenue Split Or Treasury Manager

You have two ways to build it:

* **Web2 API:** the fastest path for a backend-driven launch flow
* **SDK:** the best path when your app needs direct reads, writes, parsing, and more control over the user experience

### Advanced launchpad

Use the advanced path when the launchpad itself needs custom onchain behavior.

This path is best for:

* Custom Treasury Behavior At Launch
* Project-Specific Permissioning
* Launchpads That Must Route Every Launch Through A Custom Manager
* Wrapper Contracts Around `FlaunchZap`

## Fastest Path: Web2 API

Use the API when you want the smallest integration surface.

The launch flow is:

1. Upload the token image
2. Submit the launch job
3. Poll for launch status

This is the best choice when your product needs a clean backend-assisted flow with fewer moving parts.

{% content-ref url="<https://github.com/flayerlabs/flaunch-gitbook/tree/main/developer-resources/flaunch-memecoin-api.md>" %}
<https://github.com/flayerlabs/flaunch-gitbook/tree/main/developer-resources/flaunch-memecoin-api.md>
{% endcontent-ref %}

## Most Flexible Path: SDK

Use the SDK when you want your app to control the launch experience directly.

The SDK supports:

* Direct Token Launches
* Fee Split Launches
* Revenue Manager Launches
* Launching Into An Existing Treasury Manager
* Parsing Launch Results From Transaction Logs
* Trading, Liquidity, And Import Flows Around The Launch

At the protocol layer, a launch is centered around the `FlaunchParams` fields used by the position manager, including:

* Token Name And Symbol
* Metadata URI
* Fair Launch Allocation And Duration
* Creator Address
* Creator Fee Allocation
* Optional Scheduled Launch Time
* Initial Pricing Parameters

{% content-ref url="/pages/iJzmKifT7hmngVRQt0Xn" %}
[SDK Guide: Flaunching a Coin](/guides/flaunching-a-coin)
{% endcontent-ref %}

## When You Need a Manager

Managers are used when revenue rights or treasury behavior need to be handled by another contract.

Common examples:

* A Revenue-Sharing Launchpad
* A Staking-Based Launchpad
* A Split Manager For Multiple Recipients
* A Custom Treasury Contract Controlled By Your Product

Flaunch already supports this model directly. A launchpad can:

* Deploy A Manager First, Then Launch Into It
* Launch A Token And Create A New Manager In The Same Flow
* Add Existing Flaunch Positions Into A Manager Later

{% content-ref url="<https://github.com/flayerlabs/flaunch-gitbook/tree/main/developer-resources/treasury-managers/README.md>" %}
<https://github.com/flayerlabs/flaunch-gitbook/tree/main/developer-resources/treasury-managers/README.md>
{% endcontent-ref %}

## Recommended Build Order

1. Start with the default token launch flow.
2. Add fee splits or manager support if your product needs custom ownership or revenue routing.
3. Move to a custom manager or zap wrapper only when your launchpad needs hard onchain policy.

This keeps the launchpad simple at first while preserving a clear upgrade path as the product expands.

## Related Guides

{% content-ref url="/pages/ktCvruUTVUKV5eFyfc7x" %}
[Launch a Token](/getting-started/flaunch-a-coin)
{% endcontent-ref %}

{% content-ref url="/pages/ZKynv9uxFRQzVUKUpkFh" %}
[Quick Start](/guides/quick-start)
{% endcontent-ref %}


# Import a Token

Flaunching a token brings a range of ecosystem benefits, including automated buybacks, ETH yield without impacting the token, and more. Each traditional flaunch mints a supply of 100B fresh ERC20 tokens and enters a fresh price discovery phase, usually through a Fair Launch window.

But if you launched your token on another protocol, you can still get access to the post-launch benefits that our optimised Uniswap V4 pools offer. If you have an existing ERC20 token, then you'll likely be eligible to bridge your token into Flaunch and benefit from our core protocol features, whilst retaining all fees earned from your token through Flaunch.

{% embed url="<https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FZ7N2KDzpDSvxEq8jqwXq%2Fuploads%2FO99oTcNHpKI6Yc3WhPlB%2FImport-Tokens.mp4?alt=media&token=a72564a6-b072-4dca-be35-5ed7139d109b>" %}

### Supported External Protocols

If you launched your ERC20 through one of these existing launchpads and you are the owner, then you can directly initialize a Flaunch pool with that token. Any token holders can then add single- or double-sided liquidity against the new Uniswap V4 pool.

<details>

<summary>Clanker</summary>

If you are the onchain `admin` of the `ClankerToken` then you can import your token without any additional verification.

</details>

<details>

<summary>Doppler</summary>

If you are the onchain `integrator` of the `DopplerAirlock` token's `AssetData`, then you can import your token without any additional verification.

</details>

<details>

<summary>Virtuals</summary>

If you are an onchain admin of a `AgentToken` (determined by `owner`) on the token contract, then you can import your token without any additional verification.

</details>

<details>

<summary>Zora</summary>

If you are an onchain admin of a `ZoraCoin` (determined by `isOwner`) on the coin contract, then you can import your token without any additional verification.

</details>

As the creator, you will receive the [ERC721 memestream](/features/royalty-nft) to prove ownership and drive revenue.

To import your token, you can use our frontend UI here:

{% embed url="<https://flaunch.gg/import>" %}

<figure><img src="https://1229184497-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoleIQgpsdD3uHYHcTay2%2Fuploads%2Fgit-blob-7886b769ac08d3d00e926f40d6a726daed69e99f%2FScreenshot%202025-10-22%20at%2016.18.57.png?alt=media" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
To calculate the "Current Coin Price" then you can take the `totalSupply` response from the ERC20 and divide it by the market cap value.\
\
For example, if the `totalSupply()` is `1,000,000,000` and your market cap is `$50,000` , then the Current Coin Price should be:

```
50,000 USDC / 1,000,000,000 Total Supply = 0.00005
```

You do not need to factor in decimal accuracies in either the USDC coin or the coin being imported
{% endhint %}

#### Migrating ERC20 Tokens Not Listed Above

If you have an ERC20 token from a protocol not listed above, we created a whitelist approach to allow us to approve specific tokens to be imported by specific EOA addresses.

As the tokens bridged will have non-flaunch ERC20 implementation logic, we strive to prevent malicious ERC20 contracts from entwining into our platform. For this reason, we run a vetting process before a token can be migrated into Flaunch:

1. **Are you the owner** - Only the project team or owner can migrate the token into Flaunch.
2. **Contract Review** - Our protocol team will review your ERC20 token to ensure there are no malicious exploits present, and then all Flaunch functionality will gel smoothly.

{% hint style="success" %}
If you are interested in migrating your existing ERC20 to the Flaunch ecosystem please reach out on [Discord](https://discord.gg/flaunch).
{% endhint %}

If your token currently resides on a chain other than Base, we can assist you in bridging the token from other chains, including Solana.

### What Flaunch Unlocks for Existing Tokens

When a token is bridged into Flaunch:

* An ERC721 will be minted that shows ownership of the memestream
  * All ETH yield will be sent to the owner of this ERC721
  * Logic and functionality can be expanded with [Treasury Managers](https://github.com/flayerlabs/flaunch-gitbook/tree/main/developer-resources/treasury-managers/README.md)
* Unlike a traditional Flaunch, no ERC20 will be created nor minted. An initial ETH price will be set for your token and then an optional liquidity position can be created in the same transaction
  * Other parties can also create additional liquidity position, but fees will still be directed back solely to the ERC721 memestream owner and the [BidWall](https://github.com/flayerlabs/flaunch-gitbook/tree/main/developer-resources/hooks/progressive-bid-wall.md). If you want to reward other LPs, then a TreasuryManager can be set up to facilitate this as a management strategy
* With your new token, you will have a [Progressive Bid Wall](https://github.com/flayerlabs/flaunch-gitbook/tree/main/developer-resources/hooks/progressive-bid-wall.md) that will facilitate buy positions from any community rev that you assign
* All revenue will be distributed to the memestream owner solely in ETH, preserving your token floor and not requiring you to dump on your holders
* The security and gas optimisations from being built on top of Flaunch and Uniswap V4

### What Next?

Once your token has been imported, you will now have a Flaunch token, but with no liquidity available to swap against. You can then add liquidity by going to the Add Liquidity URL and selecting your new token:

{% embed url="<https://flaunch.gg/add-liquidity>" %}

<figure><img src="https://1229184497-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoleIQgpsdD3uHYHcTay2%2Fuploads%2Fgit-blob-a92a09de117cf6ef63521f6ecfed248404105174%2FScreenshot%202025-10-22%20at%2016.25.13.png?alt=media" alt=""><figcaption></figcaption></figure>

We have some helpers that will assist in setting a full range or concentrated liquidity position.

#### Liquidity Recommendations

The liquidity you add is completely up to you and the project that you are wanting to launch; however, we would propose the following suggestions:

* Ideally adding full range liquidity to support both sides of the swap. If you **are** adding concentrated liquidity try to at least add some ETH to your position, ideally no less than 25% of the corresponding token value.
* Supply sufficient liquidity to be picked up by routers and to support initial price discovery swaps when your listing appears.
* The more liquidity added, the better!


# Flaunch MCP

The Flaunch MCP server lets AI agents launch, discover, and trade Flaunch tokens on Base. It exposes the Flaunch launch flow, IPFS uploads, and coin discovery as [Model Context Protocol](https://modelcontextprotocol.io) tools, and pairs with [Base MCP](https://mcp.base.org) for wallet signing and swaps.

### Endpoint

The server is hosted at:

```
https://mcp.flaunch.gg
```

It uses the **Streamable HTTP** transport. No API key is required. Clients that do not support remote MCP can use the REST routes instead.

### Connecting a Client

#### Claude Code

```bash
claude mcp add --transport http flaunch https://mcp.flaunch.gg
```

#### Cursor / generic MCP config

```json
{
  "mcpServers": {
    "flaunch": {
      "url": "https://mcp.flaunch.gg"
    }
  }
}
```

For wallet-native launches and swaps, also connect Base MCP — the Flaunch tools return inputs shaped for Base MCP's `send_calls` and `swap` tools.

### What Agents Can Do

* Prepare a wallet-native Flaunch token launch for Base MCP `send_calls`.
* Launch through the Flaunch Web2 API and poll the returned `jobId`.
* Upload token images and metadata to IPFS through Flaunch.
* Resolve a completed Web2 launch job into a deployed token contract address.
* Build Base MCP `swap` input for a deployed token contract address.
* Discover newest Flaunch coins and market-cap-ranked Flaunch coins on Base.

### Recommended Launch Flow

Use `prepare_base_launch` for new launches where the user approves the transaction in their own wallet.

1. Collect the launch payload:

```json
{
  "name": "Fuzzy Cat",
  "symbol": "FCAT",
  "description": "A community memecoin.",
  "imageIpfs": "Qm...",
  "creatorAddress": "0x..."
}
```

2. If the user provides an image file instead of an IPFS CID, call `upload_image` first and use the returned `ipfsHash`.
3. Call `prepare_base_launch`.
4. Show the final payload and the returned transaction target to the user for confirmation.
5. Pass the returned `input` directly to Base MCP `send_calls`.

The response shape is:

```json
{
  "supported": true,
  "chain": "base",
  "tool": "send_calls",
  "input": {
    "chain": "base",
    "calls": [
      {
        "to": "0x...",
        "value": "0x0",
        "data": "0x..."
      }
    ]
  },
  "tokenUri": "ipfs://...",
  "metadataIpfsHash": "Qm...",
  "note": "Pass input directly to Base MCP send_calls..."
}
```

`prepare_base_launch` only prepares unsigned calldata — it never submits the transaction. The user must approve it in their wallet.

### Running on Base

Flaunch MCP is designed to run alongside [Base MCP](https://mcp.base.org). Flaunch prepares everything — metadata, IPFS uploads, unsigned launch calldata, swap inputs — while Base MCP owns the wallet: account onboarding, transaction approval, and submission. The agent never signs or broadcasts through Flaunch.

All production launches and swaps target the `base` chain. `base-sepolia` is available for the Web2 launch path only — do not use Base MCP `swap` with `base-sepolia` addresses.

#### Launching a token

1. Run Base MCP onboarding first.
2. If the user did not provide a `creatorAddress`, call Base MCP `get_wallets` and use their Base Account address.
3. Collect token details and upload the image with `upload_image` if it is not already an IPFS CID.
4. Show the final launch details and ask the user to confirm.
5. Call `prepare_base_launch` and verify the response has `tool: "send_calls"` and `input.chain: "base"`.
6. Ask for explicit confirmation, then call Base MCP `send_calls` with the returned `input`.
7. Surface the approval URL as "Approve Transaction" and wait for the user to act.
8. Call Base MCP `get_request_status` once after the user acts and report the confirmed result.

Do not submit launches silently, and do not report success until Base MCP request status confirms completion.

#### Discovering and buying coins

1. Call `get_new_coins` for fresh launches or `get_market_cap_coins` for top coins.
2. Show a compact list: symbol, name, contract address, and market data when present.
3. Do not auto-buy. Ask the user which token and what amount.
4. On explicit confirmation, call `swap_guidance` and pass its `input` to Base MCP `swap` with a funding asset such as `ETH` or `USDC`.
5. Surface the approval URL and poll request status only after the user acts.

#### Swapping by contract address

Tokens can be traded directly by Base contract address — no launch flow required. For buys, set `fromAsset` to `ETH` or `USDC` and `toAsset` to the token address; for sells, reverse them. If an address came directly from the user, describe it as a user-provided Base token address — do not claim it is a Flaunch token unless Flaunch discovery verified it. If Base MCP `swap` cannot quote or route the token, report that it is not currently swappable rather than improvising raw calldata.

#### Risks

* **Low liquidity** — newly launched memecoins can have thin liquidity, volatile prices, and user-supplied metadata. Never present a discovery result as endorsed or vetted.
* **Slippage** — swaps on new tokens can fill materially worse than quoted or fail to route. Do not auto-raise slippage or retry failed swaps without explicit user confirmation.
* **Irreversible** — once the user approves a `send_calls` launch or `swap`, the onchain result cannot be undone. Always confirm chain, token details, creator address, and amount before any write action.

### Tools

| Tool                   | Purpose                                                                          |
| ---------------------- | -------------------------------------------------------------------------------- |
| `prepare_base_launch`  | Prepare unsigned Flaunch launch calldata for Base MCP `send_calls`.              |
| `launch_memecoin`      | Create a server-side launch job through the Flaunch Web2 API. Returns a `jobId`. |
| `get_launch_status`    | Poll a Web2 launch job by `jobId`.                                               |
| `resolve_token`        | Resolve a completed Web2 launch job into a deployed token contract address.      |
| `upload_image`         | Upload and moderate a token image; returns an IPFS hash.                         |
| `upload_metadata`      | Upload token metadata to IPFS.                                                   |
| `swap_guidance`        | Build Base MCP `swap` input for buying or selling a deployed token.              |
| `get_new_coins`        | List the newest Flaunch coin launches on Base.                                   |
| `get_market_cap_coins` | List Base Flaunch coins sorted by market cap.                                    |
| `get_top_coins`        | Explicit discovery query (`sort`: `new` or `marketCap`).                         |
| `health_check`         | Check upstream Flaunch API health.                                               |

#### `prepare_base_launch`

Input:

```json
{
  "chain": "base",
  "name": "Fuzzy Cat",
  "symbol": "FCAT",
  "description": "A community memecoin.",
  "imageIpfs": "Qm...",
  "creatorAddress": "0x...",
  "websiteUrl": "https://example.com",
  "telegramUrl": "https://t.me/example",
  "discordUrl": "https://discord.gg/example",
  "twitterUrl": "https://x.com/example"
}
```

Required fields are `name`, `symbol`, `description`, `imageIpfs`, and `creatorAddress`. Social fields are optional.

Internally this uploads metadata through the Flaunch Web2 API, then uses `@flaunch/sdk` calldata mode to build the launch call. SDK launch defaults are kept server-side.

#### `launch_memecoin`

Create a server-side Flaunch launch job through the Web2 API. Use this only when the product flow explicitly wants the Web2 launch path — it returns a `jobId`, not wallet calldata.

#### `get_launch_status`

```json
{ "jobId": "..." }
```

#### `resolve_token`

```json
{ "jobId": "..." }
```

If the job has not completed, the tool returns a structured `token_not_deployed` error.

#### `upload_image`

```json
{ "base64Image": "data:image/png;base64,..." }
```

Use the returned `ipfsHash` as `imageIpfs` in launch preparation.

#### `upload_metadata`

```json
{
  "name": "Fuzzy Cat",
  "symbol": "FCAT",
  "description": "A community memecoin.",
  "imageIpfs": "Qm...",
  "websiteUrl": "https://example.com"
}
```

#### `swap_guidance`

Buy example:

```json
{
  "tokenAddress": "0x...",
  "direction": "buy",
  "amount": "0.01",
  "asset": "ETH",
  "chain": "base"
}
```

Response:

```json
{
  "chain": "base",
  "tool": "swap",
  "input": {
    "chain": "base",
    "fromAsset": "ETH",
    "toAsset": "0x...",
    "amount": "0.01"
  }
}
```

Pass the returned `input` to Base MCP `swap`.

### Resources

Agents can read these static MCP resources:

* `flaunch://chains` — supported chains and feature flags.
* `flaunch://schema/launch` — launch payload summary.
* `flaunch://docs/capabilities` — concise tool capability notes.

### Prompts

The server exposes reusable prompts for common workflows:

* `launch-simple-token`
* `buy-token-by-address`
* `discover-coins`
* `inspect-launch`

### REST Routes

For clients that cannot use MCP, the same functionality is available over REST:

```
GET  /livez
GET  /v1/flaunch/livez
POST /v1/upload-image
POST /v1/upload-metadata
POST /v1/base/launch/prepare
POST /v1/{base|base-sepolia}/launch-memecoin
GET  /v1/launch-status/:jobId
GET  /v1/launch-status/:jobId/token
GET  /v1/swap-guidance
GET  /v1/base/coins/new
GET  /v1/base/coins/market-cap
GET  /v1/base/coins/top?sort=new|marketCap
```

Example native launch preparation over REST:

```bash
curl -s https://mcp.flaunch.gg/v1/base/launch/prepare \
  -H 'content-type: application/json' \
  -d '{
    "name": "Fuzzy Cat",
    "symbol": "FCAT",
    "description": "A community memecoin.",
    "imageIpfs": "Qm...",
    "creatorAddress": "0x1111111111111111111111111111111111111111"
  }'
```

### Agent Rules

Agents integrating this server should follow these rules:

* Never submit launches silently. Show the final launch payload and ask for explicit user confirmation before using `send_calls`.
* Prefer `prepare_base_launch` for wallet-native launches.
* Use `launch_memecoin` only for the server-side Web2 job flow.
* Use `resolve_token` before attempting a swap from a Web2 `jobId`.
* For swaps by contract address, call `swap_guidance` and pass its `input` to Base MCP `swap`.
* Treat `prepare_base_launch.input` as unsigned transaction data — the user must approve it in their wallet.


# Creator Revenue

Swap fees are shared between creators and communities and the split is decided by the creator themselves. The creator can choose to take from 0% up to 100% of the coin's revenue.

{% hint style="info" %}
Revenue split is immutable and cannot be changed after the coin has launched.
{% endhint %}

* For creators, the revenue is streamed on every swap, paid in ETH
* For communities, the revenue is streamed into [auto buybacks](/features/auto-buybacks)

The creator can choose to burn the tokens that are automatically bought back, or they can turn off auto buybacks to accumulate ETH that can be spent on market buying the coin.

<figure><img src="https://1229184497-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoleIQgpsdD3uHYHcTay2%2Fuploads%2Fgit-blob-e60194e0c087235b49a53d3ef0f8cf188dfd4b98%2Fimage%20(25).png?alt=media" alt="" width="563"><figcaption><p>Devs can choose their own adventure...</p></figcaption></figure>

Revenue streams are fully decentralized and ownership of the “Memestream” is tokenized as an NFT. These NFTs are transferable. You can read about the implications of this in the [Memestream](/features/royalty-nft) section.

The right dev, flaunching the right coin, could find themselves with an annual revenue stream in the millions.

If MOTHER had been Flaunched, Iggy would have a multi-million dollar stream of passive income with at least 20% going to coin holders. The same goes for WIF, MOODENG and many, many others. Instead, those revenues were donated to the platform they launched on.

Flaunched coins retain *all* the value for the coin and creator.


# Royalty NFT

When a coin is flaunched the creator takes ownership of an NFT—The Royalties NFT—which grants the holder rights to the creator's share of the revenue.

By making royalty streams transferable as an NFT, creators can sell their coin's future income to another person, entity or DAO, allowing them to immediately realize future income. It's not just simple NFT trading that is unlocked, but leverage (borrowing against future income) and renting (interest rate swaps) are all possible too.

<figure><img src="https://1229184497-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoleIQgpsdD3uHYHcTay2%2Fuploads%2Fgit-blob-e2cf235e5666cccdb117f8e2cca2008b002e8d05%2Fimage%20(26).png?alt=media" alt="" width="375"><figcaption><p>Tokenized coin's grant the owner the revenue stream.</p></figcaption></figure>

Royalty streams can also be fractionalized or turned into a DAO to create shared ownership of the revenue stream.

Flaunch is providing infrastructure for not just launching coins, but a secondary market for coins and DeFi that ultimately generates more value for creators and coin holders alike.

{% hint style="info" %}
Every Flaunched coin is a 24/7 passive fundraising opportunity, with the most successful coins making as much as 7 figures per day.
{% endhint %}

### Passive Fundraising and Donations

Selling, leveraging and fractionalizing the Royalty stream is one way to further generate value from Flaunch, but what about fundraising? Funds passively accrue to the holder of the Royalty stream passively—so what would you do with those funds?

* Raise $650,000 to put your coin on the Las Vegas Sphere, all without holding a fundraiser.
* Fund community grants and/or hackathons, all onchain.
* Sponsor the next London Milady Rave.
* Raise funds to develop the first coin-founded Network State.

With Flaunch, transferring the Royalty stream is enough to send all future income of the coin to the recipient—paid in ETH. There are no tokens to dump, and no permission needed.

* Donate to the cause of your community's choice.
* Send the Royalty stream to vitalik.eth where he can donate on your coin's behalf.
* Looking to fundraise for malaria treatment? Donate the Royalty stream to charity.

### Coin Management

<figure><img src="https://1229184497-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoleIQgpsdD3uHYHcTay2%2Fuploads%2Fgit-blob-23e8bf27758004f8b0ecb6cd7820f9fe93108b1d%2Fimage%20(34).png?alt=media" alt="" width="375"><figcaption></figcaption></figure>

The holder of the Royalty stream is also endowed with specific management rights that can help to accelerate their coin's culture and price. These include the ability to market buy their coin or burn tokens they have bought back. More actions are being developed to allow for use in liquidity management and airdrops.

Want some more management functionality? Make a request [in the Discord](https://discord.gg/PcSmznqqqb)!

### Community Take Overs (CTOs)

By tokenizing the underlying value of the coin in the Royalty stream, anyone can put an offer to buy the coin's future income (and management - see below) on secondary markets. This creates a very real CTO market, where creators that abandon their coin can exit with some additional value by selling its Royalty stream and allowing the community to keep the culture alive (and getting paid to do so).

CTOs on Flaunch are more concrete and meaningful than anywhere else. Furthermore, the Royalty stream's ownership can be shared across the community through DAOs, multi-sigs and fractionalization.


# Fixed Price Fair Launch

When a coin is flaunched it enters into a Fixed Price Fair Launch. During this period a set number of coins are available to buy at a fixed price *for everyone*. This levels the playing field for all traders—from degens to bots.

<figure><img src="https://1229184497-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoleIQgpsdD3uHYHcTay2%2Fuploads%2FMMTU8wlqnspXOg5jQxT9%2Fimage.png?alt=media&amp;token=4eb30925-9ad1-4945-ad4a-789880a78c65" alt="" width="375"><figcaption><p>Everyone gets the same price for the first 30 minutes.</p></figcaption></figure>

{% hint style="success" %}
Buys during Fixed Price Fair Launch can be sold at the same price (minus fees), removing price risk entirely.
{% endhint %}

{% hint style="danger" %}
It is possible to buy more than the remaining Fair Launch amount, any additional amounts will not be protected by the fixed price.
{% endhint %}

While a Fair Launch is active, coins that are purchased cannot be sold. Coins that were purchased during Fair Launch can be sold at the same price they were bought for (minus fees). This reduces ape risk and gives early supporters a chance to enter before price discovery kicks in.

Creators also have the option to buy up some of their Fair Launch tokens before they become available to the public (and at the same price). This gives creators the flexibility to ensure they have skin in the game or to use these early coins for distribution later on.


# Auto Buybacks

Flaunch introduces a new Uniswap V4 hook called the "Progressive Bid Wall" (PBW) that uses the trading fees generated by the coin to protect its own price from dropping.

{% hint style="info" %}
Whatever the [dev doesn't take](/features/creator-revenue) in fees goes to the PBW. For instance, if the dev share was 20%, then 80% would go to the PBW.
{% endhint %}

A new PBW is created for every 0.1 ETH of trading fees it receives. This places a 0.1 ETH limit order immediately below spot, reducing the impact of any selling.

<figure><img src="https://1229184497-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoleIQgpsdD3uHYHcTay2%2Fuploads%2Fgit-blob-b730d8fe1dbec1ab44cbe775d9c130a701060be9%2Fimage%20(22).png?alt=media" alt="" width="375"><figcaption><p>The PBW follows the price up as it increases</p></figcaption></figure>

If the price continues moving upwards, the PBW follows with more and more ETH being added to its size as each 0.1 ETH threshold is met.

### Turning off Progressive Bid Walls

[Memestream](/features/royalty-nft) owners can disable their coin's Progressive Bid Wall to allow the ETH to accumulate in the coin's treasury. This ETH can be used for approved actions starting with Full Stack Churchills that market buy the token.


# Sniper Protection

Flaunch has created proprietary technology that allows web2 verification of a user to be embedded in the Flaunch AMM.

Enabling Sniper Protection when launching a coin via the [Flaunch app](https://flaunch.gg/) requires the user to validate a CAPTCHA before being able to swap during the Fair Launch period (5 minutes by default).

<figure><img src="https://1229184497-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoleIQgpsdD3uHYHcTay2%2Fuploads%2Fgit-blob-4fec6b2ba0ca0395831cd178ab698818cf1199f7%2FScreenshot%202025-09-11%20at%2012.51.36.png?alt=media" alt=""><figcaption></figcaption></figure>

This allows the Creator to leverage the power of hardened web2 anti-bot/proof of humanity tooling to create a better initial distribution of the coin.

{% hint style="success" %}
A "per wallet cap" can also be set to facilitate a broader distribution amongst users at launch.
{% endhint %}

If you are a builder, it's possible to create your own custom implementation of Sniper Protection that can use any offchain data to grant access to the Fair Launch period. Reach out on [Discord](https://discord.gg/PcSmznqqqb) to discuss implementation.

{% hint style="info" %}
Sniper Protection asks whether you are a person. [Game Mode](/game-mode/game-mode) goes further and asks what you did to deserve your allocation — access is earned by playing a game, and how much you can buy depends on how well you did.
{% endhint %}


# Game Mode

Flaunch is on a mission to give people fairer access to token launches while maximizing rewards for creators. Game Mode is a new innovation on that mission, powered by our Uniswap V4 hook: a **play-to-enter bonding curve**, the first of its kind. It's egalitarian, it's anti-bot and anti-bundler, and it's the future of token launches.

A fair launch is meant to give everyone the same shot at a coin. In practice the first block goes to whoever has the best infrastructure. Bots watch the mempool, land their buys in the same second the pool opens, and sell into the people who arrived moments later. Technically nothing stopped you from buying; practically the good price was gone before you saw the coin.

Game Mode replaces that race with a **window**. For as long as the window is open, the only way onto the curve is to earn it, by playing a game. Nobody buys before the window opens, and nobody buys more than they earned. When the window closes, the coin trades like any other Flaunch coin.

## How a round works

1. **A coin launches with a window.** The creator schedules the launch and picks the game that will guard it. Until the window opens, every swap against the pool reverts, and that's the pool's own rule rather than something the game server has to enforce.
2. **Players play.** Everyone in the round shares one window and one leaderboard. Scoring happens on the server, which re-runs every move from the player's inputs instead of trusting the browser.
3. **Points become spending power.** Your score converts to an allowance in the coin's paired token (ETH, or an approved token such as a tokenised stock). Score more, buy more, up to a per-wallet cap that applies to everyone equally.
4. **You buy what you earned.** Claiming your allowance produces a signed authorization for exactly that amount. The pool checks the signature and the amount on every swap.
5. **The window closes and the gate lifts.** The coin is now an ordinary coin, trading permissionlessly.

## What you can rely on

These hold because the pool enforces them, not because the game server is well behaved:

* **No buying before the window.** The launch's opening time is written into the pool, so there's no early access for anyone to be given or to buy.
* **No buying more than you earned.** Every authorization names a maximum spend, and the pool measures the swap's real input, in the paired token, against it.
* **No buying more than your share.** A per-wallet cap is set at launch and enforced cumulatively, so a player who wins ten rounds of allowance still can't exceed it.
* **The coin reaches the open market on time.** The gate carries an expiry written into the pool at launch. Past it the gate stops enforcing on its own, with no transaction needed from the game server, the creator, or Flaunch.

That last one is the important one. Without an expiry, a coin would need our servers to still be alive to ever trade freely, and holders would be waiting on us instead of on a clock.

{% hint style="info" %}
Game Mode is live on Robinhood chain and Base. The technical details — the signing service, the contracts, and how enforcement works inside the Uniswap V4 hook — are documented under [Spend-Gated Launches](/references/spend-gate).
{% endhint %}

## What a launch looks like

This is supply distribution through the window of a live Game Mode round, ten seconds at a time:

<figure><img src="https://1229184497-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoleIQgpsdD3uHYHcTay2%2Fuploads%2Fgit-blob-aa6a0bf9d613e35e4cd8d6d0bb3a1d8b03a4e713%2Fgame-mode-launch-supply.jpg?alt=media" alt="Supply bought through the gated window, ten seconds at a time: 0.72% across 2 wallets by ten seconds, 35.55% across 194 wallets at close"><figcaption><p>Ten seconds in: 0.72% of supply, held by two wallets. At close: 35.55%, spread across 194.</p></figcaption></figure>

Ten seconds is first-block territory — in a sniped launch the whole story has already happened. Here, two wallets held 0.72% of the supply. From there it built the way a launch should: 51 wallets by thirty seconds, 138 by sixty, and 194 wallets holding 35.55% between them when the window closed. Supply was earned, not sniped.

The bundlers still turned up. One cluster of fifteen wallets — the kind built to split a launch buy across itself — bought nothing at all during the window. One of the fifteen tried playing the round; none of them bought. The 9.27% of supply the cluster did acquire was bought on the open market after the gate lifted, at prices the players had already set. For the first time, the players front-ran the bundlers.

<figure><img src="https://1229184497-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoleIQgpsdD3uHYHcTay2%2Fuploads%2Fgit-blob-9af2da99f7426b01483ec6404da41f645f9d9aae%2Fgame-mode-launch-bundlers.jpg?alt=media" alt="A fifteen-wallet bundler cluster acquired 0.00% of supply during the gated window and 9.27% on the open market afterwards"><figcaption><p>The fifteen-wallet cluster: nothing in the window, 9.27% after it.</p></figcaption></figure>

The full breakdown is in [this thread](https://x.com/flaunchgg/status/2085701754864189580).

## What it changes for creators

Game Mode changes what buyers compete over. Instead of latency, it's skill, knowledge or luck, and instead of a few automated wallets clearing the fair launch in one block, you get a room full of people who spent five minutes earning a position. That's a slower launch and a better holder list, which is the trade a creator is making when they turn it on.

## Why games, why now

Browser gaming is in the middle of a boom. three.js — the library most in-browser 3D is built on, including Split the Arrow — has been downloaded 826 million times from npm, and over half of that is projected to happen in 2026 alone.

<figure><img src="https://1229184497-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoleIQgpsdD3uHYHcTay2%2Fuploads%2Fgit-blob-1db82d7b1b93f867545c52661318c87cb2830d2e%2Fgame-mode-threejs-downloads.png?alt=media" alt="three.js npm downloads over ten years, flat until 2024 then rising steeply, with a 2026 projection of roughly 513 million downloads"><figcaption><p>three.js npm downloads. The 2026 projection is ~513M — up 353% year on year.</p></figcaption></figure>

That curve matters for launches because a real 3D game now runs in the same browser tab as the wallet, with nothing to install between a player and a round. Game Mode turns that into launch infrastructure: any dev can gate entry to a token launch with gameplay nobody else has.

## The games

[**Split the Arrow**](/game-mode/split-the-arrow) is the first, and it's a real game rather than a buy button with a puzzle bolted to it: 3D archery with wind you have to read, a shot budget, and a leaderboard full of people you can watch shooting. It's playable now.

More are coming from us, but Game Mode is open to anyone's game — a trivia round for a knowledge community, a reflex test, a raffle for a project that would rather gate on luck than skill. Anything that can score a player can issue allowance, and the launch experience becomes whatever the game makes it.

One thing worth being precise about, because it's easy to assume the opposite: the games themselves are never tokenized. A game has no coin of its own, and building one involves no launch. Game developers supply the entrance, creators launch coins through it, and a game in the official library earns a share of the trading fees of every coin that launches through it.

See [**Build a Game**](/game-mode/build-a-game) for where that stands, including the open [Game Mode Hackathon](https://flaunch.gg/game-mode/hackathon).


# Split the Arrow

You get sixty seconds and a longbow, shooting at a target thirty-five metres away in gusting wind. Every point you score becomes ETH you're allowed to spend on the coin that's launching. Everyone in the round shoots at the same time, and you can watch them do it.

This page walks through a round as a player sees it. For how the gate works underneath, see [Spend-Gated Launches](/references/spend-gate).

## The lobby

A round runs on its coin's page on Flaunch. Open the page and you're in the lobby with everyone else, watching the countdown to the launch window.

<figure><img src="https://1229184497-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoleIQgpsdD3uHYHcTay2%2Fuploads%2Fgit-blob-2547ed2aedbfd3a10f9a04c2b88fd0c2b64dcf89%2Fgame-mode-01-lobby.png?alt=media" alt="The Split the Arrow lobby, showing the roster of players and the countdown to the launch window"><figcaption><p>Everyone who opens the page lands in the same room. The code in the address bar is the invite.</p></figcaption></figure>

The room code in the URL is a working invite — send it to someone and they join the round you're in, not whichever round happens to be current when they click. If you leave and come back you return to your own seat, with the same wind and the same score.

You can't shoot yet. Until the window opens, the coin can't be bought at all.

## Nocking, drawing, aiming

<figure><img src="https://1229184497-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoleIQgpsdD3uHYHcTay2%2Fuploads%2Fgit-blob-5d612ca7c57f5736a7b11694292ecdeb6fd8333c%2Fgame-mode-02-tutorial.png?alt=media" alt="The tutorial card explaining the controls"><figcaption><p>The tutorial runs once and can be skipped.</p></figcaption></figure>

There are only four controls:

| Control        | What it does                                                                           |
| -------------- | -------------------------------------------------------------------------------------- |
| **Space**      | Nock an arrow                                                                          |
| **Hold click** | Draw. Power builds for about 1.4 seconds to a full draw, and keeps going into overdraw |
| **Drag**       | Aim                                                                                    |
| **Shift**      | Hold your breath — freezes the sway for 2 seconds, once per shot                       |
| **Release**    | Shoot                                                                                  |

Your aim sways while you hold a draw, and the longer you hold the worse it gets. Holding your breath freezes the sway for two seconds so you can place the shot, and you get one breath per arrow. Spending it early because the sway looked bad is the most common way to lose a bullseye.

## The wind

<figure><img src="https://1229184497-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoleIQgpsdD3uHYHcTay2%2Fuploads%2Fgit-blob-dc17f7d79e1a7264e8fb1b858b9c3ba33c55dacb%2Fgame-mode-03-wind.png?alt=media" alt="The aiming view with the range flags showing crosswind"><figcaption><p>The flags are the only wind indicator. Read them before you release.</p></figcaption></figure>

Wind is where the skill is. It gusts on roughly a seven-second cycle and reverses direction at least once per round, and there's no readout for it — the flags down the range are all you get. A shot that would have been a bullseye in still air lands in the outer ring if you release into a gust you didn't see building.

Every player gets their own wind seed, so the gusts you're fighting aren't the ones the person above you on the leaderboard is fighting. That's deliberate: if everyone shared the same wind, one person could solve it and hand the answer around.

## Scoring

<figure><img src="https://1229184497-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoleIQgpsdD3uHYHcTay2%2Fuploads%2Fgit-blob-ca6a7d68732d19d3ffd3b9bbff4feb43ef404904%2Fgame-mode-04-rings.png?alt=media" alt="Arrows landed on the target, showing the scoring rings"><figcaption><p>Four rings. The tightest one containing the arrow wins.</p></figcaption></figure>

| Ring     | Points |
| -------- | ------ |
| Outer    | 50     |
| Third    | 150    |
| Second   | 400    |
| Bullseye | 1,000  |

You have **32 arrows** per round with a short cooldown between shots. At roughly one shot per second you won't run out of arrows inside sixty seconds unless you're trying to.

## Splitting the arrow

<figure><img src="https://1229184497-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoleIQgpsdD3uHYHcTay2%2Fuploads%2Fgit-blob-81e9809504e193553c3f02b0b7a18e08cc40d193%2Fgame-mode-05-split.png?alt=media" alt="An arrow splitting a previously landed arrow on the target"><figcaption><p>The shot the game is named after.</p></figcaption></figure>

Land an arrow in one already stuck in the board and you split it — the Robin Hood shot. A split **doubles that shot's ring score**, so splitting a bullseye is worth 2,000.

Only the first three splits in a round pay the bonus. After that arrows still split and still score their ring — they just stop doubling. The cap is there because a bot that has solved the wind puts every arrow on the same point by default, and would happily collect the bonus thirty times in a round where no human collects it twice.

## The Taxman

<figure><img src="https://1229184497-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoleIQgpsdD3uHYHcTay2%2Fuploads%2Fgit-blob-ad5c86a9afbf38f75e41d2ee5d0dc4f730646dd3%2Fgame-mode-06-taxman.png?alt=media" alt="The Taxman riding across the back of the range"><figcaption><p>He crosses once. Everyone in the round sees the same ride.</p></figcaption></figure>

Once per round, the Taxman gallops across the road behind the target. Unhorse him and you take **2,500 points** — two and a half bullseyes, the biggest single score in the game.

He's a hard shot. He's further away than the target, he's moving, and his pace surges rather than holding steady, so leading him takes practice. Unlike the wind, his crossing is shared: everyone in the round sees the same ride at the same moment, which is usually when the reactions bar lights up.

The only cost of trying is the arrow.

## The leaderboard

<figure><img src="https://1229184497-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoleIQgpsdD3uHYHcTay2%2Fuploads%2Fgit-blob-61a7dc4994cae41c05b3018338fd816b755da63d%2Fgame-mode-07-leaderboard.png?alt=media" alt="The live leaderboard of players in the round with reactions"><figcaption><p>The whole round, scored live on the server.</p></figcaption></figure>

Scores update live for everyone. There's no chat — just reactions, which are one tap each, so nobody can shill a different coin at a captive audience.

Every score on the board was calculated on the server. The game re-runs your shots from your inputs and scores what actually happened, not what your browser claimed.

## Buying what you earned

<figure><img src="https://1229184497-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoleIQgpsdD3uHYHcTay2%2Fuploads%2Fgit-blob-1f22af5aa0e4b544f20f1ff64c67d3ba895d4928%2Fgame-mode-08-buy.png?alt=media" alt="The buy panel showing the ETH allowance earned from the round score"><figcaption><p>Your score, converted into spending power.</p></figcaption></figure>

Your score is an ETH allowance, and the BUY button spends it. Press it and the server issues a signed authorization for that exact amount, your wallet submits the swap carrying it, and the pool checks the signature before letting the trade through.

There are two limits: you can't spend more than you earned, and you can't spend more than the per-wallet cap set at launch, which is the same for everyone no matter how well they shot. A very good round will hit the cap — it's what stops the best player in the room from taking the whole float.

<figure><img src="https://1229184497-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoleIQgpsdD3uHYHcTay2%2Fuploads%2Fgit-blob-1e405be14f605d606b31014005fbc70f646133d7%2Fgame-mode-09-price.png?alt=media" alt="The price chart with confirmed buys from across the round"><figcaption><p>Everyone's buys land on the same curve.</p></figcaption></figure>

Every buy in the round moves the same price. Waiting to buy is a real decision: your allowance doesn't expire inside the window, but the price it buys at climbs with every buy that lands before yours.

## The horn

<figure><img src="https://1229184497-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoleIQgpsdD3uHYHcTay2%2Fuploads%2Fgit-blob-321542ce7d1655e3a8a0bdbe25cc99acb3665ba0%2Fgame-mode-10-results.png?alt=media" alt="The end-of-round results card showing the final board and score"><figcaption><p>Your board, ready to share.</p></figcaption></figure>

When the window closes the round settles and the gate lifts. From then on the coin is an ordinary Flaunch coin — anyone can buy it, no signature required, no game involved.

You keep your board. The results card renders your round as an image, and your best three shots can be pulled out as a replay clip, re-rendered from the same numbers the server scored.

## Playing before you play

Practice rounds are the full multiplayer experience — real roster, real scoring, real opponents — with a simulated economy. Nothing is earned and nothing is bought, so there's no wallet to connect and nothing to sign. It's the right place to learn what a headwind looks like.

{% hint style="warning" %}
Points earned in a practice round are not allowance. Only a live round against a real launch produces something you can spend.
{% endhint %}


# Build a Game

[Split the Arrow](/game-mode/split-the-arrow) is the first Game Mode game. It won't be the only one, and they won't all be ours: Game Mode is open to anyone's game, and the launch experience will be as unique as the game that gates it.

The gate underneath isn't archery-shaped. It's two pieces: a **signer** that decides how much ETH a wallet has earned the right to spend, and a **fee calculator** that enforces that decision on chain. Nothing in either piece knows what a bow is. Any game that can look at a player and produce a number can drive it.

Note which direction this runs. A game developer never tokenizes their game — there is no coin for the game, and nothing for you to launch. Coins are launched by creators, who pick a game to be the entrance; your game is the launch's distribution mechanism. On an open pool the first block belongs to bots and snipers; inside a game, the first holders are the people who showed up and played. You build the room the launch happens in.

That opens up most of what "fair distribution" could mean:

* **Skill** — reflex, aim, timing. What Split the Arrow does.
* **Knowledge** — a trivia round for a community that actually knows its subject, gating the launch on getting the answers right.
* **Luck** — a raffle, for a project that would rather not reward the quickest thumbs.
* **Effort** — anything that costs a few minutes of genuine attention, which is already more than a sniper is willing to spend.

And "game" carries no blockchain qualifier. There is no requirement that a Game Mode game be about money, tokens, or chains — a real game in the Quake 3 sense qualifies exactly as well as a trivia round. Your game code never sees a wallet, a key, or a transaction.

## The hackathon

The [Game Mode Hackathon](https://flaunch.gg/game-mode/hackathon) is open now, and submitting is deliberately itch.io-shaped: build your game with the [Game Mode SDK](/game-mode/game-mode-sdk), zip the static build, and upload it at [flaunch.gg/game-mode/create](https://flaunch.gg/game-mode/create) with a name, a category and a short description. Hosting is included — we serve the game for you.

That is the whole submission. The gate — the signer and enforcement half described above — is a server, but not a *second* one: the gate **is** your game's server, running your rules and signing what they award. It only matters when a real launch runs through your game, and **it is not part of a hackathon submission**: a game built on the SDK's `createMockRoom` runs a complete round in the browser with no server at all. If you do want to demo against a real gate, the SDK ships one and the submission form takes its address; the [SDK page](/game-mode/game-mode-sdk#running-a-server) covers both paths.

You also don't need to build from zero. If a browser game already exists — including a permissively-licensed open-source one — hand your AI coding agent the [`port-game-mode` skill](/game-mode/game-mode-sdk#already-have-a-game-port-it) and it will walk the whole port: the scoring economy, the coin surfaces, the launch framing, and the ZIP.

```bash
npx skills add https://github.com/flayerlabs/flaunch-skills --skill port-game-mode
```

The best submissions join the official Game Mode library, and library games earn **5% of the trading fees of every coin that launches through them** — for as long as creators keep choosing your game.

## Under the hood

The contracts are live on Robinhood chain and Base and documented in full under [Spend-Gated Launches](/references/spend-gate) — the launch parameters, the signature format, and every way enforcement can refuse a swap. You do not need any of it to build or submit a game; it is there for the curious and for anyone integrating at the contract level.

{% hint style="success" %}
If you're building one, come and talk to us on [Discord](https://discord.gg/PcSmznqqqb) — we play every submission, and we'd rather help you ship than have you guess.
{% endhint %}


# Game Mode SDK

Build a game that other people's coin launches happen inside.

You are not launching a token, and your game does not get a coin. Coins are launched by creators on Flaunch, and a creator who launches in Game Mode picks a game to be the entrance: while the launch window is open, playing that game is the only way to earn the right to buy. Your game is the launch's distribution mechanism — a fairer and more fun one than an open pool, where the first block goes to whoever runs the fastest bot.

Players play, the game awards them points, and points become an allowance they can spend on the coin during the launch window. You write the game. Flaunch handles the wallet, the chain and the money.

### The two pieces

A Game Mode game has two parts, and only one of them is yours to worry about at the start:

* **The game** — a browser game, built to static files, zipped and uploaded at [flaunch.gg/game-mode/create](https://flaunch.gg/game-mode/create). Hosting is included — you upload the ZIP and we serve it, the way itch.io does. For the [Game Mode Hackathon](https://flaunch.gg/game-mode/hackathon), this is the whole submission.
* **The gate** — the server side of your game: it runs your game's rules, keeps score, and signs each player's spending allowance. This is the part that is unique to Game Mode, and **you do not need it to submit a game**: a game built on the SDK's `createMockRoom` runs a complete round in the browser with no server at all. The gate enters the picture when a real launch runs through your game — see [Running a server](#running-a-server).

If you have deployed to itch.io before: the ZIP upload is that. Everything about signers, gates and servers further down this page is the second piece, and it can wait.

### What you need

* Node 20 or later
* pnpm
* Docker, only if you want to run a server locally
* a code editor, or an AI coding agent

You do not need to know anything about blockchains. Your game never sees a wallet, a key or a transaction.

### Install

```bash
npm install @flayerlabs/gamemode-client @flayerlabs/gamemode-spec
npm install --save-dev @flayerlabs/gamemode-cli
```

Add `@flayerlabs/gamemode-gate` as well if you are running your own server.

### Make a game in 4 steps

1. Run `npx gamemode new my-game` to create a project you can play straight away.
2. Open `src/game/rules.ts` and write your game.
3. Run `pnpm dev` to play it in a browser. No server, no wallet, no chain.
4. Run `pnpm test` to check it still works.

The scaffold gives you a complete working game with passing tests. Change it rather than starting from an empty file.

### Already have a game? Port it

You do not have to start from the scaffold. If a browser game already exists — yours, or any permissively-licensed open-source game — the `port-game-mode` AI skill turns porting it into a checklist your coding agent can run:

```bash
npx skills add https://github.com/flayerlabs/flaunch-skills --skill port-game-mode
```

A port is the one case with a licence requirement: the upstream game must carry a permissive open-source licence, because that is what gives you the right to redistribute a modified version of someone else's work. Porting your own game has no such requirement — see [Your game stays yours](#your-game-stays-yours).

The skill carries the whole route: licensing and provenance gates, a scoring economy bounded by the game's own rules, the room wiring for coin metadata, the live chart and buying, the launch framing players expect (tutorial, practice lobby, round timer with an end-of-round summary, leaderboard, the coin's art inside the game world), a headless QA harness that proves the loop, and the ZIP you upload. It is built on the same SDK surfaces documented on this page — nothing about a ported game is special once it ships.

{% hint style="info" %}
Building from scratch instead? The `build-game-mode` skill ships inside the `@flayerlabs/gamemode-cli` package and covers rules authoring, testing and the trust boundary in depth.
{% endhint %}

### How a game is structured

Your game is one file of pure functions called a rules module. It runs on the server, which is what stops a player editing their score in the browser.

```ts
import { defineGame } from '@flayerlabs/gamemode-spec'

export const rules = defineGame<Config, State, Event, Action, PublicView, PlayerView>({
  id: 'my-game',

  parseAction(input) { ... },              // reject anything malformed
  initRound(config, seed, window) { ... },  // the starting state
  decide(state, command) { ... },           // what happens, and who earns points
  evolve(state, event) { ... },             // apply one event
  publicView(state) { ... },                // what everyone sees
  playerView(state, player) { ... },        // what one player sees
  nextWakeAt(state) { ... },                // when the game needs waking
  rewardBounds(config) { ... },             // the most one player can earn
})
```

`defineGame` exists for type inference — it does nothing at runtime, and saves you naming six type arguments by hand everywhere the module is used.

#### Deciding and evolving

`decide` answers "what should happen?" and `evolve` answers "what does the state look like afterwards?". Keeping them apart is what lets the server replay a round exactly, and lets you test a game without running a server.

`decide` returns events, and optionally awards:

```ts
decide(state, command) {
  if (command.kind !== 'action') return { events: [] }
  if (state.phase !== 'open') return { refuse: 'not-open' }

  return {
    events: [{ type: 'answered', player: command.player, choice: command.action.choice }],
    awards: [{ player: command.player, points: 100 }],
  }
}
```

You do not have to award points at the moment a player acts. A quiz can accept answers during a question and pay everyone at the reveal. Both use the same shape.

#### Rules must be pure

Your rules module must not use:

* `Date.now()` or any clock
* `Math.random()`
* network calls, files, or databases
* variables that change between calls

Time arrives on every command as `command.at`. Randomness comes from the `seed` given to `initRound`. Run `npx gamemode check` and it will tell you if you have broken this.

This matters because the server replays rounds. A rules module that reads the clock gives a different answer on replay, and a game that disagrees with itself cannot pay anyone reliably.

#### Keeping answers secret

`publicView` is sent to everyone, including spectators. If a value must stay hidden, leave it out of the type. Do not return it and hide it in the interface — a quiz that puts the correct answer in `publicView` has already leaked it, whatever the screen shows.

### What your game talks to

Your browser code talks to one object, the room.

```ts
import { createMockRoom } from '@flayerlabs/gamemode-client'

const room = createMockRoom(rules, { config })

room.subscribe(({ publicView, playerView }) => render(publicView, playerView))
await room.send({ kind: 'answer', choice: 'a' })
room.now()
```

The room also carries everything the platform provides:

| Capability        | What it gives you                                                |
| ----------------- | ---------------------------------------------------------------- |
| `room.launch`     | coin, pool and the round's timings                               |
| `room.connection` | `connecting`, `connected`, `reconnecting`, `superseded`, `ended` |
| `room.economy`    | what a player earned, holds, and buy progress                    |
| `room.market`     | the coin's price history, trades and current market cap          |
| `room.identity`   | names and avatars for wallet addresses                           |
| `room.presence`   | how many players are connected                                   |
| `room.social`     | reactions                                                        |

Every `subscribe` gives you the current value immediately, then updates.

Use `room.now()` for anything a player sees counting down. It corrects for a wrong clock on their device. `Date.now()` in a game is a bug: two players in different timezones will see different games.

#### Buying

```ts
const result = await room.economy.buy(maxSpendWei)
```

Your game asks. The page around it builds the transaction and asks the player to approve it. Your game never constructs a transaction and cannot, which is why a bug in your game cannot lose anyone money.

#### Where market data comes from

`room.market` carries the coin's price history and its current market cap in USD, and the source is the **coin page**, not your gate. Your gate knows the round's ledger — who earned what, who holds what — and nothing at all about the coin's price. So the page pushes its own live feed into the game: the same feed drawing the chart beside you, which is why the two never disagree on a number.

For a game built on rules inside the gate, `joinRoom` wires this for you. For a game with its own server, `joinEconomy` needs telling once — miss it and `market.status` stays `unavailable` for the whole round:

```ts
const embedded = await connectHost()

const gameMode = await joinEconomy({
  gateUrl: embedded.context.gateUrl,
  roundId: embedded.context.roundId,
  host: embedded.host,
  platform: { market: embedded.market },
})
```

`market.status` is the cue for what you are looking at: `unavailable` means the page has no feed and the honest thing to draw is an empty chart, not a spinner that never resolves.

#### Building a chart with no chain

On your laptop there is no page and no chain, so the chart would be empty. Use the replay fixture instead:

```ts
import { createMockRoom, replayMarket, BUSY_LAUNCH } from '@flayerlabs/gamemode-client'

const room = createMockRoom(rules, { config, platform: { market: replayMarket(BUSY_LAUNCH) } })
```

`BUSY_LAUNCH` has a price spike in it on purpose. A chart that looks right on flat data and wrong on a spike is the usual result of building against nothing.

One thing the fixture will not catch: show `marketCapUsd` as it arrives. It is already the coin's current market cap, so scaling it by the round's price move counts that move twice — and puts a number in your game that contradicts the one on the page.

### Testing

Test the rules module directly. No server, no browser, no mocks. The spec package ships a round driver that runs your rules the way the server does — send commands, move time forward, read the result:

```ts
import { Round } from '@flayerlabs/gamemode-spec/round'

const round = Round.start(rules, config, 42, { opensAt: 1_000_000, closesAt: 1_300_000 })
round.send({ kind: 'action', player: '0xabc', action: { choice: 'a' }, at: 1_001_000 })
round.advanceTo(1_012_000) // time only moves when you say so

expect(round.pointsFor('0xabc')).toBe(100)
expect(round.playerView('0xabc').wasRight).toBe(true)
```

Because rules are pure, the same inputs always give the same answer. If a test passes here, it passes on the server. The scaffold's `test/rules.test.ts` starts you off, including a check that secrets stay out of `publicView`.

### Running a server

This is the second of [the two pieces](#the-two-pieces), and it is optional until a real launch runs through your game — a hackathon submission does not need it.

When a launch does go live, the game needs a gate: a small server that runs your rules, keeps score and signs the allowance a player spends. One gate serves one game, and it is your game's only server — the same process that runs the simulation is the one that signs.

To try one on your laptop:

```ts
import { createDemoGate } from '@flayerlabs/gamemode-gate'

const { app } = await createDemoGate({ game: rules, config })
await app.listen({ port: 4000 })
```

This is a real gate with a real database and real signatures. Only the chain is faked: purchases are recorded rather than submitted. It needs Postgres, and one Docker command matches its default connection string:

```bash
docker run -d --rm --name gamemode-pg -e POSTGRES_PASSWORD=gamemode \
  -e POSTGRES_DB=gamemode -p 55439:5432 postgres:16-alpine
```

(Or point `DATABASE_URL` at a Postgres you already have.)

For a live game, `startGate()` is the paved road: your rules module and an environment in, a verified, announced, running gate out.

```ts
import { startGate } from '@flayerlabs/gamemode-gate'
import { rules, config } from './src/game/rules.js'

const { port, signer } = await startGate(rules, config)
```

It reads its configuration from the environment (`CHAIN_ID`, `RPC_URL`, `SIGNER_PRIVATE_KEY`, `DATABASE_URL`, `SESSION_SECRET`, `SIGN_IN_DOMAIN`, `GATE_ORIGIN`, `ALLOWED_ORIGINS` — the full contract is in the [`@flayerlabs/gamemode-gate` README](https://www.npmjs.com/package/@flayerlabs/gamemode-gate) and the DEPLOY.md that ships in the package), refuses loudly on anything misconfigured, runs its own migrations, and serves the `/config` endpoint the launch form reads — a gate that boots is a gate a launch can actually be written against. The `signer` it prints is the address launches will trust; generate its key fresh and never share it, least of all with us.

One rule that catches people: `ALLOWED_ORIGINS` must name both browser callers — your hosted game's origin (`https://*.games.moongate.com`; the hostname changes on every upload, so use the wildcard) and the flaunch page origins, because the coin page itself calls your gate to adopt the round. Leave the page out and every launched coin fails on a CORS error.

Pairings need nothing from you. A coin can be paired with ETH or with any token the chain's `PairedTokenRegistry` has approved (on Robinhood chain that includes tokenised stocks; on Base, LAPTOP), and from SDK 0.5.6 the gate prices whichever one a launch arrives with by itself: it reads the registry from its `PositionManager`, quotes the token through the calculator it was registered with, and sizes the round from that. A pairing approved tomorrow works with the gate you deployed today. `SPEND_TOKENS` still exists for pinning a price, but there is no list to maintain, and a launch on a token the registry does not approve is refused, as the launch itself would have been.

Everything `startGate` assembles is also exported for wiring the gate yourself — `createGate`, `PayloadSigner`, `Discovery`, `Settlement`, `Sessions`, `Claims` and `migrate` — for the rare setup the paved road cannot express; the contract addresses `Discovery` verifies launches against are listed under [Spend-Gated Launches](/references/spend-gate). Two options worth knowing about:

* **`admit`** decides who the gate will talk to — one hook, consulted before a session is issued and before allowance is committed. `createTurnstileAdmit` ships in the gate package if Cloudflare Turnstile is your human check; anything else is a function returning ok or a refusal written for the player to read.
* **`config`** can be a function of the verified launch instead of a constant, resolved once per round — for a game whose rules differ from coin to coin.

### Bring your own multiplayer server

Everything above assumes your rules run inside the gate. A game with its own authoritative realtime server — custom netcode, region fleets, anything where a 100ms round trip is gameplay — keeps that server, and the platform does not host or relay its traffic. The integration stays light:

* Your gate uses `createGameServerGate()` instead of running rules: your server reports scores through an authenticated award route, and the gate still owns sessions, points, allowances and settlement. This path serves `/config` only when you pass `announce` — the launch form refuses a gate without it.
* The submission form's game server addresses field lists your server origins (up to twenty, exact https, no wildcards) — that list is what your hosted game's security policy permits, alongside your gate. The same list goes into `createGameServerGate()` as `gameServerOrigins`, and players prove their wallet to your server with a short-lived join ticket scoped to one of those exact origins.
* Region rotation belongs behind stable hostnames — the reviewed list is not meant to churn.

The full walkthrough — env semantics, the announce block, ticket verification, smoke tests — is the `run-a-game-server` AI skill:

```bash
npx skills add https://github.com/flayerlabs/flaunch-skills --skill run-a-game-server
```

with the same material in the [`@flayerlabs/gamemode-gate` README](https://www.npmjs.com/package/@flayerlabs/gamemode-gate). Talk to us on [Discord](https://discord.gg/PcSmznqqqb) before building this tier — it is the newest path and we would rather walk it with you.

### Going live on Flaunch

1. Build your game to static files.
2. Upload them as a ZIP at [flaunch.gg/game-mode/create](https://flaunch.gg/game-mode/create). You get back a version that cannot change, so what was reviewed is what players get.
3. Games are reviewed, and the best join the official Game Mode library.
4. A creator launches a coin through your game. The launch names the gate's signer and a per-wallet spending cap, and your game appears on the coin's page on flaunch.gg.

Step 4 is not yours: the coin belongs to whoever launches it, and a library game can carry any number of launches. What you get from each one is a share of it — games in the official library earn 5% of the trading fees of every coin that launches through them.

If your game runs its own gate rather than the demo one, this is the point where it goes up somewhere public — [Running a server](#running-a-server) lists what that takes, and the submission form has a field for its address (plus, for a game with its own multiplayer servers, a field for their addresses — see [Bring your own multiplayer server](#bring-your-own-multiplayer-server)). Talk to us on [Discord](https://discord.gg/PcSmznqqqb) before you get here — we would rather help wire it than have you guess.

### Your game stays yours

You do not have to open-source a game you wrote to put it on Flaunch, and we do not ask for ownership of it. Your code, your art and your IP stay yours.

What we need is narrow: permission to host and serve your game inside Game Mode, and to show its name, tagline and cover art in the library and on the coin pages where it runs. Hosting a game means copying it to our servers and serving it to players, so some permission is unavoidable — but it stops there. Not exclusive, no right to modify it beyond the packaging needed to serve it, and no claim on anything you do with the game anywhere else.

One consequence worth knowing before you submit, because it cannot be undone afterwards: **a launch is permanent.** Each ZIP becomes a version that cannot change, and a coin launched through it embeds that exact version on its page forever. If you later withdraw your game from the library, we stop offering it for new launches — but coins already launched through it keep working, which means we keep serving that version to their players. Withdrawing is not deletion.

The open-source requirement you may have seen applies only to [porting someone else's game](#already-have-a-game-port-it). A permissive licence there is how a port proves it has the right to redistribute the original, alongside the provenance file naming the upstream repo, author and commit. It has nothing to do with a game of your own.

{% hint style="info" %}
This section describes the position in plain terms; [Games You Submit](/protocol/terms-of-service#games-you-submit) in the Terms of Service governs. If your game needs something different — a specific attribution, a licence you are already bound by, an asset pack with its own terms — raise it on [Discord](https://discord.gg/PcSmznqqqb) before you submit rather than after.
{% endhint %}

### Linking out of your game

Your game runs inside a sandboxed frame on the coin page. It can open your site, Discord or X in a new tab — `target="_blank"` on a link, or `window.open` inside the click handler; browsers refuse openers that run without a user gesture. The new tab is a normal page, not sandboxed. What the frame cannot do is move the coin page itself or submit forms to it: `window.top`, `location.assign()` and `target="_top"` are blocked, by design.

### Limits that protect players

The chain enforces a spending cap for each wallet on your pool. Your server cannot exceed it, whatever your rules say. If a perfect round would earn more than the cap allows, the gate refuses to start rather than showing players a reward they cannot spend.

Your signing key only ever affects your own launches.

### Packages

| Package                       | Use it for                                                      |
| ----------------------------- | --------------------------------------------------------------- |
| `@flayerlabs/gamemode-spec`   | the types both sides share, and the round driver your tests use |
| `@flayerlabs/gamemode-client` | browser code: the room, the mock, the embed                     |
| `@flayerlabs/gamemode-gate`   | the server                                                      |
| `@flayerlabs/gamemode-cli`    | `gamemode new` and `gamemode check`                             |

Your game's browser bundle uses `client` and `spec`. Your server uses `gate` and `spec`. Keeping them apart is what stops a database driver ending up in a browser.

### Commands

| Command                     | What it does                                  |
| --------------------------- | --------------------------------------------- |
| `npx gamemode new <name>`   | create a game you can play immediately        |
| `npx gamemode check [file]` | check your rules are pure                     |
| `pnpm dev`                  | play it, with no server and no wallet         |
| `pnpm test`                 | check the rules are pure, then run your tests |
| `pnpm typecheck`            | check the types                               |


# Launch calendar

Game Mode launches on Flaunch share one calendar, so two rounds of the same game do not fight for the same players.

When a creator schedules a Game Mode launch, the picker shows start times in five-minute steps for the next 24 hours. Some are greyed out as unavailable. Whether a time is open depends on the game they picked, not on a fixed grid: each game decides how long a launch occupies the calendar and how many of its rounds may overlap.

### How a launch occupies the calendar

A launch takes up the calendar from its start until its round ends, plus a short grace period:

```
occupied = [ start, start + round length + grace )
```

* **Round length** comes from your gate's `/config` (`roundDurationMs`), frozen when your game was approved on that network. A 90-second arcade round occupies a minute and a half; a week-long strategy game occupies a week.
* **Grace** is set by Flaunch per game (60 seconds by default). It keeps the next launch from starting the instant your round settles.
* **Rounds in parallel** is also set per game (1 by default). A three-minute game usually allows one round at a time, so the next start is at least three minutes plus grace later. A seven-day game might allow twenty overlapping rounds, because nobody expects a week-long round to have the field to itself.

A start time is available while, at every moment of its window, fewer than the allowed number of rounds of that game are already open. A game's calendar spans networks: a round on Base and a round on Robinhood Chain count together.

Launches that do not pick a game share a per-network "default gate" calendar with its own limits.

### What creators see

* Picking a time **holds** it for ten minutes while the form is filled in. Another creator sees it as unavailable. Re-picking moves the hold; closing the form releases it.
* Launching **confirms** the hold with the coin's address, and the time stays occupied until the round and its grace end.
* If the calendar cannot be reached, the picker still works. Every time shows as available with a warning that the launch may overlap another round. A paid launch is never blocked by a scheduling outage.
* Whether testnet launches are governed depends on the enforcement scope below.

### Launches made elsewhere

The calendar governs launches made through flaunch.gg. Other launchers are free to run their own queues; a round they start does not block a time here, and a Flaunch reservation does not block them. If a Flaunch launch's confirmation is lost in transit, the backend still recognises the coin when the game's gate reports the round and keeps the time occupied.

### Scope and the off switch

Flaunch can limit enforcement to mainnet chains, to testnets, or run it everywhere, and can switch it off entirely. When it is off, or a chain is out of scope, every time is available and nothing is held. Base Sepolia rehearsals run with enforcement on testnets only, so mainnet launches are untouched.

### For game developers

You do not configure any of this in your game or gate. Your round length is read from `/config`, and Flaunch sets grace and parallel rounds when your game is reviewed. If your game is designed for long, overlapping rounds, say so in your submission so the limit is set to match. If you change `roundDurationMs` in a new build, the calendar picks up the new length once that revision is approved; launches already on the calendar keep the window they were given.


# AI Skills Quick Start

Install the Flaunch AI skills and start building quickly.

The Flaunch skills repository gives AI coding agents a structured way to build on Flaunch.

It is designed to route the agent to the smallest skill that matches the job, whether the goal is launching a token, building a launchpad, or creating a manager-based flow.

## Install The Flaunch Skill

For a single install target, install the top-level `flaunch` skill:

```bash
npx skills add https://github.com/flayerlabs/flaunch-skills --skill flaunch
```

That installs the umbrella router skill, which then routes the agent to the right deeper skill for the task.

{% hint style="info" %}
If the installer only supports direct folder URLs, use the `flaunch/` folder rather than the repository root.
{% endhint %}

## What The Skill Helps With

The installed skill can guide an AI coding agent through:

* Launching A Token
* Building A Launchpad
* Choosing Between The API, SDK, And Manager Paths
* Working With Revenue, Staking, Or Buyback Managers
* Porting An Existing Open-Source Game Into Game Mode

The main manager-development skill is `skills/core/manager/SKILL.md`.

Use the wrapper-zap skill only when the launch flow itself must enforce a manager policy.

## Port A Game Into Game Mode

If the goal is to take an existing open-source browser game and attach it to a token launch as a [Game Mode](/game-mode/game-mode), install the porting skill directly:

```bash
npx skills add https://github.com/flayerlabs/flaunch-skills --skill port-game-mode
```

It walks the agent through the whole port: the licensing and provenance gates, a claims-bounded scoring economy, the coin metadata / chart / buy surfaces, the launch framing players expect (tutorial, practice lobby, round timer, leaderboard), a headless QA harness, and the ZIP you upload at [flaunch.gg/game-mode/create](https://flaunch.gg/game-mode/create).

For building a Game Mode from scratch, the `build-game-mode` skill ships inside the `@flayerlabs/gamemode-cli` npm package — see the [Game Mode SDK](/game-mode/game-mode-sdk).

## Quick Start

{% stepper %}
{% step %}

#### Install the skill

Install the umbrella `flaunch` skill so the agent can route itself to the right path.
{% endstep %}

{% step %}

#### Pick the goal

The two most common outcomes are:

* Launch A Token
* Build A Launchpad
  {% endstep %}

{% step %}

#### Prompt the agent clearly

Use a direct prompt that includes the desired outcome.

{% code overflow="wrap" %}

```
Use flaunch: Help me choose whether this launchpad should use the API, SDK, or a custom manager.
```

{% endcode %}
{% endstep %}

{% step %}

#### Follow the suggested path

For basic launch flows, the skill will usually route toward the API or SDK.

For custom treasury behavior, the skill will route toward the manager path.
{% endstep %}
{% endstepper %}

## Example Prompts

* `Use flaunch: Launch a memecoin on Base with the fastest possible path.`
* `Use flaunch: Help me choose whether this launchpad should use the API, SDK, or a custom manager.`
* `Use flaunch: Build a TypeScript launch flow with @flaunch/sdk on Base Sepolia.`
* `Use flaunch: Create a revenue manager through the Web2 API.`
* `Use port-game-mode: Port this open-source browser game into a Flaunch Game Mode.`

## Build Paths

### Basic Path

Use the basic path when the goal is to:

* Launch A Token With Minimal Parameters
* Build A Standard Launchpad On Top Of The Existing API Or SDK
* Ship Quickly Without Custom Treasury Contracts

### Advanced Path

Use the advanced path when the product needs:

* Custom Treasury Or Revenue Behavior After Launch
* Buyback, Staking, Or Project-Specific Payout Logic
* Manager-Bound Launch Flows
* Wrapper Zaps That Enforce Manager Defaults During Launch

## FAQ

<details>

<summary>Do I need to install every skill separately?</summary>

No. The main install target is the umbrella `flaunch` skill. It routes the agent to the right deeper skill for the task.

</details>

<details>

<summary>What should I install for token creation?</summary>

Start with the umbrella skill. It will usually route to `skills/basic/token-creation/SKILL.md` for the fastest path.

</details>

<details>

<summary>What should I install for launchpad work?</summary>

Start with the umbrella skill. It will usually route to `skills/basic/token-launchpad/SKILL.md`, then into the API, SDK, or manager path as needed.

</details>

## Continue Reading

{% content-ref url="/pages/CDx2ZS3kQCcBoC0b6MqT" %}
[Understanding Skill Files](/a.i.-skills/skill-files)
{% endcontent-ref %}

{% content-ref url="/pages/KKanSI9loqloPkqKzc2C" %}
[Build a Launchpad](/getting-started/launch-a-launchpad)
{% endcontent-ref %}

{% content-ref url="/pages/8WHGtVVoNsgBxJsC4MKC" %}
[Custom Managers](/managers/custom-managers)
{% endcontent-ref %}


# Understanding Skill Files

Understand how the Flaunch skill repository is organized.

The Flaunch skills repository is organized to help AI coding agents choose the right path quickly.

At the top level, Flaunch supports two primary outcomes:

* Launch A Token
* Build A Launchpad

Those outcomes can be solved through a lighter path or a more advanced path depending on how much control the product needs after launch.

## The Three Skill Groups

The repository is organized into three groups:

* `skills/basic`: Fast paths for common tasks
* `skills/core`: Source-of-truth guidance for the main integration surfaces
* `skills/advanced`: Custom contract and wrapper flows

## What Each Group Is For

### Basic

Use the basic skills when you want the shortest route to a finished result.

Common examples:

* Launch A Token With Minimal Inputs
* Scope A Standard Launchpad
* Choose Between The API And SDK

### Core

Use the core skills when the agent needs full guidance for one Flaunch surface.

Core skills cover:

* The Web2 API
* The SDK
* Manager integrations

### Advanced

Use the advanced skills when the product needs custom protocol behavior.

Advanced skills cover:

* Custom manager implementation
* Wrapper zaps
* Project-specific treasury policy
* Porting an existing open-source game into Game Mode

## Recommended Reading Order

1. Start with the umbrella `flaunch` skill.
2. Let it route to the smallest matching skill.
3. Move into `core` or `advanced` only when the product requires more control.

## Key Skill Files

The main files to know are:

* `flaunch/SKILL.md`
* `skills/basic/token-creation/SKILL.md`
* `skills/basic/token-launchpad/SKILL.md`
* `skills/core/api/SKILL.md`
* `skills/core/sdk/SKILL.md`
* `skills/core/manager/SKILL.md`
* `skills/advanced/manager-builder/SKILL.md`
* `skills/advanced/manager-zap-wrapper/SKILL.md`
* `skills/advanced/port-game-mode/SKILL.md`
* `skills/advanced/run-a-game-server/SKILL.md`

## When To Use Which Skill

Use `token-creation` when the goal is to launch a token with the fewest decisions.

Use `token-launchpad` when the goal is to build a launchpad and the first question is whether the API, SDK, or a manager path is required.

Use the manager skills when the launchpad needs custom treasury or payout behavior after launch.

Use `run-a-game-server` when a Game Mode runs its own authoritative multiplayer server and the gate, `/config`, join tickets and platform submission need to line up. Use `port-game-mode` when an existing open-source browser game should become a [Game Mode](/game-mode/game-mode): it carries the licensing and provenance gates, the scoring-economy design, the launch framing checklist, templates, and a QA harness. Its counterpart for building a game from scratch, `build-game-mode`, ships inside the `@flayerlabs/gamemode-cli` npm package rather than this repository.

## Continue Reading

{% content-ref url="/pages/4aYVzbqaNoJvLLMowjft" %}
[AI Skills Quick Start](/a.i.-skills/vibe-guide)
{% endcontent-ref %}

{% content-ref url="/pages/KKanSI9loqloPkqKzc2C" %}
[Build a Launchpad](/getting-started/launch-a-launchpad)
{% endcontent-ref %}


# Manager Overview

Managers control what happens to value after launch.

They sit on the treasury side of Flaunch and define how revenue rights are held, routed, claimed, or shared. This is what makes Flaunch useful not just for token launches, but also for launchpads and custom treasury systems.

## What A Manager Does

A manager can be used to:

* Route Revenue To One Or More Recipients
* Control Claim And Payout Behavior
* Support Revenue, Staking, Or Buyback-Style Flows
* Apply Project-Specific Treasury Logic After Launch

## When To Use A Manager

Use a manager when the product needs more than a standard launch.

Common cases:

* A Launchpad That Takes A Share Of Revenue
* A Treasury That Routes Value To Stakers Or Buybacks
* A Team Treasury With Multiple Recipients
* A Project That Needs Custom Post-Launch Ownership Logic

## Manager Types

Flaunch currently documents the following manager types:

{% content-ref url="/pages/jex5b0QaBgE87PggvcTG" %}
[Revenue Manager](/managers/revenuemanager)
{% endcontent-ref %}

{% content-ref url="/pages/fQMskSxAGJEt7EkKfgDq" %}
[Address Fee Split Manager](/managers/addressfeesplitmanager)
{% endcontent-ref %}

{% content-ref url="/pages/3uyZIfgMzKCnPIqERP6i" %}
[Staking Manager](/managers/stakingmanager)
{% endcontent-ref %}

{% content-ref url="/pages/8WHGtVVoNsgBxJsC4MKC" %}
[Custom Managers](/managers/custom-managers)
{% endcontent-ref %}

## Which Manager Should I Use?

### Revenue Manager

Use this when a product wants to take a protocol share while still routing the creator share correctly.

### Address Fee Split Manager

Use this when revenue should be split across multiple wallets or recipients.

### Staking Manager

Use this when value should flow toward stakers of an ecosystem token.

### Custom Managers

Use this when the project needs treasury behavior that is not covered by the standard manager set.


# Revenue Manager

If you operate an external protocol, there are a number of benefits that can come from integrating with Flaunch.

1. Create your own launchpad that gives you full control of the business model
2. Integrate your protocol's functionality into Flaunch's whitelisted treasury actions to build TVL
3. Build popular money games with the tokenized revenue streams and profit
4. Builders can take up to 100% of all fees generated, and the remaining will go to your token creator and [the community](https://docs.flaunch.gg/developer-resources/hooks/progressive-bid-wall).

The Flaunch protocol is built in a way that directly rewards the token creator though, which won't benefit an external protocol. To alleviate this, we can use an escrow contract that will capture fees as a middleware and give more granular control over fee distribution in any way wanted.

To achieve this, we created the `RevenueManager` implementation contract that is simple to integrate. Before making your call to flaunch a token you will first need to deploy an implementation of the Treasury Manager and then initialize the `RevenueManager` like below.

### Initialization <a href="#who-is-using-the-revenuemanager" id="who-is-using-the-revenuemanager"></a>

```solidity
/**
 * Parameters passed during manager initialization.
 *
 * @member protocolRecipient The recipient of protocol fees
 * @member protocolFee The fee that the external protocol will take (2dp)
 */
struct InitializeParams {
    address payable protocolRecipient;
    uint protocolFee;
}
```

### Deposit <a href="#who-is-using-the-revenuemanager" id="who-is-using-the-revenuemanager"></a>

```
No additional data required
```

### Public Calls

<details>

<summary>balances(address _recipient) returns (uint)</summary>

Allows the caller to check the balance of their position. This will check all of the creator's tokens, and if the protocol fee recipient calls this then it will also show the amount available for them to claim.

</details>

<details>

<summary>claim() returns (uint)</summary>

Allows a caller to make a claim against their whole balance, without any additional {FlaunchToken} logic being passed in the parameters.

</details>

<details>

<summary>claim(FlaunchToken[] calldata _flaunchToken) returns (uint)</summary>

Allows a creator to make claims against the fee revenues they have earned. This returns the amount of ETH claimed during the call.

If the `msg.sender` does not match the `creator` of any of the passed `FlaunchToken` , then the entire tx will revert.

</details>

<details>

<summary>creator(address _flaunch, uint _tokenId) returns (address)</summary>

The address of the user allocated as the creator of the token

</details>

<details>

<summary>creatorTotalClaimed(address _creator) returns (uint)</summary>

The total amount of ETH that a creator address has claimed

</details>

<details>

<summary>deposit(FlaunchToken calldata _flaunchToken, address _creator, bytes calldata _data)</summary>

Deposits a FlaunchToken into the manager.

</details>

<details>

<summary>getProtocolFee(uint _amount) returns (uint)</summary>

Calculates the protocol fee that will be taken from the amount passed in.

</details>

<details>

<summary>managerOwner() returns (address)</summary>

The owner of the manager that can make protected function calls.

</details>

<details>

<summary>protocolFee() returns (uint)</summary>

The fee that the external protocol will take (2dp)

</details>

<details>

<summary>protocolRecipient() returns (address)</summary>

The recipient address of the protocol revenue split

</details>

<details>

<summary>protocolTotalClaimed() returns (uint)</summary>

The total amount of ETH that the protocol has claimed

</details>

<details>

<summary>tokenPoolId(address _flaunch, uint _tokenId) returns (uint)</summary>

Maps a FlaunchToken to a PoolId for simple lookups

</details>

<details>

<summary>tokens(address _creator<em>)</em> returns (FlaunchToken[] memory flaunchTokens)</summary>

Returns an array of all FlaunchToken data assigned to the creator.

</details>

<details>

<summary>tokenTotalClaimed(address _flaunch, uint _tokenId) returns (uint)</summary>

The total amount of ETH that has been claimed for a specific token

</details>

### Protected Calls

Only the owner of the manager can make these calls

Allows a protocol owner to make a claim, without any additional {FlaunchToken} logic being passed in the parameters. This returns the amount of ETH claimed during the call.

<details>

<summary>rescue(FlaunchToken calldata _flaunchToken, address _recipient)</summary>

Rescues the ERC721, extracting it from the manager and transferring it to a recipient.

</details>

<details>

<summary>setCreator(FlaunchToken calldata _flaunchToken, address payable _creator)</summary>

Allows the end-owner creator of the ERC721 to be updated by the intermediary platform. This will change the recipient of fees that are earned from the token externally and can be used for external validation of permissioned calls.

</details>

<details>

<summary>setProtocolRecipient(address payable _protocolRecipient)</summary>

Allows the protocol recipient to be updated. This can allow a zero value that will bypass the protocol recipient taking a protocol fee during the claim.

</details>

<details>

<summary>transferManagerOwnership(address _newManagerOwner)</summary>

Transfers ownership of the contract to a new account (`newOwner`).

</details>

### Who is using the RevenueManager? <a href="#who-is-using-the-revenuemanager" id="who-is-using-the-revenuemanager"></a>

{% hint style="info" %}
We are currently working with a small number of launchpads to implement our RevenueManager. When they are released as public code repositories, we will share and document the implementations. Check back soon!
{% endhint %}

### ABI

{% file src="/files/KqkFeeBf28DY6CiFQ4ja" %}


# Staking Manager

The `StakingManager` allows an ERC20 token to be staked by users and distributes pro-rata ETH rewards from Flaunch stream to staking users.

### Initialization <a href="#who-is-using-the-revenuemanager" id="who-is-using-the-revenuemanager"></a>

```solidity
/**
 * Parameters passed during manager initialization.
 *
 * @member stakingToken The address of the token to be staked
 * @member minEscrowDuration The minimum duration that the creator's NFT is locked for
 * @member minStakeDuration The minimum duration that the user's tokens are locked for
 * @member creatorShare The share that a creator will earn from their token
 * @member ownerShare The share that the manager owner will earn from their token
 */
struct InitializeParams {
    address stakingToken;
    uint minEscrowDuration;
    uint minStakeDuration;
    uint creatorShare;
    uint ownerShare;
}
```

### Deposit <a href="#who-is-using-the-revenuemanager" id="who-is-using-the-revenuemanager"></a>

```
No additional data required
```

### Public Calls

<details>

<summary>stake(uint amount)</summary>

Allows a caller to stake the defined ERC20 token.

</details>

<details>

<summary>unstake(uint amount)</summary>

Allows a caller to unstake the defined ERC20 token and claim any pending ETH fees

Before unstaking, the function validates that the user’s stake is no longer time-locked and that they have sufficient balance.

</details>

<details>

<summary>claim() returns (uint)</summary>

Allows a caller to withdraw their pending ETH rewards earned from staking.

It calculates all owed balances, updates internal snapshots, transfers ETH to the caller, and returns the total amount claimed.

</details>

<details>

<summary>balances(address user) returns(uint balance)</summary>

Allows the caller to check the total claimable ETH balance for a given address.

</details>

<details>

<summary>getUserStakeInfo(address <em>user) returns (uint amount</em>_, uint timelockUntil_, uint pendingETHRewards_)</summary>

Allows the caller to view detailed staking data for any user, including the amount of tokens currently staked, the timestamp when the stake unlocks, and the pending ETH rewards accrued so far.

</details>

### Creator Calls

<details>

<summary>escrowWithdraw(FlaunchToken calldata _flaunchToken)</summary>

Allows the token creator to withdraw their ERC721 after the escrow lock period has passed by verifying ownership and time-based unlock conditions.

</details>

<details>

<summary>extendEscrowDuration(FlaunchToken calldata _flaunchToken, uint _extendBy)</summary>

Allows the token creator to increase the escrow lock period by a specified duration, delaying when the ERC721 can be withdrawn.

</details>

### Who is using the StakingManager? <a href="#who-is-using-the-revenuemanager" id="who-is-using-the-revenuemanager"></a>

{% hint style="info" %}
The StakingManager is designed for protocols launching ecosystem tokens that want to offer staking yield, DAOs looking to distribute ETH rewards to stakers or contributors, meme or gamefi projects aiming to gamify attention and trading activity, and artist collectives or collaborative economies that want to coordinate shared upside through ETH-based rewards.
{% endhint %}


# Address Fee Split Manager

The `AddressFeeSplitManager` allows revenue to be distributed across any number of addresses. Each address can be given a percentage (as small as 0.00001%) and can claim independently of each other.

Multiple Flaunch stream tokens can be held inside the manager, and the creator will also receive a share of their revenue before it is distributed to the nominated addresses.

{% hint style="info" %}
Addresses that receive a fee split are immutable at point of manager creation.
{% endhint %}

### Initialization <a href="#who-is-using-the-revenuemanager" id="who-is-using-the-revenuemanager"></a>

```solidity
/**
 * Parameters passed during manager initialization.
 *
 * @member creatorShare The 5dp percentage share that a creator will earn from their token
 * @member recipientShares Revenue recipients and their share
 */
struct InitializeParams {
   uint creatorShare;
   RecipientShare[] recipientShares;
}

/**
 * Defines a revenue recipient and the share that they will receive.
 *
 * @member recipient The share recipient of revenue
 * @member share The 5dp percentage that the recipient will receive
 */
struct RecipientShare {
   address recipient;
   uint share;
}
```

### Deposit <a href="#who-is-using-the-revenuemanager" id="who-is-using-the-revenuemanager"></a>

```
No additional data required
```

### Public Read Calls

<details>

<summary>amountClaimed(address _recipient) returns (uint)</summary>

The amount claimed for the recipient

</details>

<details>

<summary>balances(address _recipient) returns (uint)</summary>

Allows the caller to check the balance of their position. This will check all of the creator's tokens and their fee split share.

</details>

<details>

<summary>creator(address _flaunch, uint _tokenId) returns (address)</summary>

The address of the user allocated as the creator of the token

</details>

<details>

<summary>creatorFees() returns (uint)</summary>

Gets the total amount of fees allocated to creators, including any fees that are pending against the manager. These pending fees will be claimed during the recipient claim flow.

</details>

<details>

<summary>creatorShare() returns (uint)</summary>

The percentage that a creator will receive before other recipients, accurate to 5 decimal places.

</details>

<details>

<summary>creatorTotalClaimed(address _creator) returns (uint)</summary>

Tracks the total claims for creators

</details>

<details>

<summary>feesCreator() returns (uint)</summary>

The total fees that have been claimed for creators

</details>

<details>

<summary>feesSplit() returns (uint)</summary>

The total fees that have been claimed for the split recipients

</details>

<details>

<summary>getCreatorFee(uint _amount) returns (uint)</summary>

Calculates the creator fee that will be taken from the amount passed in.

</details>

<details>

<summary>isValidRecipient(address _recipient, bytes memory _data) returns (bool)</summary>

Checks if the recipient has either been given a share at initialization or has any tokens that they created held in the manager.

</details>

<details>

<summary>managerFees() returns (uint)</summary>

Gets the total amount of fees held by the manager, including any fees that are pending against the manager. These pending fees will be claimed during the recipient claim flow.

</details>

<details>

<summary>managerFees() returns (uint)</summary>

Gets the total amount of fees held by the manager, including any fees that are pending against the manager. These pending fees will be claimed during the recipient claim flow.

</details>

<details>

<summary>managerOwner() returns (address)</summary>

The owner of the manager that can make protected function calls.

</details>

<details>

<summary>recipientShare(address _recipient, bytes memory _data) returns (uint)</summary>

Gets the percentage share that a recipient address is allocated from the whole of the revenue fees.

</details>

<details>

<summary>tokens(address _creator) returns (FlaunchToken[] memory flaunchTokens)</summary>

Returns an array of all FlaunchToken data assigned to the creator.

</details>

<details>

<summary>tokenTotalClaimed(address _flaunch, uint _tokenId) returns (uint)</summary>

The total amount of ETH that has been claimed for a specific token

</details>

### Public Write Calls

<details>

<summary>claim() returns (uint)</summary>

Allows for a claim call to be made without requiring any additional requirements for bytes to be passed, as these would always be unused for this FeeSplit Manager.

</details>

<details>

<summary>deposit(FlaunchToken calldata _flaunchToken, address _creator, bytes calldata _data)</summary>

Deposits a FlaunchToken into the manager.

</details>

<details>

<summary>transferRecipientShare(uint _newRecipient)</summary>

Allows the user to transfer their recipient share to another user.

The recipient share can only be transferred by the address that owns the recipient share. If the new recipient already has a recipient share, then these will be merged.

</details>

### Protected Calls

Only the owner of the manager can make these calls

Allows a protocol owner to make a claim, without any additional {FlaunchToken} logic being passed in the parameters. This returns the amount of ETH claimed during the call.

<details>

<summary>rescue(FlaunchToken calldata _flaunchToken, address _recipient)</summary>

Rescues the ERC721, extracting it from the manager and transferring it to a recipient.

</details>

<details>

<summary>setCreator(FlaunchToken calldata _flaunchToken, address payable _creator)</summary>

Allows the end-owner creator of the ERC721 to be updated by the intermediary platform. This will change the recipient of fees that are earned from the token externally and can be used for external validation of permissioned calls.

</details>

<details>

<summary>transferManagerOwnership(address _newManagerOwner)</summary>

Transfers ownership of the contract to a new account (`newOwner`).

</details>

### Who is using the AddressFeeSplitManager? <a href="#who-is-using-the-revenuemanager" id="who-is-using-the-revenuemanager"></a>

{% hint style="info" %}
We are currently working with a small number of launchpads to implement our AddressFeeSplitManager. When they are released as public code repositories, we will share and document the implementations. Check back soon!
{% endhint %}

### ABI

{% file src="/files/t2uAq6gcfJzrfPabcb6O" %}


# Custom Managers

Custom managers let builders define treasury behavior outside the standard approved manager set.

## What A Custom Manager Is

A custom manager is a treasury-side contract that receives or controls the Flaunch revenue rights for a launched token.

Builders use custom managers when they need:

* Custom Fee Routing
* Custom Claim Logic
* Custom Escrow Or Treasury Behavior
* Product-Specific Policy After Launch

## How It Connects To Flaunch

Through a wrapper around `FlaunchZap` that enforces the manager path automatically.

The wrapper path is useful when the launch flow itself must guarantee the correct manager setup for every launch.

## Standard Managers vs Custom Managers vs Wrappers

### Standard managers

Use a standard manager when one of the existing manager types already matches the product.

This is the simplest path when you want a supported manager flow with less custom contract work.

Example: a launchpad that wants to use the existing RevenueManager so it can take a protocol fee without writing a new treasury contract.

### Custom managers

Use a custom manager when the treasury behavior itself is unique to the product.

This is the right path when the post-launch logic cannot be expressed through the existing manager set.

Custom managers will usually also need a wrapper around `FlaunchZap` so the intended manager setup is applied consistently during token creation.

Example: a product that wants fees to unlock over time, route to a game treasury, or follow custom creator payout rules that the standard managers do not support.

### Wrappers around `FlaunchZap`

Use a wrapper when the launch entrypoint itself needs to enforce a chosen manager policy for every launch.

This is not the first step for most builders. It is an advanced pattern on top of the custom manager model.

Example: a branded launchpad where every token launch must use the same custom manager and the team does not want integrators setting manager parameters manually.

## What A Wrapper Does

A wrapper around `FlaunchZap` can:

* Force The Intended Manager
* Set Default `permissions`
* Set Default `initializeData`
* Set Default `depositData`
* Ensure New Launches Bind To The Right Manager Path

This is useful when a product does not want users or integrators to configure manager parameters by hand.

## Related Docs

{% content-ref url="/pages/MTctP1EOwOyjd4tW89dG" %}
[Manager Overview](/managers/manager-types)
{% endcontent-ref %}

{% content-ref url="/pages/KKanSI9loqloPkqKzc2C" %}
[Build a Launchpad](/getting-started/launch-a-launchpad)
{% endcontent-ref %}

{% content-ref url="/pages/4aYVzbqaNoJvLLMowjft" %}
[AI Skills Quick Start](/a.i.-skills/vibe-guide)
{% endcontent-ref %}

## Need Support Building Custom Manager?

Support is available in the [Flaunch Discord](https://discord.gg/PcSmznqqqb) and [Telegram](https://t.me/flaunchgg/1).


# Quick Start

Want to integrate with Flaunch?

Flaunch gives developers a fast way to integrate token launches, trading, and treasury behavior without rebuilding the protocol layer from scratch.

## Choose Your Path

Start with the entrypoint that matches the job:

* [AI Skills Quick Start](/a.i.-skills/vibe-guide)
* [SDK Package](https://www.npmjs.com/package/@flaunch/sdk)
* [API Reference](/references/api)
* [Custom Managers](/managers/custom-managers)

At a high level, there are three common integration paths:

1. Launch Tokens Through The Web2 API
2. Build Directly With The SDK
3. Use A Treasury Manager When Revenue Or Ownership Needs Custom Behavior

Flaunch is built on Uniswap V4 and supports launch flows that can continue into ongoing fee routing, treasury logic, and post-launch products.

## Exclusive Features

Some of the core protocol features are:

#### [Fair Launch](/features/fixed-price-fair-launch)

When a coin is flaunched it enters into a Fixed Price Fair Launch. During this period a set number of coins are available to buy at a fixed price *for everyone*. This levels the playing field for all traders—from degens to bots.

#### [Untarnished Revenue Generation](/features/creator-revenue)

Swap fees are shared between creators (devs) and communities (auto buybacks) and the split is decided by the creator themselves. The dev can choose to take from 0% up to 100% of the coin's revenue. All revenue that is earned from the token is output as ETH, so you don't have to factor in logic to dump your token to realize revenue.

#### [Auto Buybacks / Progressive Bid Wall](/features/auto-buybacks)

Flaunch introduces a new Uniswap V4 hook called the "Progressive Bid Wall" (PBW) that uses the trading fees generated by the coin to protect its own price from dropping while accumulating tokens in the coin's treasury that can be used later.

## Treasury Managers

[Treasury Managers](https://github.com/flayerlabs/flaunch-gitbook/tree/main/developer-resources/treasury-managers/README.md) allow revenue generated by the ERC721 memestream to be handled by an intermediary contract.

This is the main building block for revenue-sharing products, split launches, and custom treasury logic.

Flaunch ships with approved manager implementations, but the model is flexible enough for custom manager flows as well.

#### Approved Treasury Manager Types

<details>

<summary>Revenue Manager</summary>

Launch tokens and capture a share of the revenue for each, without the heavy lifting.

[**Read more >**](https://github.com/flayerlabs/flaunch-gitbook/tree/main/developer-resources/treasury-managers/revenuemanager.md)

</details>

## Flaunch JS SDK

A TypeScript SDK for launching, trading, reading protocol data, and building products on top of Flaunch.

* 🚀 Flaunch new memecoins
* 💱 Buy and sell memecoins via Uniswap V4 hooks
* 📊 Read functions for token and pool data
* 🔒 Built-in Permit2 support for gasless approvals
* 🔵 Works on Base and Base Sepolia networks

{% embed url="<https://www.npmjs.com/package/@flaunch/sdk>" %}

## Recommended Path

Choose the smallest path that fits the product.

### API

Use the API when you want the fastest backend-assisted token launch flow.

### SDK

Use the SDK when your app needs direct reads, writes, launch result parsing, swap flows, or integration with managers.

### Manager layer

Use a treasury manager when revenue should be captured or controlled by another contract.

{% content-ref url="/pages/KKanSI9loqloPkqKzc2C" %}
[Build a Launchpad](/getting-started/launch-a-launchpad)
{% endcontent-ref %}

{% content-ref url="/pages/8WHGtVVoNsgBxJsC4MKC" %}
[Custom Managers](/managers/custom-managers)
{% endcontent-ref %}

## Additional Support

If you're looking for some additional support from the team, be sure to reach out in the **#builders** channel in Discord, or in the Telegram chat below.

{% embed url="<https://discord.gg/PcSmznqqqb>" %}
Join the #builders channel
{% endembed %}

{% embed url="<http://t.me/flaunchgg>" %}


# SDK Guide: Flaunching a Coin

Launching a token should comprise of three steps. Firstly we will need to upload a coin image to IPFS, followed by uploading the token metadata to IPFS. Once we have our data available, we can make the onchain call to flaunch the token.

### 1. Upload image

When uploading an image, it is recommended to use `jpg`, `png`, `webp` or `gif`. These can be uploaded directly to an IPFS protocol such as [Pinata](https://docs.ipfs.tech/quickstart/publish/) either through their [SDK](https://docs.pinata.cloud/quickstart) or through their manual control panel.

Once the image is uploaded, you will need to note the `CID`, also sometimes known as the `IPFS Hash`, for the next step.

### 2. Upload JSON metadata

With our image, we will now need to upload a JSON metadata structure to IPFS that defines some additional information about the coin. This metadata is picked up by the frontend to provide information about social networks linked to the coin, as well as a human readable description.

```json
{
  "name": "Token Name",
  "description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc efficitur ut orci.",
  "image": "ipfs://ImageCID",
  "external_link": "https://flaunch.gg",
  "discordUrl": "https://discord.gg/PcSmznqqqb",
  "twitterUrl": "https://x.com/flaunchgg",
  "telegramUrl": "https://t.me/flaunchgg",
  "collaborators": []
}
```

Again, take note of the `CID`(`IPFS Hash`) of the uploaded JSON metadata for step 3.

### 3. Create the onchain call data

When flaunching a coin we *can* make a call directly to the [**PositionManager**](https://github.com/flayerlabs/flaunchgg-contracts/blob/main/src/contracts/PositionManager.sol#L221) contract, but it is recommended to use the [**FlaunchPremineZap**](https://github.com/flayerlabs/flaunchgg-contracts/blob/main/src/contracts/zaps/FlaunchPremineZap.sol#L70) which adds additional logic and functionality on top of the default function call.

As you can likely garner from the name of the zap, it allows the caller to premine their own token before other users can frontrun it. If this logic is not required, then you can call **PositionManager** directly with the same parameters instead and save a small amount of gas.

```solidity
/**
 * Parameters required when flaunching a new token.
 */
struct FlaunchParams {
    string name;
    string symbol;
    string tokenUri;
    uint initialTokenFairLaunch;
    uint premineAmount;
    address creator;
    uint24 creatorFeeAllocation;
    uint flaunchAt;
    bytes initialPriceParams;
    bytes feeCalculatorParams;
}
```

Below is a breakdown of each parameter that is passed, as well as some additional detail in constructing them and examples where applicable.

<details>

<summary>name</summary>

The name of the token that will be used for the ERC20.

***Example:***

```
Flaunchy
```

</details>

<details>

<summary>symbol</summary>

The symbol of the token that will be used for the ERC20.

It is recommended to keep this value betweene 3-6 characters for maximum DEX support.

***Example:***

```
FLNCHY
```

</details>

<details>

<summary>tokenUri</summary>

The IPFS URI of the CID created in step 2 of this process. If this is badly formatted or invalid, then information will be missing and the token may be hidden on the platform entirely.

***Example:***

```
ipfs://QmScdsMTXWm3GUvzUwvQvYJLBQjtXwFjWvLgGvPBgipHmg
```

</details>

<details>

<summary>initialTokenFairLaunch</summary>

The amount of tokens to add as single sided fair launch liquidity. This does not require any additional ETH to be sent.

This value must be between 1% (`1e27`) - 69% (`69e27`).

***Example for 50% of total supply:***

```
50e27
```

</details>

<details>

<summary>premineAmount</summary>

The amount of tokens that the `msg.sender`will buy and the `creator` will receive. This will be quoted and charged at the swap price and will require an ETH value to be passed with the call.

This value must be less than, or equal to, the value in `initialTokenFairLaunch`.

***Example for 20% of total supply:***

```
20e27
```

</details>

<details>

<summary>creator</summary>

The address that will receive the ERC721 ownership and premined ERC20 tokens. The `msg.sender`will still make all ETH payments for this call.

An address must be provided. If a zero address is provided then the call will revert.

***Example:***

```
0xYourCreatorAddress
```

</details>

<details>

<summary>creatorFeeAllocation</summary>

The percentage of fees the creators wants to take from the BidWall. This is denoted on the frontend by showing a split between "Dev" and "Community". This allocation refers to the share that the "Dev" will receive. This value shows a percentage accurate to 2 decimal places.

This value cannot be greater than 100% (`100_00`).

***Example for 60.25% dev revs:***

```
6025
```

</details>

<details>

<summary>flaunchAt</summary>

If the token wants to be scheduled to launch at a future time, a unix timestamp can be set to define when it will launch.

Tokens will not be able to be swapped until this time is reached. If an `initialTokenFairLaunch` allocation has been set, then the fair launch window won't start until this timestamp is reached.

This value cannot be greater than `+30 days`time from the current `block.timestamp`.

***Example:***

```
1739534400
```

</details>

<details>

<summary>initialPriceParams</summary>

The encoded parameters for the **InitialPrice** logic. This bytes data is passed to the current pricing calculator to allow for the currently active contract to handle the market cap calculations for the flaunching process.

The current data required on this endpoint is a USDC value that will represent the marketcap that the coin is created at. This will define the coin value.

At a protocol level this allows for extendability, and as such means that the expected values for this call may change. It should handle fallback values gracefully, but this cannot be guaranteed.

This value must be greater than, or equal to, `1000e6`.

***Example of setting a $5,000 market cap:***

```solidity
abi.encode(5000e6)
```

***Example of setting a $75,000 market cap:***

```solidity
abi.encode(75000e6)
```

</details>

<details>

<summary>feeCalculatorParams</summary>

The encoded parameters for the **FeeCalculator**. This bytes data is passed to the current fee calculator to allow for the currently active contract to handle the swap fee calculations after the flaunching process.

At a protocol level this allows for extendability, and as such means that the expected values for this call may change. It should handle fallback values gracefully, but this cannot be guaranteed.

***This is not currently implemented, so a blank value can be passed:***

```
0x0
```

</details>

### 4. Determine the flaunching fee

There are two function calls that should be made to determine the ETH fee that will be required to flaunch the token. There is a flaunching fee that is 0.1% of the market cap set, and any token premine costs. The latter is optional, but the first will always be required.

#### Find the Flaunching fee

Firstly, the 0.1% of the market cap value can be retrieved by passing the `initialPriceParams` attribute from the FlaunchParams to get back an ETH value.

```solidity
uint flaunchingFee = PositionManager.getFlaunchingFee(
    FlaunchParams.initialPriceParams
)
```

#### **Find the Premine fee**

Passing the number of tokens that you are wanting to purchase, as well as the `initialPriceParams` we can calculate the cost to premine the tokens. We can provide slippage here, though it shouldn't be required as it will only fall within the fair launch amount.

```solidity
uint premineFee = FlaunchPremineZap.calculateFee(
    FlaunchParams.premineAmount,
    0, // The slippage percentage with 2 decimal places
    FlaunchParams.initialPriceParams
)
```

***Note: This can be overpaid and the sender will receive a refund afterwards of unspent ETH.***

### 5. Flaunch!

Now that we have our fees and combined parameters we can make our call to flaunch our token!

```solidity
(address memecoin, uint ethSpent) = premineZap.flaunch{value: flaunchingFee + premineFee}(
    PositionManager.FlaunchParams({
        name: 'Example Memecoin',
        symbol: 'EXMPL',
        tokenUri: 'ipfs://QmScdsMTXWm3GUvzUwvQvYJLBQjtXwFjWvLgGvPBgipHmg',
        initialTokenFairLaunch: 10e27,  // 10% fair launch allocation
        premineAmount: 5e27,  // 5% premine tokens
        creator: address(this),
        creatorFeeAllocation: 20_00,  // 20% dev revs
        flaunchAt: block.timestamp + 24 hours,  // Launch in 24 hours
        initialPriceParams: abi.encode(75_000e6),  // $75,000 mcap
        feeCalculatorParams: abi.encode(0)
    })
);
```


# Making a Swap

All of the Flaunch liquidity is powered by Uniswap V4, meaning that swaps can be easily executed using the [Uniswap V4 Universal Router](https://docs.uniswap.org/contracts/v4/guides/swap-routing).

All liquidity on Flaunch is created as FLETH : MEME, meaning that to make a swap between ETH and Token, we will need an intermediary step to either wrap or unwrap ETH <> FLETH.

### Swapping ETH to / from Token

In the following example we make a 2-step swap to convert ETH to FLETH to MEME.

{% hint style="warning" %}
Note that code has not been tested and is provided as-is, as a learning resource, and should not be used in production without proper audits and review.
{% endhint %}

```solidity
// Encode the Universal Router command
bytes memory commands = abi.encodePacked(uint8(Commands.V4_SWAP));
bytes[] memory inputs = new bytes[](1);

// Encode V4Router actions
bytes memory actions = abi.encodePacked(
    uint8(Actions.SWAP_EXACT_IN_SINGLE),
    uint8(Actions.SWAP_EXACT_IN_SINGLE),
    uint8(Actions.SETTLE_ALL),
    uint8(Actions.TAKE_ALL)
);

// Set the amount being spent
int amountIn = -1e18;

// Set the minimum amount of tokens to receive
uint minAmountOut = 0;

// Set an optional referrer address
address referrer = address(0);

// Define the PoolKey for ETH/FLETH
PoolKey memory ethPoolKey = PoolKey({
    currency0: ETH_ADDRESS,
    currency1: FLETH_ADDRESS,
    fee: 0,
    tickSpacing: 60,
    hooks: IHooks(POOL_MANAGER_HOOK_ADDRESS)
});

// Define the PoolKey for FLETH/MEME
PoolKey memory memePoolKey = PoolKey({
    currency0: FLETH_ADDRESS,
    currency1: TOKEN,
    fee: 0,
    tickSpacing: 60,
    hooks: IHooks(POSITION_MANAGER_HOOK_ADDRESS)
});

// Prepare parameters for each action
bytes[] memory params = new bytes[](4);

// Param: Swapping ETH to FLETH
params[0] = abi.encode(
    IV4Router.ExactInputSingleParams({
        poolKey: ethPoolKey,
        zeroForOne: true,
        amountIn: amountIn,
        amountOutMinimum: minAmountOut,
        sqrtPriceLimitX96: TickMath.MAX_TICK - 1,
        hookData: bytes('')
    })
);

// Param: Swapping FLETH to MEME
params[1] = abi.encode(
    IV4Router.ExactInputSingleParams({
        poolKey: key,
        zeroForOne: true,
        amountIn: amountIn,
        amountOutMinimum: minAmountOut,
        sqrtPriceLimitX96: TickMath.MAX_TICK - 1,
        hookData: abi.encode(referrer)
    })
);

// Param: Settling spent ETH
params[2] = abi.encode(key.currency0, amountIn);

// Param: Confirming expected min MEME received
params[3] = abi.encode(key.currency1, minAmountOut);

// Combine actions and params into inputs
inputs[0] = abi.encode(actions, params);

// Execute the swap
router.execute(commands, inputs, block.timestamp);
```


# Setting a Swap Referrer

When a swap is made on Flaunch, a portion of the swap fee is earmarked for referrer fees before being divided between the remaining allocations.

{% hint style="info" %}
If no referrer is set, then the allocation is instead divided between other sources.
{% endhint %}

By default, all fees in Flaunch are distributed as ETH. However, for referrers they receive their referral fee in the unspecified token (ETH or Token).

This referrer fee is taken before any other fee and is given regardless of token type. The protocol is designed this way as when tokens are sent to the Internal Swap Protocol, it becomes unfeasible to map and maintain referrer allocations.

For example, if a swap buys 10 tokens using ETH, then the fee would be taken in ETH as the ETH was unspecified. Alternatively, if the swap is 0.1 ETH for tokens, then the fee would be in tokens as that is unspecified.

### Direct Swap Calls

When making a swap call to our hook, which will swap (FLETH for, or from, memecoin) we will determine the optional referrer from the `hookData` that is passed. This `hookData` contains optional bytes passed during any hook call.

This referrer is the only `hookData` that we parse in our `beforeSwap` call, meaning that when calling the **PoolManager.swap** function the following can be passed to assign the referrer:

```solidity
BalanceDelta delta = poolManager.swap({
    key: POOL_KEY,
    params: SWAP_PARAMS,
    hookData: abi.encode(address(referrer))
});
```

### Using the Universal Router

Swaps can also be implemented using the [Uniswap V4 Universal Router](https://docs.uniswap.org/contracts/v4/guides/swap-routing). As the documentation on the Uniswap page is extensive, it would be better to read through that approach.

### Claiming Referrer Fees

Referral fees will be distributed in one of two ways:

1. If the `ReferralEscrow` contract is not set on the protocol, then it will instead just be directly transferred to the referrer.
2. If a `ReferralEscrow` contract has been set up, then the tokens will be assigned by escrow to the referrer to claim.

```solidity
// If we don't have referral escrow, send direct to user. We use an unsafe transfer so that
// invalid addresses don't prevent the process.
if (address(referralEscrow) == address(0)) {
    _swapFeeCurrency.transfer(referrer, referrerFee_);
    emit ReferrerFeePaid(poolId, referrer, Currency.unwrap(_swapFeeCurrency), referrerFee_);
}
// Transfer referrer fees to the escrow contract that they can claim or swap for later
else {
    _swapFeeCurrency.transfer(address(referralEscrow), referrerFee_);
    referralEscrow.assignTokens(poolId, referrer, Currency.unwrap(_swapFeeCurrency), referrerFee_);
}
```

{% hint style="warning" %}
The **ReferralEscrow contract is currently enabled on the protocol**
{% endhint %}

The claim process for referral fees is called by passing an array of token addresses to claim, and the recipient of the claim. Tokens can only be claimed from the allocation of the `msg.sender`.

```solidity
/**
 * Function for a user to claim tokens across multiple token addresses.
 *
 * @param _tokens The tokens to be claimed by the caller
 */
function claimTokens(address[] calldata _tokens, address payable _recipient);
```

If there is no allocation for a provided token address then it will just be skipped and the call will not revert.

If the user holds flETH in their referral fees, then when this is claimed it will automatically be unwrapped into ETH and transferred to the `_recipient`.


# Token Images

When building on Flaunch, use the Flaunch image flow first.

The recommended paths are:

* API path: Upload a `base64Image` to the Flaunch image endpoint, then use the returned `ipfsHash` as `imageIpfs`
* SDK path: Pass `metadata.base64Image` into `flaunchIPFS(...)` and let the SDK handle the IPFS flow

This keeps the launch flow aligned with the Flaunch tools and avoids extra manual metadata work.

## API Path

The Web2 API expects images in two steps:

1. Send `base64Image` to `POST /api/v1/upload-image`
2. Use the returned `ipfsHash` as `imageIpfs` when calling `launch-memecoin`

The image upload endpoint validates the image and stores it on IPFS before launch.

{% content-ref url="<https://github.com/flayerlabs/flaunch-gitbook/tree/main/developer-resources/flaunch-memecoin-api.md>" %}
<https://github.com/flayerlabs/flaunch-gitbook/tree/main/developer-resources/flaunch-memecoin-api.md>
{% endcontent-ref %}

## SDK Path

The SDK path is simpler when you are already building in a TypeScript app or script.

Pass the image as `metadata.base64Image` inside `flaunchIPFS(...)`.

The SDK then uploads:

1. The image to IPFS
2. The token metadata JSON to IPFS
3. The launch transaction with the generated metadata URI

This is the recommended path when the app needs direct wallet-controlled launch behavior.

## What To Pass

Use one of these formats:

* A full data URL like `data:image/png;base64,...`
* A base64 string produced from a user-uploaded file

Recommended image formats:

* `jpg`
* `png`
* `webp`
* `gif`

## If You Already Have IPFS

If you already have an IPFS-hosted image, you can still use it.

For the API path, pass the image hash as `imageIpfs`.

For lower-level onchain flows, you can work from a prepared metadata URI, but the preferred developer path is still to use the Flaunch API or SDK upload flow first.

## Recommended Build Order

1. Start with the Flaunch upload flow
2. Confirm the returned IPFS hash or metadata URI
3. Launch the token

## Related Guides

{% content-ref url="/pages/iJzmKifT7hmngVRQt0Xn" %}
[SDK Guide: Flaunching a Coin](/guides/flaunching-a-coin)
{% endcontent-ref %}

{% content-ref url="/pages/4aYVzbqaNoJvLLMowjft" %}
[AI Skills Quick Start](/a.i.-skills/vibe-guide)
{% endcontent-ref %}


# Audits

During the development of Flaunch we undertook three audits to ensure that the protocol is secure and functions as expected. At each audit we remediated or acknowledged all known issues.

### Audit 1: Omniscia

Omniscia undertook our initial audit. Unfortunately this cannot be shared publicly, but a synopsis extract from the findings has been provided below showing their initial findings.

<figure><img src="https://1229184497-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoleIQgpsdD3uHYHcTay2%2Fuploads%2FaSRegd5cZyDV8XqMA4MM%2FScreenshot%202024-12-19%20at%2010.23.40.png?alt=media&amp;token=51c856ce-47db-43fa-93d0-96176267b255" alt=""><figcaption></figcaption></figure>

### Audit 2: Enigma Dark

The first Enigma Dark audit followed on from the Omnisca findings and also reviewed some newly implemented zap logic including flaunch scheduling and premining.

{% file src="/files/A1IwxrRcuIl8XiKy4QAb" %}

### Audit 3: Enigma Dark

After the initial Enigma Dark audit there was a small raft of changes to optimise flow which were subsequently reaudited.

{% file src="/files/uhZxFlLghTHOqr9Ejotz" %}

### Audit 4: Enigma Dark

For our version 1.1 contracts, Enigma Dark followed up to audit our new and modified functionality.

{% file src="/files/Jo1O11dvAQm4GK7L2llf" %}


# Bug Bounty

{% hint style="danger" %}
We are currently in the process of releasing an updated version of the Flaunch contracts. During this time, our bug bounty program will be paused until it is released.
{% endhint %}

{% hint style="warning" %}
We are receiving a greatly increased number of bug bounty submissions with the recent surge of AI assisted auditing. Responses to bug bounty submissions may be delayed, so please bear with us whilst we resolve backlog.
{% endhint %}

The Flaunch Bounty program rewards users that discover and properly disclose found bugs with predefined bounties. We encourage anyone to help strengthen the protocol by actively searching for bugs in the Flaunch contracts.

The Flaunch Bounty program is derived from the Ethereum Bounty Program, an industry standard when it comes to rightfully rewarding bug bounty hunters.

Please send vulnerability submissions to <bounty@flayer.io>.

## Rules and Rewards

Please have a look at the bullets below before starting your hunt!

* Issues that have already been submitted by another user, or are already known to the Flaunch team, are not eligible for bounty rewards.
* Only bugs found in deployed and utilised mainnet contracts, or code found in the `main` branch of the codebase will be eligible. Some contracts in the `main` branch may not be deployed or planned to be used, so applicability will be determined at the Flaunch team's discretion.
* Public disclosure of a vulnerability makes it ineligible for a bounty.
* You can start or fork a private chain for bug hunting. Please respect the Flaunch main and test networks and refrain from attacking them.
* All paid Flaunch and Flayer Labs members are not eligible for rewards.
* Flaunch websites and organizational infrastructure in general, are NOT part of the bounty program.
* The Flaunch Bounty program considers a number of variables in determining rewards. Determinations of eligibility, score and all terms related to an award are at the sole and final discretion of the Flaunch team.

The value of rewards paid out will vary depending on Severity. The severity is calculated according to the [OWASP](https://www.owasp.org/index.php/OWASP_Risk_Rating_Methodology) risk rating model based on Impact and Likelihood:

<figure><img src="https://1229184497-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoleIQgpsdD3uHYHcTay2%2Fuploads%2FfyrqMCjtUbOf05OrI8NB%2Fimage-3.png?alt=media&amp;token=481996a9-8286-48e0-b50c-660bb4b3fb08" alt=""><figcaption><p>Severity Calculation Table</p></figcaption></figure>

{% hint style="info" %}
We are currently only accepting bug bounties that explore vulnerabilities or attacks that would result in a loss of, or restrict access to, funds for either the user or protocol.
{% endhint %}

Reward sizes are guided by the rules below, but are in the end, determined at the sole discretion of the Flaunch team.

<table><thead><tr><th>Severity</th><th width="446">Max Bounty</th></tr></thead><tbody><tr><td><strong>Critical</strong></td><td>25,000 USDC</td></tr><tr><td><strong>High</strong></td><td>15,000 USDC</td></tr><tr><td><strong>Medium</strong></td><td>10,000 USDC</td></tr><tr><td><strong>Low</strong></td><td>2,000 USDC</td></tr><tr><td><strong>Note / Informational</strong></td><td>500 USDC</td></tr></tbody></table>

Bounties may be paid out in USDC, ETH or $FLAY tokens.

In addition to Severity, other variables are also considered when the Flaunch team decides the score, including (but not limited to):

* **Quality of description.**\
  Higher rewards are paid for clear, well-written submissions.
* **Quality of reproducibility.**\
  Please include test code, scripts and detailed instructions. The easier it is for us to reproduce and verify the vulnerability, the higher the reward.
* **Quality of fix, if included.**\
  Higher rewards are paid for submissions with clear descriptions of how to fix the issue.

\
**Important Legal Information**

The bug bounty program is an experimental and discretionary rewards program for our active Flaunch community to encourage and reward those who are helping to improve the platform. It is not a competition. You should know that we can cancel the program at any time, and awards are at the sole discretion of the Flaunch team. You are responsible for all taxes. All awards are subject to applicable law. Finally, your testing must not violate any law or compromise any data that is not yours.

#### KYC Requirements <a href="#bounty-scope" id="bounty-scope"></a>

Approved bug bounties with payouts under $10k can be processed fully anonymously, with no personal information collected.

Any bounties above this value require a custom flow through our legal team and a level of KYC will need to be reached in order to process the payment.

#### Bounty Scope <a href="#bounty-scope" id="bounty-scope"></a>

The above mentioned bug bounty rules and rewards are applicable to all smart contracts that are actively being used and/or promoted by Flaunch.

When in doubt about whether the bug applies to the bounty program, please contact the team by sending an email to <bounty@flayer.io>.

{% embed url="<https://github.com/flayerlabs/flaunchgg-contracts>" %}
Flaunch Repository
{% endembed %}


# FAQ

### What's the swap fee? <a href="#what-revenues-might-i-expect" id="what-revenues-might-i-expect"></a>

1% on both buys and sells.

### What revenues might I expect from a Flaunched coin? <a href="#what-revenues-might-i-expect" id="what-revenues-might-i-expect"></a>

Let's take a look at some of the outcomes for a profit maxi dev who chooses 80% revenue share, leaving 20% to the community.

{% hint style="info" %}
If MOTHER had Flaunched, Iggy would be sitting on an annual passive income of >$10,000,000. Instead those funds are being handed over to platform owners.
{% endhint %}

| Dev           |  24h Volume  | Annual Dev Revs |                 Description |
| ------------- | :----------: | --------------: | --------------------------: |
| Retardio      |      $10     |          $29.20 |    Enough to buy some lunch |
| Peasant       |    $1,000    |          $2,920 |        A little side hustle |
| Meme Lord     |    $10,000   |         $29,200 |     Passive income unlocked |
| Degen King    |   $100,000   |        $292,000 |                  Retirement |
| Chad Emperor  |  $1,000,000  |      $2,920,000 |      Meme-powered lifestyle |
| Network State | $100,000,000 |    $292,000,000 | Crypto party extraordinaire |

And if you Flaunch the next DOGE or PEPE? Higher.

### How do I collect my revenue? <a href="#how-do-i-collect-my-revenue" id="how-do-i-collect-my-revenue"></a>

Simple. All revenue from all your coins is available as a single ETH claim in the header. Claimable balances are updated in real-time as fees accumulate and reach a threshold of 0.001 ETH.

### Can my rewards be taken away from me? <a href="#can-my-rewards-be-taken-away-from-me" id="can-my-rewards-be-taken-away-from-me"></a>

Flaunch is a decentralized protocol with no central authority that can take your rewards. Your rewards will be claimable and revenues will continue to accumulate no matter what.

In fact, the protocol goes even further to protect your rewards. When you Flaunch a coin you receive an NFT. The owner of the NFT receives the rewards from the coin. What does that mean? You can **sell your revenue streams, borrow against them, or use them however you want**. This is the power of decentralized meme finance.

### How do I sell my revenue stream?

The [Memestream NFT](/features/royalty-nft) can be traded on any secondary marketplace like Magic Eden or OpenSea. There are no royalties on Memestream sales.

### How are communities rewarded? <a href="#how-are-communities-rewarded" id="how-are-communities-rewarded"></a>

Enough about devs, what's in it for the community? All Flaunched can have up to 100% of the revenue sent to the community. By default, these fees are used exclusively for [Automated Buybacks](/features/auto-buybacks) that support the token's price from day 1.

The dev can choose to turn off Auto Buybacks and instead begin accumulating ETH that can be used for market buys, airdrops and more. This aspect is called Meme Management and will have a huge impact on how communities coordinate around their coin.

If the community is led by a Galaxy Brain dev, the shared treasury could reach eye watering levels that even the greatest DAOs would not know what to do with.

WIF's fundraise to buy a $650K ad on the Sphere would have been raised in a single day of trading volume had it been Flaunched instead of launched.

{% embed url="<https://x.com/flaunchgg/status/1846620086854885640>" %}

### What is the Fixed Price Fair Launch? <a href="#fair-launch-explained" id="fair-launch-explained"></a>

When a coin is Flaunched it starts with an initial 30 minute Fair Launch.

During Fair Launch the price is fixed for everyone for 30 minutes. The ETH raised during the Fair Launch is then placed immediately into a limit buy, ensuring that Fair Launch participants can exit at the same price (minus trading fees).

After Fair Launch the coin moves into price discovery.

### Why can't I sell during Fair Launch? <a href="#why-cant-i-sell-during-fair-launch" id="why-cant-i-sell-during-fair-launch"></a>

The Fair Launch period is only for buying. After Fair Launch any buyers can sell at the same price they entered (minus trading fees).

### How does the Progressive Bid Wall work? <a href="#how-does-the-progressive-plunge-protection-work" id="how-does-the-progressive-plunge-protection-work"></a>

Trading fees are added to the coin's Progressive Bid Wall (PBW) on every swap.

In the case of a coin with 100% community share, all of the trading revenue will go towards filling this PBW which is automatically created for every 0.1 ETH earned.

We add a little Uniswap V4 magic to the PBW as well, with a hook that ensures it moves up to follow the coin's price as it increases – providing additional price support.

### Does Flaunch have a token? <a href="#does-flaunch-have-a-token" id="does-flaunch-have-a-token"></a>

Flaunch is a decentralized protocol with a governance fee switch that is controlled by FLAY holders.

{% embed url="<https://www.coingecko.com/en/coins/flayer>" %}

### Does the team take any fees? <a href="#does-the-team-take-any-fees" id="does-the-team-take-any-fees"></a>

No. The team does not take any of the trading fees. FLAY governance can choose to turn on a fee switch that can take a maximum of 10% of the fees.

Instead, the liquidity in the system is lent out via a Uniswap V4 hook and into Aave for an ultra low risk 2% yield. These funds are used to support the Flayer Foundation's growth.

### Is Flaunch audited? <a href="#is-flaunch-audited" id="is-flaunch-audited"></a>

Yes! We have two audits completed by two leading audit firms. Findings and remediations have been published on the links below:

* EnigmaDark audit
* Omniscia audit

### Glossary 📖 <a href="#glossary" id="glossary"></a>

* **Flaunch**: The act of Flaunching a coin on the Flaunch platform. Flaunched coins are upgraded memecoins with 100% revenue share built in.
* **Progressive Bid Wall:** A mechanism where the community's share of revenue is automatically used to support the token price as a bid wall—automatically triggered at every 0.1 ETH revenue.
* **Fixed Price Fair Launch**: The first 30 minutes of a coin launch, where the price is fixed for all buyers.
* **Memestream**: A unique token you receive when you Flaunch a coin. It holds the rights to all revenue streams and Meme Management for that coin.


# Privacy Policy

Last Updated: 10 April 2025

This Cookie Policy explains how Flayer Protocol (“Flayer” “we,” “us,” and “our”) uses cookies and similar technologies to recognize you when you visit our website at \[flaunch.gg] (“Website”). It explains what these technologies are and why we use them, as well as your rights to control our use of them.

In some cases we may use cookies to collect personal information, or that becomes personal information if we combine it with other information.

### What are cookies? <a href="#what-are-cookies" id="what-are-cookies"></a>

Cookies are small data files that are placed on your computer or mobile device when you visit a website. Cookies are widely used by website owners in order to make their websites work, or to work more efficiently, as well as to provide reporting information.

Cookies set by the website owner (in this case, Flayer Protocol) are called “first-party cookies.” Cookies set by parties other than the website owner are called “third-party cookies.” Third-party cookies enable third-party features or functionality to be provided on or through the website (e.g., advertising, interactive content, and analytics). The parties that set these third-party cookies can recognize your computer both when it visits the website in question and also when it visits certain other websites.

### Why do we use cookies? <a href="#why-do-we-use-cookies" id="why-do-we-use-cookies"></a>

We use first- and third-party cookies for several reasons. Some cookies are required for technical reasons in order for our Website to operate, and we refer to these as “essential” or “strictly necessary” cookies. Other cookies also enable us to track and target the interests of our users to enhance the experience on our Online Properties. Third parties serve cookies through our Website for advertising, analytics, and other purposes. This is described in more detail below.

### How can I control cookies? <a href="#how-can-i-control-cookies" id="how-can-i-control-cookies"></a>

You have the right to decide whether to accept or reject cookies. You can exercise your cookie rights by setting your preferences in the Cookie Consent Manager. The Cookie Consent Manager allows you to select which categories of cookies you accept or reject. Essential cookies cannot be rejected as they are strictly necessary to provide you with services.

The Cookie Consent Manager can be found in the notification banner and on our Website. If you choose to reject cookies, you may still use our Website though your access to some functionality and areas of our Website may be restricted. You may also set or amend your web browser controls to accept or refuse cookies.

The specific types of first- and third-party cookies served through our Website and the purposes they perform are described in the table below (please note that the specific cookies served may vary depending on the specific Online Properties you visit):

### Essential website cookies: <a href="#essential-website-cookies" id="essential-website-cookies"></a>

These cookies are strictly necessary to provide you with services available through our Website and to use some of its features, such as access to secure areas. Name: Purpose: Provider: Service: Type: Expires in: Name: Purpose: Provider: Service: Type: Expires in:

### Performance and functionality cookies: <a href="#performance-and-functionality-cookies" id="performance-and-functionality-cookies"></a>

These cookies are used to enhance the performance and functionality of our Website but are non-essential to their use. However, without these cookies, certain functionality (like videos) may become unavailable. Name: Purpose: Provider: Service: Type: Expires in: Name: Purpose: Provider: Service: Type: Expires in:

### Analytics and customization cookies: <a href="#analystics-and-customization-cookies" id="analystics-and-customization-cookies"></a>

These cookies collect information that is used either in aggregate form to help us understand how our Website is being used or how effective our marketing campaigns are, or to help us customize our Website for you. Name: Purpose: Provider: Service: Type: Expires in: Name: Purpose: Provider: Service: Type: Expires in:

### Advertising cookies: <a href="#a-dvertising-cookies" id="a-dvertising-cookies"></a>

These cookies are used to make advertising messages more relevant to you. They perform functions like preventing the same ad from continuously reappearing, ensuring that ads are properly displayed for advertisers, and in some cases selecting advertisements that are based on your interests. Name: Purpose: Provider: Service: Type: Expires in: Name: Purpose: Provider: Service: Type: Expires in:

### How can I control cookies on my browser? <a href="#how-can-i-control-cookies-on-my-browser" id="how-can-i-control-cookies-on-my-browser"></a>

As the means by which you can refuse cookies through your web browser controls vary from browser to browser, you should visit your browser's help menu for more information. The following is information about how to manage cookies on the most popular browsers: [Chrome(opens in a new tab)](https://support.google.com/chrome/answer/95647#zippy=%2Callow-or-block-cookies) [Internet Explorer(opens in a new tab)](https://support.microsoft.com/en-us/windows/delete-and-manage-cookies-168dab11-0753-043d-7c16-ede5947fc64d) [Firefox(opens in a new tab)](https://support.mozilla.org/en-US/kb/enhanced-tracking-protection-firefox-desktop?redirectslug=enable-and-disable-cookies-website-preferences\&redirectlocale=en-US) [Safari(opens in a new tab)](https://support.apple.com/en-ie/guide/safari/sfri11471/mac) [Edge(opens in a new tab)](https://support.microsoft.com/en-us/windows/microsoft-edge-browsing-data-and-privacy-bb8174ba-9d73-dcf2-9b4a-c582b4e640dd) [Opera(opens in a new tab)](https://help.opera.com/en/latest/web-preferences/)

In addition, most advertising networks offer you a way to opt out of targeted advertising. If you would like to find out more information, please visit: [Digital Advertising Alliance(opens in a new tab)](http://www.aboutads.info/choices/) [Digital Advertising Alliance of Canada(opens in a new tab)](https://youradchoices.ca/) [European Interactive Digital Advertising Alliance(opens in a new tab)](http://www.youronlinechoices.com/)

### What about other tracking technologies, like web beacons? <a href="#what-about-other-tracking-technologies-like-web-beacons" id="what-about-other-tracking-technologies-like-web-beacons"></a>

Cookies are not the only way to recognize or track visitors to a website. We may use other, similar technologies from time to time, like web beacons (sometimes called “tracking pixels” or “clear gifs”). These are tiny graphics files that contain a unique identifier that enables us to recognize when someone has visited our Website or opened an email including them. This allows us, for example, to monitor the traffic patterns of users from one page within a website to another, to deliver or communicate with cookies, to understand whether you have come to the website from an online advertisement displayed on a third-party website, to improve site performance, and to measure the success of email marketing campaigns. In many instances, these technologies are reliant on cookies to function properly, and so declining cookies will impair their functioning.

### Do you use Flash cookies or Local Shared Objects? <a href="#do-you-use-flash-cookies-or-local-shared-objects" id="do-you-use-flash-cookies-or-local-shared-objects"></a>

Websites may also use so-called “Flash Cookies” (also known as Local Shared Objects or “LSOs”) to, among other things, collect and store information about your use of our services, fraud prevention, and for other site operations.

If you do not want Flash Cookies stored on your computer, you can adjust the settings of your Flash player to block Flash Cookies storage using the tools contained in the Website Storage Settings Panel. You can also control Flash Cookies by going to the Global Storage Settings Panel and following the instructions (which may include instructions that explain, for example, how to delete existing Flash Cookies (referred to “information” on the Macromedia site), how to prevent Flash LSOs from being placed on your computer without your being asked, and (for Flash Player 8 and later) how to block Flash Cookies that are not being delivered by the operator of the page you are on at the time).

Please note that setting the Flash Player to restrict or limit acceptance of Flash Cookies may reduce or impede the functionality of some Flash applications, including, potentially, Flash applications used in connection with our services or online content.

### Do you serve targeted advertising? <a href="#do-you-serve-targeted-a-dvertising" id="do-you-serve-targeted-a-dvertising"></a>

Third parties may serve cookies on your computer or mobile device to serve advertising through our Website. These companies may use information about your visits to this and other websites in order to provide relevant advertisements about goods and services that you may be interested in. They may also employ technology that is used to measure the effectiveness of advertisements. They can accomplish this by using cookies or web beacons to collect information about your visits to this and other sites in order to provide relevant advertisements about goods and services of potential interest to you. The information collected through this process does not enable us or them to identify your name, contact details, or other details that directly identify you unless you choose to provide these.

### How often will you update this Cookie Policy? <a href="#how-often-will-you-update-this-cookie-policy" id="how-often-will-you-update-this-cookie-policy"></a>

We may update this Cookie Policy from time to time in order to reflect, for example, changes to the cookies we use or for other operational, legal, or regulatory reasons. Please therefore revisit this Cookie Policy regularly to stay informed about our use of cookies and related technologies.

The date at the top of this Cookie Policy indicates when it was last updated.

### Where can I get further information? <a href="#where-can-i-get-further-information" id="where-can-i-get-further-information"></a>

If you have any questions about our use of cookies or other technologies, please email us at <info@flayer.io>.


# Terms of Service

Last Updated: 10 August 2026

**PLEASE READ THESE TERMS OF USE BEFORE USING THE WEBSITE.**

### Acceptance of the Terms of Use <a href="#acceptance-of-the-terms-of-use" id="acceptance-of-the-terms-of-use"></a>

These terms of use are entered into by and between you and the Flayer Protocol, a Cayman Islands company (including all affiliates and subsidiaries, collectively referred to as, “Flayer,” “we,” “us,” or “our”). The following terms and conditions, together with any documents they expressly incorporate by reference (collectively, these “Terms of Use”), govern your access to and use of flaunch.gg, including, but not limited to, any content, functionality, and services offered on or through flaunch.gg (collectively, the “Website”). Please read the Terms of Use carefully before you start to use the Website. By using the Website or by clicking to accept or agree to the Terms of Use when this option is made available to you, you accept and agree to be bound and abide by these Terms of Use in addition to our Privacy Policy, incorporated herein by reference and available at \[docs.flaunch.gg/privacy].

If you do not agree to these Terms of Use, you must not access or use the Website.

### About the Website <a href="#about-the-website" id="about-the-website"></a>

Our Website is primarily meant to function as access to and use of the Flaunch App.

To use parts of our Website, a user may need to use a third-party, non-custodial wallet software that allows the user to interact with public smart contracts and blockchains. We do not operate, maintain, or provide any wallets or wallet services. We will at no time have any custody or control of any crypto-assets that any user is interacting with. We are not a wallet provider, exchange, broker, lender or borrower.

As part of our Website, you may from time to time gain access to decentralized open-source smart contracts deployed on public blockchains. Our interface is distinct and separate from any of the smart contracts that may be accessed through it, and is merely one of multiple means of accessing such smart contracts. Users can interact with the same smart contracts otherwise directly, including to develop and build their own user interfaces on top of such smart contracts.

Our Website may change and grow in numbers, which may require that we include additional terms for certain new parts of the Website (which, in such event, will be construed as part of the “Website”). We reserve the right in our sole discretion to modify or discontinue any parts of the Website at any time and without any liability.

### Game Mode and Gated Launches <a href="#game-mode-and-gated-launches" id="game-mode-and-gated-launches"></a>

Some token launches accessible through the Website open behind a gated launch window (“**Game Mode**”). During the window, the launch’s smart contract (the “**pool**”) accepts purchases only up to a spending allowance that a participant has earned by playing a game associated with that launch. Participation in Game Mode is entirely optional.

**Skill, not chance.** A participant’s spending allowance is determined solely by that participant’s performance in the game: the game server independently re-validates every submitted move, and no random drawing, lottery, or other element of chance determines any allowance. An allowance is a ceiling on what you may spend, not an entitlement to anything: you purchase tokens yourself, onchain, with your own funds, within your earned allowance and at your own discretion. Tokens acquired through Game Mode are purchases — they are not prizes, winnings, or awards — and, consistent with the section above, we at no time have custody or control of them.

**The gate expires onchain.** Every gated launch carries an expiry that is written into the pool’s smart contract at the moment of launch. Once that expiry passes, the gate is null and void automatically and permanently: the pool trades permissionlessly like any other token, without any transaction, approval, signature, or continued operation required from us, the game server, or the coin’s creator. None of us has the ability to extend the window, reimpose the gate, or delay the transition to permissionless trading. This is enforced by the smart contract itself and holds even if the game server or the Website is unavailable.

**What we operate, and what we do not.** The game server that scores rounds and issues allowance authorizations is operated by us or our contractors. We may decline to accept new rounds at any time (for example, for maintenance), and we may modify or discontinue Game Mode as part of the Website in accordance with these Terms of Use — but neither affects a launch already written onchain: a scheduled round’s window and expiry proceed exactly as its smart contract provides.

**Fair play.** We use automated and manual review to protect the integrity of rounds, including re-running gameplay from submitted inputs. Where we determine, in our sole discretion, that a participant has cheated, used automation, colluded, or otherwise exploited a round, we may void scores, decline to issue allowance authorizations, and exclude wallets from current or future rounds. Because the system is non-custodial, we cannot and do not seize tokens that have already been purchased onchain.

**Limits and no guarantees.** Per-wallet spending caps are set at launch and apply to every participant equally. Scores and allowances have no cash value, are not transferable except as the relevant smart contract permits, and expire with the window. We make no representation or warranty as to the availability of any allocation, the execution or price of any purchase, or the present or future value of any token, and amounts spent participating in a round or purchasing tokens are not refundable by us.

**Private rounds.** A creator may schedule a round that is joinable only through an invite link. Anyone who holds the link may join; safeguarding and distributing the link is the creator’s responsibility, and rounds and purchases remain publicly visible on the blockchain regardless of how a round is joined.

**Eligibility.** Notwithstanding the “Who May Use the Website” section above, you must be at least 18 years of age (or the age of majority where you live, if higher) to participate in a Game Mode round. Paid skill contests are regulated in some jurisdictions; you are responsible for ensuring your participation is lawful where you are, and we may restrict the availability of Game Mode in any jurisdiction at our discretion.

**Test networks.** Game Mode may from time to time be made available on blockchain test networks. Tokens, scores, and allowances on a test network have no monetary value, exist for testing only, and may be reset or discontinued at any time.

### Games You Submit <a href="#games-you-submit" id="games-you-submit"></a>

This section applies if you submit a game, or any other file, text, or image, for use in Game Mode (each, a “**Submission**”). It does not apply to using the Website as a player.

**Your Submission stays yours.** We claim no ownership of your Submission. All right, title, and interest in and to it — including its source code, assets, artwork, trademarks, and all other intellectual property — remain yours or your licensors'. Nothing in these Terms of Use transfers ownership of a Submission to us, and we do not require you to publish a Submission under an open-source licence.

**The permission you grant us.** So that we can host your Submission and make it playable, you grant us a non-exclusive, worldwide, royalty-free licence, sublicensable only to our hosting, storage, and content-delivery providers to the extent needed to operate the Website, to store, copy, host, transmit, publicly display, and publicly perform the Submission as part of the Website and Game Mode, and to reformat, compress, or repackage it solely as technically necessary to serve it. You also grant us a licence to use the name, tagline, description, and cover image you supply with the Submission to list, describe, and promote the game and the launches that run through it. We acquire no other rights: this licence does not permit us to modify your game's substance, to license it to third parties for their own use, or to exploit it outside the Website and Game Mode.

**Withdrawal is not deletion.** Each Submission you upload becomes a specific version that cannot be changed, and a token launch created through that version embeds it permanently onchain and on that token's page. You may withdraw a Submission from the Game Mode library at any time, and we will stop offering it for new launches. However, the licence above survives withdrawal solely to the extent needed to keep serving the versions that existing launches already depend on, so that those launches continue to function for the people who joined them. Nothing in this paragraph permits us to accept new launches through a withdrawn Submission.

**What you promise us.** By making a Submission you represent and warrant that: you own it or have all rights and permissions necessary to grant the licence above; it does not infringe or misappropriate any third party's intellectual property, privacy, or publicity rights; every third-party component in it — code, libraries, fonts, artwork, audio, and other assets — is properly licensed for this use, and any notices or attributions those licences require are included in the Submission; it contains no malware, no undisclosed data collection, and no functionality designed to interfere with the Website, a gate, or another participant; and it complies with applicable law and with the Prohibited Uses section below.

**Ports of other people's work.** If your Submission adapts a game you did not write, the original must be licensed under a permissive open-source licence that permits redistribution of modified versions, and you must retain the original licence text and attributions and include accurate provenance identifying the upstream work, its author, and the version you adapted. Adaptations of works that are unlicensed, “source-available,” or licensed on terms that do not permit this use are not eligible.

**We decide what to host.** We are under no obligation to accept, review, host, or continue hosting any Submission. We may decline a Submission, remove it, or suspend its availability at any time and for any reason, including where we believe it infringes a third party's rights, breaches these Terms of Use, presents a security or integrity risk, or where we are required to do so by law. Removal by us does not affect launches already written onchain, which continue as their smart contracts provide.

**Your responsibility for your Submission.** Your Submission is your content, not ours. We do not endorse it, and we make no representation or warranty about it to anyone. You are responsible for it, including for supporting it and for any claim arising from it, and the Indemnification section below applies to that responsibility.

### Who May Use the Website <a href="#who-may-use-the-website" id="who-may-use-the-website"></a>

The Website is offered and available to users who are 13 years of age or older. The Website is not intended for children under 13 years of age. By using the Website, you represent and warrant that you (i) are 13 years of age or older, (ii) are not barred to use the Website under any applicable law, (iii) are using the Website only for your own personal use, (iv) are not a Sanctioned Person and are not located in, ordinarily resident in, or organized under the laws of any Sanctioned Jurisdiction, and (v) are not acting on behalf of, or for the benefit of, any Sanctioned Person or any person located in a Sanctioned Jurisdiction. If you do not meet these requirements, you must not access or use the Website.

“**Sanctioned Jurisdiction**” means any country or region that is the subject of comprehensive sanctions administered or enforced by the U.S. Office of Foreign Assets Control (OFAC), the United Nations Security Council, the European Union, or His Majesty’s Treasury of the United Kingdom (as of the date above: Cuba, Iran, North Korea, Syria, and the Crimea, Donetsk, and Luhansk regions of Ukraine). “**Sanctioned Person**” means any person or entity that is listed on any sanctions list maintained by any of the foregoing authorities — including OFAC’s Specially Designated Nationals and Blocked Persons List — or that is directly or indirectly owned 50% or more, or controlled, by any such listed person or entity.

### Changes to the Terms of Use <a href="#changes-to-the-terms-of-use" id="changes-to-the-terms-of-use"></a>

We may revise and update these Terms of Use from time to time in our sole discretion. All changes are effective immediately when we post them. Your continued use of the Website following the posting of revised Terms of Use means that you accept and agree to the changes. You are expected to check this page frequently so you are aware of any changes, as they are binding on you.

### Accessing the Website and Account Security <a href="#accessing-the-website-and-account-security" id="accessing-the-website-and-account-security"></a>

We reserve the right to withdraw or amend the Website, and any service or material we provide on the Website, in our sole discretion without notice. We do not guarantee that our Website or any content on them will always be available or be interrupted. We will not be liable if for any reason all or any part of the Website is unavailable at any time or for any period. From time to time, we may restrict access to some parts of the Website, or entire Website, to users.

You are responsible for:

* Making all arrangements necessary for you to have access to the Website; and
* Ensuring that all persons who access the Website through your internet connection are aware of these Terms of Use and comply with them.

To access the Website or some of the resources it offers, you may be asked to provide certain registration details or other information. It is a condition of your use of the Website that all the information you provide on the Website is correct, current, and complete. You agree that all information you provide to use the Website, including, but not limited to, using any interactive features on the Website, is governed by our Privacy Policy, and you consent to all actions we may take with respect to your information that are consistent with our Privacy Policy.

You should use particular caution when inputting personal information onto the Website on a public or shared computer so that others are not able to view or record your personal information.

### Intellectual Property Rights <a href="#intellectual-property-rights" id="intellectual-property-rights"></a>

Unless otherwise indicated, the Website is our proprietary property and all source code, databases, functionality, software, website designs, information, audio, video, text, photographs, and graphics on the Website (collectively, the “Content”, which excludes any Submission as defined in the “Games You Submit” section above) and the trademarks, service marks, and logos contained therein (collectively, the “Marks”) are owned or controlled by us or licensed to us, and are protected by copyright, trademark and other intellectual property laws and international conventions. You are not permitted to use the Marks without the prior written consent of the owner of the Mark.

Except as expressly provided herein, Flayer and its licensors do not grant any express or implied license to the Website or the Content. You agree not to copy, reproduce, aggregate, republish, download, post, display, transmit, modify, rent, lease, loan, sell, assign, distribute, license, sublicense, sell, reverse engineer, create derivative works based on, or otherwise exploit for any commercial purposes whatsoever, the Website or the Content, without our express prior written permission. If you are eligible to use the Website, you are granted a limited license to access and use the Website and the Content to which you have properly gained access solely for your personal, non-commercial use. You may not modify or alter the Content in any way. We reserve all rights not expressly granted to you in and to the Website, the Content and the Marks.

### Prohibited Uses <a href="#prohibited-uses" id="prohibited-uses"></a>

You may use the Website only for lawful purposes and in accordance with these Terms of Use. You agree not to use the Website:

* In any way that violates any applicable federal, state, local, or international law or regulation (including, without limitation, any laws regarding the export of data or software to and from the United States or other countries);
* In any way that violates applicable economic or trade sanctions or export-control laws, or to evade the geographic and sanctions restrictions described in these Terms of Use, including through the use of any virtual private network, proxy, or other means of obscuring your location or identity;
* For the purpose of exploiting, harming, or attempting to exploit or harm minors in any way by exposing them to inappropriate content, asking for personally identifiable information or otherwise;
* To send, knowingly receive, upload, download, use, or re-use any material which does not comply with these Terms of Use;
* To transmit, or procure the sending of, any advertising or promotional material without our prior written consent, including any “junk mail”, “chain letter”, “spam”, or any other similar solicitation;
* To impersonate or attempt to impersonate Flayer, a contractor of Flayer, another user, or any other person or entity (including, without limitation, by using e-mail addresses or screen names associated with any of the foregoing); and
* To engage in any other conduct that restricts or inhibits anyone's use or enjoyment of the Website, or which, as determined by us, may harm Flayer or users of the Website or expose them to liability.

Additionally, you agree not to:

* Use the Website in any manner that could disable, overburden, damage, or impair the Website or interfere with any other party's use of the Website, including their ability to engage in real time activities through the Website;
* Use any robot, spider, or other automatic device, process or means to access the Website for any purpose, including monitoring or copying any of the material on the Website;
* Use any manual process to monitor or copy any of the material on the Website or for any other unauthorized purpose without our prior written consent;
* Use any device, software or routine that interferes with the proper working of the Website;
* Introduce any viruses, trojan horses, worms, logic bombs, or other material which is malicious or technologically harmful;
* Attempt to gain unauthorized access to, interfere with, damage, or disrupt any parts of the Website, the server(s) on which the Website is stored, or any server, computer or database connected to the Website;
* Attack the Website via a denial-of-service attack or a distributed denial-of-service attack; and
* Otherwise attempt to interfere with the proper working of the Website.

### Reliance on Information Posted <a href="#reliance-on-information-posted" id="reliance-on-information-posted"></a>

The information presented on or through the Website is made available solely for general information purposes. We do not warrant the accuracy, completeness or usefulness of this information. Any reliance you place on such information is strictly at your own risk. We disclaim all liability and responsibility arising from any reliance placed on such materials by you or any other visitor to the Website, or by anyone who may be informed of any of its contents.

The Website may include content provided by third parties, including materials provided by third-party licensors, syndicators, aggregators, and/or reporting services. All statements and/or opinions expressed in these materials, other than the content provided by Flayer, are solely the opinions and the responsibility of the person or entity providing those materials. These materials do not necessarily reflect the opinion of Flayer. We are not responsible, or liable to you or any third party, for the content or accuracy of any materials provided by any third parties.

### Changes to the Website <a href="#changes-to-the-website" id="changes-to-the-website"></a>

We may update the content on the Website from time to time, but its content is not necessarily complete or up-to-date. Any of the material on the Website may be out of date at any given time, and we are under no obligation to update such material.

### Information About You and Your Visits to the Website <a href="#information-about-you-and-your-visits-to-the-website" id="information-about-you-and-your-visits-to-the-website"></a>

All information we collect on the Website is subject to our Privacy Policy. By using the Website, you consent to all actions that may be taken by us with respect to your information in compliance with the Privacy Policy.

### Linking to the Website and Social Media Features <a href="#linking-to-the-website-and-social-media-features" id="linking-to-the-website-and-social-media-features"></a>

You may link to our homepage, provided you do so in a way that is fair and legal and does not damage our reputation or take advantage of it, but you must not establish a link in such a way as to suggest any form of association, approval or endorsement on our part without our express written consent.

### Links from the Website <a href="#links-from-the-website" id="links-from-the-website"></a>

If the Website contains links to other sites and resources provided by third parties, these links are provided for your convenience only. This includes links contained in advertisements, including banner advertisements and sponsored links. We have no control over the contents of those sites or resources, and accept no responsibility for them or for any loss or damage that may arise from your use of them. If you decide to access any of the third party websites linked to the Website, you do so entirely at your own risk and subject to the terms and conditions of use for such Website. We reserve the right to withdraw linking permission without notice.

### Geographic Restrictions <a href="#geographic-restrictions" id="geographic-restrictions"></a>

The owner of the Website is based in the Cayman Islands. We make no claims that the Website or any of its content is accessible or appropriate outside of the Cayman Islands. Access to the Website may not be legal by certain persons or in certain countries. If you access the Website from outside the Cayman Islands, you do so on your own initiative and are responsible for compliance with local laws.

Without limiting the foregoing, the Website is not offered to, and must not be accessed or used by, any Sanctioned Person or any person located in, ordinarily resident in, or organized under the laws of any Sanctioned Jurisdiction (each as defined in “Who May Use the Website” above). We reserve the right to restrict access to the Website, or any part of it, from any jurisdiction at any time.

### Disclaimer of Warranties <a href="#disclaimer-of-warranties" id="disclaimer-of-warranties"></a>

You understand that we cannot and do not guarantee or warrant that files available for downloading from the internet or the Website will be free of viruses or other destructive code. You are responsible for implementing sufficient procedures and checkpoints to satisfy your particular requirements for anti-virus protection and accuracy of data input and output, and for maintaining a means external to our site for any reconstruction of any lost data. WE WILL NOT BE LIABLE FOR ANY LOSS OR DAMAGE CAUSED BY A DISTRIBUTED DENIAL-OF-SERVICE ATTACK, VIRUSES, OR OTHER TECHNOLOGICALLY HARMFUL MATERIAL THAT MAY INFECT YOUR COMPUTER EQUIPMENT, COMPUTER PROGRAMS, DATA, OR OTHER PROPRIETARY MATERIAL DUE TO YOUR USE OF THE WEBSITE OR ANY SERVICES OR ITEMS OBTAINED THROUGH THE WEBSITE OR TO YOUR DOWNLOADING OF ANY MATERIAL POSTED ON IT, OR ON ANY WEBSITE LINKED TO IT. YOUR USE OF THE WEBSITE, THEIR CONTENT AND ANY SERVICES OR ITEMS OBTAINED THROUGH THE WEBSITE IS AT YOUR OWN RISK. THE WEBSITE, THEIR CONTENT AND ANY SERVICES OR ITEMS OBTAINED THROUGH THE WEBSITE IS PROVIDED ON AN "AS IS" AND "AS AVAILABLE" BASIS, WITHOUT ANY WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED. NEITHER FLAYER NOR ANY PERSON ASSOCIATED WITH FLAYER MAKES ANY WARRANTY OR REPRESENTATION WITH RESPECT TO THE COMPLETENESS, SECURITY, RELIABILITY, QUALITY, ACCURACY, OR AVAILABILITY OF THE WEBSITE. WITHOUT LIMITING THE FOREGOING, NEITHER FLAYER NOR ANYONE ASSOCIATED WITH FLAYER REPRESENTS OR WARRANTS THAT THE WEBSITE, THEIR CONTENT OR ANY SERVICES OR ITEMS OBTAINED THROUGH THE WEBSITE WILL BE ACCURATE, RELIABLE, ERROR-FREE OR UNINTERRUPTED, THAT DEFECTS WILL BE CORRECTED, THAT THE WEBSITE OR THE SERVER(S) THAT MAKES THEM AVAILABLE ARE FREE OF VIRUSES OR OTHER HARMFUL COMPONENTS OR THAT THE WEBSITE OR ANY SERVICES OR ITEMS OBTAINED THROUGH THE WEBSITE WILL OTHERWISE MEET YOUR NEEDS OR EXPECTATIONS. FLAYER HEREBY DISCLAIMS ALL WARRANTIES OF ANY KIND, WHETHER EXPRESS OR IMPLIED, STATUTORY, OR OTHERWISE, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, AND FITNESS FOR PARTICULAR PURPOSE. SOME JURISDICTIONS DO NOT ALLOW EXCLUSION OF WARRANTIES OR LIMITATIONS ON THE DURATION OF IMPLIED WARRANTIES, SO THE ABOVE DISCLAIMER MAY NOT APPLY TO YOU IN THEIR ENTIRETIES, BUT WILL APPLY TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW.

### Limitation on Liability <a href="#limitation-on-liability" id="limitation-on-liability"></a>

IN NO EVENT WILL FLAYER, ITS AFFILIATES OR THEIR LICENSORS, SERVICE PROVIDERS, EMPLOYEES, AGENTS, OFFICERS, OR DIRECTORS BE LIABLE FOR DAMAGES OF ANY KIND, UNDER ANY LEGAL THEORY, ARISING OUT OF OR IN CONNECTION WITH YOUR USE, OR INABILITY TO USE, THE WEBSITE, ANY WEBSITE LINKED TO THEM, ANY CONTENT ON THE WEBSITE OR SUCH OTHER WEBSITE OR ANY SERVICES OR ITEMS OBTAINED THROUGH THE WEBSITE OR SUCH OTHER WEBSITE, INCLUDING ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL, CONSEQUENTIAL OR PUNITIVE DAMAGES, INCLUDING BUT NOT LIMITED TO, PERSONAL INJURY, PAIN AND SUFFERING, EMOTIONAL DISTRESS, LOSS OF REVENUE, LOSS OF PROFITS, LOSS OF BUSINESS OR ANTICIPATED SAVINGS, LOSS OF USE, LOSS OF GOODWILL, LOSS OF DATA, AND WHETHER CAUSED BY TORT (INCLUDING NEGLIGENCE), BREACH OF CONTRACT OR OTHERWISE, EVEN IF FORESEEABLE. THE FOREGOING DOES NOT AFFECT ANY LIABILITY WHICH CANNOT BE EXCLUDED OR LIMITED UNDER APPLICABLE LAW WHICH MAY INCLUDE FRAUD.

### Indemnification <a href="#indemnification" id="indemnification"></a>

You agree to defend, indemnify, and hold harmless Flayer, its affiliates, licensors, and service providers, and its and their respective officers, directors, employees, contractors, agents, licensors, suppliers, successors, and assigns from and against any claims, liabilities, damages, judgments, awards, losses, costs, expenses, or fees (including reasonable attorneys' fees) arising out of or relating to your violation of these Terms of Use or your use of the Website, including, but not limited to, any use of the Website’ content, services and products other than as expressly authorized in these Terms of Use or your use of any information obtained from the Website.

### Governing Law and Jurisdiction <a href="#governing-law-and-jurisdiction" id="governing-law-and-jurisdiction"></a>

All matters relating to the Website and these Terms of Use and any dispute or claim arising therefrom or related thereto (in each case, including non-contractual disputes or claims), shall be governed by and construed in accordance with the internal laws of the Cayman Islands without giving effect to any choice or conflict of law provision or rule (whether of the Cayman Islands or any other jurisdiction).

Any dispute arising out of or in connection with the Website and these Terms of Use, including any question regarding its existence, validity or termination, shall be referred to and finally resolved by arbitration under the rules of the London Court of International Arbitration (“LCIA”), which rules are deemed to be incorporated by reference into this clause. The number of arbitrators shall be one. The seat, or legal place, of arbitration shall be London, United Kingdom. The language to be used in the arbitration shall be English. You and Flayer agree to submit all Disputes between you and Flayer to individual binding arbitration. “Dispute” means any dispute, claim, or controversy between you and Flayer that relates to the Website and these Terms of Use.

If a Dispute must be arbitrated, you or Flayer must start arbitration of the Dispute within one (1) year from when the Dispute first arose. If applicable law requires you to bring a claim for a Dispute sooner than one (1) year after the Dispute first arose, you must start arbitration in that earlier time period. Flayer encourages you to tell us about a Dispute as soon as possible so we can work to resolve it. The failure to provide timely notice will bar all claims.

In any Dispute, the arbitrator will award to the prevailing party, if any, the costs and attorneys' fees reasonably incurred by the prevailing party in connection with those aspects of its claims or defenses on which it prevails, and any opposing awards of costs and legal fees awards will be offset.

Any breach by you of these Terms of Use could cause Flayer irreparable harm for which it has no adequate remedies at law. Accordingly, Flayer is entitled to seek specific performance or injunctive relief for any such breach. Nothing in this section will preclude Flayer from seeking specific performance or injunctive relief from a court of appropriate jurisdiction.

### Waiver and Severability <a href="#waiver-and-severability" id="waiver-and-severability"></a>

No waiver by Flayer of any term or condition set forth in these Terms of Use shall be deemed a further or continuing waiver of such term or condition or a waiver of any other term or condition, and any failure of Flayer to assert a right or provision under these Terms of Use shall not constitute a waiver of such right or provision.

If any provision of these Terms of Use is held by a court or other tribunal of competent jurisdiction to be invalid, illegal, or unenforceable for any reason, such provision shall be eliminated or limited to the minimum extent such that the remaining provisions of the Terms of Use will continue in full force and effect.

### Entire Agreement <a href="#entire-agreement" id="entire-agreement"></a>

The Terms of Use, our Privacy Policy and other terms and conditions applicable at the time you access the Website constitute the sole and entire agreement between you and Flayer with respect to the Website and supersede all prior and contemporaneous understandings, agreements, representations and warranties, both written and oral, with respect to the Website.


# Whitepaper

The following features are all made possible by our novel implementation of Uniswap V4 hooks, which have accelerated the potential for capital formation and decentralized coordination. We harness these to create financial features previously unavailable to the market.

### Revenue Share

It is no secret that memecoin trading fees have enriched platforms and cabals. The largest memecoins will generate as much as $1,000,000 per day in trading fees. But these fees almost exclusively reward the launch platforms themselves.

<figure><img src="https://1229184497-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoleIQgpsdD3uHYHcTay2%2Fuploads%2Fgit-blob-3fe16debcede66ca76e77e058adc45ac8453f52c%2Fimage.png?alt=media" alt="" width="563"><figcaption><p>Many such cases</p></figcaption></figure>

Flaunch ensures that 100% of these trading fees are retained by the dev and their community.

When a coin is flaunched the dev chooses their revenue share. A profit maxi dev might choose to take 80% of the fees. The remaining amount (20% in this case) is reserved for the memecoin’s treasury, which is controlled by the token holders.

<figure><img src="https://1229184497-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoleIQgpsdD3uHYHcTay2%2Fuploads%2Fgit-blob-1a4374a926bf1c90c5f70bb1a9832330bb494262%2Fimage.png?alt=media" alt="" width="563"><figcaption><p>Passive revenue streams unlocked...</p></figcaption></figure>

On the other hand, a creator like Vitalik, may choose to flaunch $VITAMIN with a community that receives 100% of the trading fees. Such a coin would likely generate huge volumes, leading to a sustainable revenue stream for $VITAMIN holders that can be used to fund public goods and charitable efforts while speculation off the back of speculation.

### Tokenized Revenue Stream

Streaming revenue to memecoin creators is cool, but what if those revenue streams were tokenized?

In one of the most profound developments since the financialization of Pepe the Frog, tokenized revenue streams will unlock a new financial primitive for memes:

<figure><img src="https://1229184497-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoleIQgpsdD3uHYHcTay2%2Fuploads%2FFYaqh6CbW895RHSx7fYS%2Fimage.png?alt=media&amp;token=c99cb3d4-6dd4-438e-aeb6-0523e5c1707a" alt="" width="563"><figcaption><p>Tokenized revenue streams unlock MemeFi</p></figcaption></figure>

* Selling streams - Devs who want an exit will have the option to sell their stream to willing investor(s).
* Future revenue as collateral - Devs could borrow against their future revenue by putting up their meme stream as collateral.
* Distributed streams - Devs can put the stream in a DAO or multi-sig, or fractionalize and distribute streams in a fully decentralized manner.
* Interest rate swaps - Devs can sell their variable rate yield from their memecoin volumes to others who are willing to pay fixed yield, further financializing the meme.

In the end, and through shared ownership, these tokenized meme streams could form the basis of businesses, franchises—and for the most ambitious cultures—Network States.

### Progressive Bid Wall

Through the use of Uniswap V4 hooks, it is possible to automate a Progressive Bid Wall (PBW) that sends ETH into a liquidity position 1 tick below spot to help provide price support to memecoins as they grow.

The PBW is self-funded from swap fees with a secondary hook that ensures all fees (token0 and token1) are both accumulated entirely as ETH without creating sell pressure on the memecoin.

<figure><img src="https://1229184497-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoleIQgpsdD3uHYHcTay2%2Fuploads%2F2LhMCdMuk92X6IrYzTlC%2Fimage.png?alt=media&amp;token=5ded95b1-391d-44c2-9660-e374e7685da8" alt="" width="563"><figcaption><p>The PBW follows the price as it moves up</p></figcaption></figure>

PBWs have the effect of supporting price, without risk of loss to MEV or bots via market buys, achieving a more effective result for memecoin holders.

### Fixed-Price Fair Launch

Every coin starts with a 30 minute Fair Launch period where a % of the total token supply (100,000,000,000) is set at a single tick. During this period the price will be fixed, ensuring that degens, bots and KOLs enter on a level playing field.

After this period ends all of the ETH raised moves into a PPP that sits below spot, ensuring that buyers from the Fair Launch period can exit at the same price (minus fees). The tokens that were not sold, along with any tokens not deployed in the Fair Flaunch, are then moved into a full range position from the current spot price, opening up the token to price discovery.

The liquidity position is effectively burned from the moment the coin flaunches with revenue streams permanently in the hands of the dev and memecoin holders.

<figure><img src="https://1229184497-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoleIQgpsdD3uHYHcTay2%2Fuploads%2FMMTU8wlqnspXOg5jQxT9%2Fimage.png?alt=media&amp;token=4eb30925-9ad1-4945-ad4a-789880a78c65" alt="" width="563"><figcaption><p>ETH from fair launch goes into a bid wall for users to sell at their entry (minus fees)</p></figcaption></figure>

### CONCLUSION

In the world of crypto, memes have always been more than jokes—they’re culture, identity, and collective dreams wrapped in viral magic. But for too long, the power and profits from this Meme Economy have been hijacked by secretive cabals and centralized platforms.

The culture of fleeting gains and unfulfilled promises has drained the potential of memecoins and their communities for far too long. With the advent of the tools laid out in this manifesto, the landscape shifts dramatically.

The fair, decentralized, and transparent path forward is here. With flaunch, memecoin creators and their communities have the means to build, grow, and profit together. The days of massive value extraction are over.

Now is the time to take part in something bigger—a permissionless Meme Economy that restores control to the devs and degens alike. This is your moment. Join us in building the Meme Economy of tomorrow.

<https://t.me/flaunchgg>


# Flaunchy

Flaunch's mascot and AI token launcher. Tweet him a name, he launches the coin.

Flaunchy is Flaunch's mascot and AI token launcher. Mention him on X with a token name and he launches a memecoin for you onchain, then replies with the contract address and a link to its flaunch.gg coin page. No wallet connect, no forms, no gas.

Talk to Flaunchy on Twitter/X: [x.com/flaunchybot](https://x.com/flaunchybot)

## How to launch

The whole flow is one tweet. Mention [@flaunchybot](https://x.com/flaunchybot) and tell him what to launch. A name is all he needs; everything else has a default.

```
💬 you: @flaunchybot launch Timer (TIME)
🐈‍⬛ flaunchy: gm. launching $TIME on base...
🐈‍⬛ flaunchy: $TIME is live: https://flaunch.gg/base/coins/0x1234...
```

You can also reply "flaunch it" under any post, and Flaunchy will spin a coin out of it:

```
💬 alice: someone should make a rocket coin 🚀
💬 you: @flaunchybot flaunch it
🐈‍⬛ flaunchy: $RCKT is live: https://flaunch.gg/base/coins/0x9abc...
```

### What Flaunchy needs from you

* **Name** - required. Used exactly as you write it.
* **Ticker** - optional. Leave it out and Flaunchy picks one (1 to 8 characters).
* **Image** - optional. Attach one and it becomes the coin's art. Otherwise the default Flaunch token image is used.
* **Everything else** - description, fee setup, and which chain to use are all handled automatically.

You don't need a wallet to launch. Flaunchy creates a claimable wallet tied to your X account, so your fees are waiting for you when you log in at flaunch.gg.

## What you get

* **Free to launch** - no cost, no gas, no wallet setup.
* **$10K starting market cap, straight to market** - there is no fair-launch period, so price discovery starts the moment the coin goes live.
* **80% of trading fees, paid in ETH** - streamed for the life of the coin and claimable at flaunch.gg by logging in with your X account.
* Coins launch on **Base** and **Robinhood Chain**. Flaunchy picks a live chain for you.

Every launch reply includes the coin's flaunch.gg link and its `$TICKER`, so you can trade and share it right away. Coin pages live at `flaunch.gg/{chain}/coins/<address>`, for example `flaunch.gg/base/coins/<address>`.

### About the fees

You keep 80% of your coin's trading fees, in ETH, for as long as it trades. Flaunchy keeps the other 20% for running the launch. If you would rather keep 100%, you can launch directly on flaunch.gg and configure the coin yourself; going through Flaunchy is the free, one-tweet path, and the cut is what keeps him running.

## Coming soon

* **Fee splitting** - split your 80% share across multiple wallets. Today the full creator share goes to the launcher.
* **Custom pairing** - launch a coin paired against a token other than ETH. Today every coin pairs against ETH.


# Brand Kit

### **Logo**

<figure><img src="https://1229184497-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoleIQgpsdD3uHYHcTay2%2Fuploads%2FgwkyYUUVZjogE0mHIcQp%2Flogos.png?alt=media&amp;token=8759b48d-c82e-4d3a-b880-8e920cfbad87" alt=""><figcaption></figcaption></figure>

{% file src="/files/dJ22kIEcBYvdPsd8Ptl1" %}

### Color Palette

<table data-view="cards"><thead><tr><th></th><th data-hidden data-card-cover data-type="image">Cover image</th></tr></thead><tbody><tr><td>Magenta<br>Hex: #FF49B4</td><td><a href="https://1229184497-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoleIQgpsdD3uHYHcTay2%2Fuploads%2Fs24q7cW6kXbAb72UXn0C%2Fmagenta.png?alt=media&amp;token=c8244b59-50f0-4a13-beb0-b2369d3a26d8">magenta.png</a></td></tr><tr><td>Purple<br>Hex: #B280FF</td><td><a href="https://1229184497-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoleIQgpsdD3uHYHcTay2%2Fuploads%2F8MpoJjDLxBYpLeO26rQB%2Fpurple.png?alt=media&amp;token=bf47cb08-be32-4964-9acd-b22e09d05245">purple.png</a></td></tr><tr><td>Black<br>Hex: #0A0A0A</td><td><a href="https://1229184497-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoleIQgpsdD3uHYHcTay2%2Fuploads%2FIdjXmrVkaoMhZv0DDWIa%2Fblack.png?alt=media&amp;token=818e7ccb-4060-4061-8606-239c5ecccd16">black.png</a></td></tr><tr><td>Blue<br>Hex: #00B6DD</td><td><a href="https://1229184497-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoleIQgpsdD3uHYHcTay2%2Fuploads%2FtE5c6cS1K9NiCWGWMFRw%2FBlue.png?alt=media&amp;token=7a097632-49e2-4cea-8467-5d0ee53e9fcb">Blue.png</a></td></tr><tr><td>Emerald<br>Hex: #00A473</td><td><a href="https://1229184497-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoleIQgpsdD3uHYHcTay2%2Fuploads%2FHcWuDoEIAcDaxiszATo2%2Femerald.png?alt=media&amp;token=07538090-6758-449b-8124-56dab8e68aa2">emerald.png</a></td></tr><tr><td>White<br>Hex: #FFFFFF</td><td><a href="https://1229184497-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoleIQgpsdD3uHYHcTay2%2Fuploads%2FwXGftNG6dUk7bOmBvWsU%2Fwhite.png?alt=media&amp;token=bfaf5033-6581-4fac-a6e6-f6f299344bfc">white.png</a></td></tr></tbody></table>

### Typography

<table data-view="cards"><thead><tr><th></th><th data-hidden data-card-cover data-type="image">Cover image</th></tr></thead><tbody><tr><td>Headings<br>BB TORSOS</td><td><a href="https://1229184497-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoleIQgpsdD3uHYHcTay2%2Fuploads%2F6jfzwUWoAoDvPt33A2hm%2Fbbtorsos.png?alt=media&amp;token=e66d13d3-921b-45a0-8f8c-d5a917331627">bbtorsos.png</a></td></tr><tr><td>Body<br>Basier Circle</td><td><a href="https://1229184497-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoleIQgpsdD3uHYHcTay2%2Fuploads%2F4PCg0WeTK7Q7OpWHKsRP%2Fbasier.png?alt=media&amp;token=3f3aa771-8482-4630-b8bf-59ed75363e0f">basier.png</a></td></tr></tbody></table>


# Governance

The Flaunch protocol has an option for a protocol fee to be enabled. When enabled, a percentage of swap fees are managed and used through Tally proposals via $FLAY holder voting.

## Introduction

$FLAY token holders can propose, vote on and execute onchain proposals through governance. We use [Tally.xyz](https://www.tally.xyz/gov/flayer) to manage our governance proposals and execution.

{% hint style="info" %}
Our $FLAY token implements the [ERC20Votes](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v5.0/contracts/token/ERC20/extensions/ERC20Votes.sol) standard to power our governance.
{% endhint %}

The token governance has two key areas of control in the Flaunch protocol:

1. Control of enabling and disabling a protocol fee
2. Utilizing ETH earned from protocol fees

## Governance Resources

{% content-ref url="/pages/VIP3t7PwvubACv9D5l4v" %}
[Broken mention](broken://pages/VIP3t7PwvubACv9D5l4v)
{% endcontent-ref %}

{% content-ref url="/pages/gWOe3qRmvFVCBHxVJjbh" %}
[Broken mention](broken://pages/gWOe3qRmvFVCBHxVJjbh)
{% endcontent-ref %}

## Contract Addresses

#### Ethereum Mainnet (Chain ID: 1)

<table><thead><tr><th width="229.1016845703125">Contract</th><th>Address</th></tr></thead><tbody><tr><td>Governor</td><td><code>0x8BA5eA8c8b1Aafe9dbcb7a36737AcfAd6afa5D38</code></td></tr><tr><td>Token</td><td><code>0xF1A7000000950C7ad8Aff13118Bb7aB561A448ee</code></td></tr><tr><td>Timelock</td><td><code>0x6c4c0CD7E0E5eeFfbd77AAfe1820d3b9B1ef27b0</code></td></tr></tbody></table>

#### Base Mainnet (Chain ID: 8453)

<table><thead><tr><th width="229.1016845703125">Contract</th><th>Address</th></tr></thead><tbody><tr><td>L2Owner</td><td><code>0x000000000Bb63D5c070d0D5791517886a4d8C545</code></td></tr></tbody></table>


# Proposals and Voting

## How can I take part in governance?

You can take part in governance by just holding $FLAY token and heading over to [Tally.xyz](https://www.tally.xyz/gov/flayer) to vote on any existing or upcoming proposals. If you hold sufficient $FLAY token, you can also create proposals to be voted on.

{% hint style="warning" %}
Delegation and voting must be undertaken on the Ethereum Mainnet. If you need to bridge your $FLAY tokens from Base to Ethereum Mainnet, then we [recommend using Superbridge](https://superbridge.app/?fromChainId=8453\&toChainId=1\&tokenAddress=0xF1A7000000950C7ad8Aff13118Bb7aB561A448ee). Please note that this takes 7 days.
{% endhint %}

## How do I create a proposal?

Creating a proposal is relatively simple. We have outlined a 5 step flow to creating your proposal. You can also pick up some useful approaches by reviewing existing, successful proposals.<br>

1. View the [current Flayer proposals](https://www.tally.xyz/gov/flayer/proposals) and click to create a new proposal.
2. Ensure that at least 1 million $FLAY is delegated to your address in order to submit a proposal, or find a delegate who has enough delegated $FLAY to meet the proposal threshold to propose on your behalf.
3. Create your proposal. The Tally interface can help to create a series of structured calls to be executed. If writing the calldata yourself, please review the logic with a qualified community member prior to posting the proposal. We would also recommend ensuring that `ProtocolFeeRecipient.claim` is the first call in your proposal to ensure that the full amount of ETH is available to execute with.
4. Once the proposal has been submitted a two day voting delay will start. After the voting delay is finished, a six day voting period begins.
5. If the proposal passes successfully (with a 40 million vote quorum) then a two day timelock will follow before the proposed code is executed.

{% hint style="info" %}
For more information about Tally and their platform, check out their [documentation](https://docs.tally.xyz/).
{% endhint %}

## What does the proposal need to include?

Your proposal should include:<br>

* The reasoning behind your proposal
* The expectation and justification of cost, or outgoing tokens, from your transaction(s)
* The expected benefits to the $FLAY community
* You may also want to include your personal background and experience in your proposal

## What should the proposal be?

As a $FLAY holder, it would be our recommendation that any proposal should have the intention of benefitting the Flayer ecosystem in the longterm. Any proposals that don't align with this have a high likelihood of being voted down.

## How long does a proposal last?

When a proposal threshold is reached, the voting period will start. This will allow for a total of 6 days to vote on the proposal. If the proposal reaches a quorum and passes, then there will be a 2 day grace window until the proposal can be executed.

<table><thead><tr><th width="213.06768798828125">Key</th><th>Value</th></tr></thead><tbody><tr><td>Proposal Threshold</td><td>1 million</td></tr><tr><td>Quorum Needed</td><td>40 million</td></tr><tr><td>Proposal Delay</td><td>2 days</td></tr><tr><td>Voting Period</td><td>6 days</td></tr></tbody></table>

{% hint style="info" %}
Please note, it takes 7 days for $FLAY tokens to bridge from Base to Ethereum Mainnet. It is recommended that tokens are held on Ethereum Mainnet in advance, rather than as a reactive response to a proposal.
{% endhint %}

## What happens when a proposal is executed?

1. Proposals and votes are made on Ethereum Mainnet through delegation of $FLAY token.
2. If proposal passes, the `TimelockController` on Ethereum Mainnet stores the executable calldata set by the proposal.
3. After the timelock of 2 days has passed, the execution can be called on the Ethereum Mainnet `TimelockController`. This executes the proposal arbritrary calldata against the `L2Owner` contract on Base Mainnet.

## How are fees raised for proposals?

Fees are earned from an optional protocol fee switch. More information about how this works, and how it can be enabled, can be found in the resource below.


# Protocol Fee Switch

## How the Fee Switch works

When disabled, the protocol fee share will just be distributed amongst the other fee beneficiaries (token creator, etc). When enabled, the fees will instead first be portioned off to capture an allocation for the protocol.

The fees will then be stored in the traditional `FeeEscrow` contract, ready to be claimed and utilised by governance.

<figure><img src="https://1229184497-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoleIQgpsdD3uHYHcTay2%2Fuploads%2FoJhq7z6tCUYDwyXIvK5x%2FScreenshot%202025-08-29%20at%2015.14.07.png?alt=media&amp;token=95c6a85b-0c4f-44cd-9d98-e04489773c99" alt=""><figcaption></figcaption></figure>

The fee calculation works like a waterfall, with each recipient capturing an amount before being passed to the next recipient.

<figure><img src="https://1229184497-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoleIQgpsdD3uHYHcTay2%2Fuploads%2F0iKyIhc4tUGvUCZAGnyu%2Fcarbon%20(17).png?alt=media&amp;token=c4704d69-36d4-4ad7-8bc5-2aef64c802c7" alt=""><figcaption></figcaption></figure>

Once captured, the swap fee (1%) is distributed across 3 different recipients. One of these, the protocol fee, is optional.

<table><thead><tr><th width="129.5404052734375">Recipient</th><th>Notes</th></tr></thead><tbody><tr><td>Protocol</td><td>Optional fee set by proposal</td></tr><tr><td>Creator</td><td>Defined when the token is flaunched.</td></tr><tr><td>Bidwall</td><td>Defined when the token is flaunched. If the <code>BidWall</code> is not enabled for the token, then it will be directly sent to the <code>MemecoinTreasury</code>.<br><br>If the Memestream NFT has been burned, then this will be allocated to the protocol.</td></tr></tbody></table>

If we assume that a swap takes place for 100 eth and that the protocol fee switch was enabled and set to 5%, then this would result in the following fee distribution:

<table><thead><tr><th width="129.5404052734375">Recipient</th><th width="129.744140625">Amount</th><th>Calculation</th></tr></thead><tbody><tr><td>Swap Fee</td><td>1 eth</td><td><code>100 / 100 * 1</code></td></tr><tr><td>Protocol</td><td>0.0475 eth</td><td><code>(1 - 0.05) / 100 * 5</code></td></tr><tr><td>Creator</td><td>0.722 eth</td><td><code>(1 - 0.05 - 0.0475) / 100 * 80</code></td></tr><tr><td>Bidwall</td><td>0.1805 eth</td><td><code>1 - 0.05 - 0.0475 - 0.722</code></td></tr></tbody></table>

## How is the fee switch enabled?

Each Flaunch `PositionManager` contract has it's own `FeeDistributor` inheritance. This allows the protocol fee to be set explicitly on each `PositionManager`. The fee switch will be enabled when this value is not 0.

{% hint style="warning" %}
The protocol fee must range from between 0% and 10%.
{% endhint %}

The value is represented with 2 decimal places, so a value of `550` would represent a protocol fee of 5.5%, taken from the overall swap fee.

<figure><img src="https://1229184497-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoleIQgpsdD3uHYHcTay2%2Fuploads%2FQde4t6vkqA8EKLkG81Gi%2Fcarbon%20(16).png?alt=media&amp;token=63037e30-ee2d-482b-9624-af46ef454250" alt=""><figcaption></figcaption></figure>

To enable the fees, the governance would need to create a structured proposal that calls each PositionManager and makes the above call to set a protocol fee value.

## Where are these fees stored?

Fees allocated to the protocol will be stored in the same `FeeEscrow` contract in the same way that fees are allocated to creators. These can be claimed by, and only by, the `ProtocolFeeRecipient` at any time. This claim call will be callable by governance to fund any proposals made.

<table><thead><tr><th width="229.1016845703125">Contract</th><th>Address</th></tr></thead><tbody><tr><td>FeeEscrow</td><td><code>0x72e6f7948b1B1A343B477F39aAbd2E35E6D27dde</code></td></tr><tr><td>ProtocolFeeRecipient</td><td><code>0x1150c53eB4cE3aDE47808D1D1Ac9636b774eE079</code></td></tr></tbody></table>

{% hint style="warning" %}
There is a singular exception to this. The first PositionManager contract deployed for Flaunch set the protocol fee recipient as the **Flayer Foundation** multisig. More information regarding this can be found below.
{% endhint %}

## Claiming Fees for proposal use

To claim protocol fees, the `L2Owner` can call `claim` against the `ProtocolFeeRecipient` contract. This provides a simplified flow to call all fees. All fees, like any other fee allocation on Flaunch, are provided exclusively in native ETH.

### A caveat in fee claiming

Due to a contract upgrade during the start of the Flaunch project, if the first PositionManager (`PositionManager1`) enables protocol fees then they will be allocated immutably to the **Flayer Foundation** multisig.

{% hint style="info" %}
At time of writing there are **4755 flaunched tokens** on this `PositionManager1`.
{% endhint %}

For legal purposes, the foundation has **no** obligation to use these protocol fees for buybacks (but with obligations to be positive-sum for everything the Foundation builds). As the `PositionManager1` protocol fee recipient cannot be changed, any fees generated from them will therefore be true to this statement.

All future PositionManagers (post `PositionManager1`) *will* be utilized at the discretion of $FLAY token holders to action on through onchain governance.

### Position Manager Addresses (Chain ID: 8453)

<table><thead><tr><th width="229.1016845703125">Contract</th><th>Address</th></tr></thead><tbody><tr><td>PositionManager1</td><td><code>0x6A53F8b799bE11a2A3264eF0bfF183dCB12d9571</code></td></tr><tr><td>PositionManager2</td><td><code>0xB4512bf57d50fbcb64a3adF8b17a79b2A204C18C</code></td></tr></tbody></table>

## Are the fees safe?

The ETH allocated to the protocol are securely stored onchain in our battle-tested `FeeEscrow` contracts.

This process has been extensively audited and shows no concerns.


# API

This API covers the creation of tokens, revenune managers, uploading images.

{% hint style="info" %}
If you're looking to consume data from the Flaunch API, see the [RESTful API section](/references/restful-data-api).
{% endhint %}

To reduce the friction of creating launchpads and launching tokens we have released an API, allowing builders to create their own launchpad contract and users to launch tokens via their launchpad with no-wallet/no-gas API calls.

There is no requirement for a wallet to be connected and instead a user can Flaunch a token connected to their email address, X (Twitter), Farcaster account or Base wallet address.

The account connected to the flaunched token will be able to connect to Flaunch, or any external flow, using [Privy](https://www.privy.io/) to have access to their launchpad fee or coin fee claims and offramp their fees into either crypto or fiat.

So whether you're extending your existing platform to benefit from token launches, or building a more generic plugin that an entire ecosystem can use, the Flaunch API should have ample logic to support you.

## API Keys

No API keys are required for the use of the Web 2 API endpoint. If you are hitting the current rate limits [reach out on discord](https://discord.gg/PcSmznqqqb) for increased access.

## Example Integration

To demonstrate the power of this API, we have put together a landing page that will allow for fast flaunching across multiple recipient types.

{% embed url="<https://just.flaunch.gg/>" %}
<https://just.flaunch.gg/>
{% endembed %}

{% hint style="info" %}
Have you integrated the Flaunch API? Get in touch and we'll feature it here!
{% endhint %}

## Available API Calls

Below we have documented the API calls that are available for the Memecoin API. These are also available as a Postman collection for quicker prototyping.

{% file src="/files/tsLVXr6JNPpHvV4Yn2u0" %}
Download the Flaunch Memecoin API Postman Collection
{% endfile %}

### Base API URI

```
https://web2-api.flaunch.gg
```

### Supported Chains

The `:chain` segment accepts these slugs. Aliases and numeric chain IDs are rejected with a `400`.

<table><thead><tr><th width="150">Slug</th><th width="95">Chain ID</th><th>Launch</th><th>Fee split at launch</th><th>Existing manager</th><th>Create manager</th></tr></thead><tbody><tr><td><code>base</code></td><td>8453</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr><tr><td><code>base-sepolia</code></td><td>84532</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr><tr><td><code>robinhood</code></td><td>4663</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr></tbody></table>

{% hint style="info" %}
**Fee split at launch works on every chain, including Robinhood.** Passing `feeSplitRecipients` deploys a fee split manager as part of the launch — on Robinhood that is a `DynamicAddressFeeSplitManager`, on Base a static `AddressFeeSplitManager`. Recipient shares behave identically either way.

The distinction that matters is *which* manager gets deployed, not whether managers are supported.
{% endhint %}

Chain support is machine-readable at [`/api/v1/config`](#service-configuration), so you should not need to hardcode this table. Check `capabilities` there before assuming a chain supports an operation:

```json
"capabilities": {
  "feeSplitLaunch": true,     // feeSplitRecipients at launch
  "existingManager": true,    // revenueManagerAddress / feeSplitManagerAddress
  "standaloneManager": true   // create-revenue-manager / create-fee-split-manager
}
```

A chain that does not support an operation rejects it with `Manager operations are not supported on this chain` before any side effect — no metadata is pinned, nothing is queued, and no RPC call is made.

## Health Check

<mark style="color:green;">`GET`</mark> `/livez`

Reports the API's dependency health. `status` is `ok` when every check passes and `degraded` otherwise; the endpoint still returns `200` either way.

**Headers**

<table><thead><tr><th width="270.36688232421875">Name</th><th>Value</th></tr></thead><tbody><tr><td>Content-Type</td><td><code>application/json</code></td></tr></tbody></table>

**Response**

{% tabs %}
{% tab title="\[200] Success Response" %}

```json
{
  "status": "ok",
  "serverWallet": "0xF1a700000087c011413C21C9b357A6962Aa256f9",
  "checks": {
    "rpc": true,
    "redis": true
  }
}
```

{% endtab %}
{% endtabs %}

## Service Configuration

<mark style="color:green;">`GET`</mark> `/api/v1/config`

Returns the chains this deployment supports, their capabilities, and whether sandbox launches are accepted. Prefer this over hardcoding chain lists.

**Response**

{% tabs %}
{% tab title="\[200] Success Response" %}

```json
{
  "success": true,
  "sandbox": false,
  "chains": [
    {
      "slug": "robinhood",
      "chainId": 4663,
      "name": "Robinhood Chain",
      "nativeCurrency": "ETH",
      "blockExplorerUrl": "https://robinhoodchain.blockscout.com",
      "capabilities": {
        "feeSplitLaunch": true,
        "existingManager": false,
        "standaloneManager": false
      }
    }
  ]
}
```

{% endtab %}
{% endtabs %}

## Create a Revenue Manager (Launchpad)

<mark style="color:yellow;">`POST`</mark> `/api/v1/{{ base | base-sepolia | robinhood }}/create-revenue-manager`

**Required Fields**

<table><thead><tr><th width="269.6185302734375">Name</th><th>Value</th></tr></thead><tbody><tr><td><code>protocolFee</code></td><td>Protocol fee in basis points (0-10000, where 100 = 1%)</td></tr></tbody></table>

**Fee Recipient Options (MUST choose one)**

<table><thead><tr><th width="270.05096435546875">Name</th><th>Value</th></tr></thead><tbody><tr><td><code>recipientAddress</code></td><td>Ethereum wallet address for the fee recipient</td></tr><tr><td><code>recipientEmail</code></td><td>Email address for the fee recipient</td></tr><tr><td><code>recipientTwitterUsername</code></td><td>Twitter username (without @ symbol)</td></tr><tr><td><code>recipientFarcasterUsername</code></td><td>Farcaster username (without the @ symbol)</td></tr></tbody></table>

**Optional Fields**

<table><thead><tr><th width="269.72064208984375">Name</th><th>Value</th></tr></thead><tbody><tr><td><code>ownerAddress</code></td><td>Ethereum address that will own the revenue manager (defaults to fee recipient below)</td></tr></tbody></table>

**Headers**

<table><thead><tr><th width="270.0615234375">Name</th><th>Value</th></tr></thead><tbody><tr><td>Content-Type</td><td><code>application/json</code></td></tr></tbody></table>

**Body**

```json
{
  "protocolFee": "1000",
  "recipientAddress": "0x498E93Bc04955fCBAC04BCF1a3BA792f01Dbaa96",
  "ownerAddress": "0xabcdef123456789abcdef123456789abcdef1234"
}
```

**Response**

{% tabs %}
{% tab title="\[200] Success Response" %}

```json
{
    "success": true,
    "managerAddress": "0x57ac78c4a704233e274bbcdeb057ba640b65de23",
    "txHash": "0x171c6358fabc86337bfe6decc6d2d6fc2fe3ca9918a680ad36b5a71bec34e56e",
    "owner": "0x498E93Bc04955fCBAC04BCF1a3BA792f01Dbaa96",
    "recipientAddress": "0xF1a700000087c011413C21C9b357A6962Aa256f9",
    "protocolFee": 1000,
    "privy": null
}
```

{% endtab %}

{% tab title="\[200] Success w/ Privy" %}

```json
{
    "success": true,
    "managerAddress": "0xe21ff18247e8816ab447c2f0eec087503105d948",
    "txHash": "0x3b2ea8464286ac85545de12cb7cbf0d56d37d5149855fcb9871337c2873ae6b8",
    "owner": "0x498E93Bc04955fCBAC04BCF1a3BA792f01Dbaa96",
    "recipientAddress": "0xDAc4A85d446B30F21a79c07097dc56Cd4A07E87b",
    "protocolFee": 1000,
    "privy": {
        "privyUserId": "did:privy:cm8prfp7700eh6kf1zduzfhsh",
        "walletAddress": "0xDAc4A85d446B30F21a79c07097dc56Cd4A07E87b"
    }
}
```

{% endtab %}

{% tab title="\[500] Error Response" %}

```json
{
  "success": false,
  "error": "Invalid protocol fee. Must be a number between 0 and 10000 (0-100%)"
}
```

{% endtab %}
{% endtabs %}

## Create a Fee Split Manager (Launchpad)

<mark style="color:yellow;">`POST`</mark> `/api/v1/:chain/create-fee-split-manager`

Create a reusable fee split manager contract that can be used across multiple token launches.

**Required Fields**

| Name                     | Type   | Description                                                                                           |
| ------------------------ | ------ | ----------------------------------------------------------------------------------------------------- |
| `recipients`             | Array  | Array of fee split recipients (same format as `feeSplitRecipients` above)                             |
| Owner (one required):    |        |                                                                                                       |
| `ownerAddress`           | string | Wallet address of the fee split manager owner                                                         |
| `ownerEmail`             | string | Email address of the owner                                                                            |
| `ownerTwitterUsername`   | string | Twitter username of the owner                                                                         |
| `ownerFarcasterUsername` | string | Farcaster username of the owner                                                                       |
| Creator Share (optional) |        |                                                                                                       |
| `creatorShare`           | number | Optional: Creator share in basis points (0-10000, where 1000 = 10%). Defaults to 0 when not included. |

**Request Examples:**

**Basic Fee Split Manager with Wallet Owner:**

```json
{
  "recipients": [
    {"type": "email", "id": "founder@example.com"},
    {"type": "twitter", "id": "justinavery"},
    {"type": "wallet", "id": "0x1234567890123456789012345678901234567890"}
  ],
  "creatorShare": 1500 // 15% to creator
  "ownerAddress": "0x9876543210987654321098765432109876543210"
}
```

**Custom Splits with Email Owner:**

```json
{
  "recipients": [
    {"type": "email", "id": "founder@example.com", "split": "5000000"},
    {"type": "twitter", "id": "justinavery", "split": "3000000"},
    {"type": "wallet", "id": "0x123...", "split": "2000000"}
  ],
  "creatorShare": 5000 // 50% to creator
  "ownerEmail": "manager@example.com"
}
```

**Success Response**

```json
{
  "success": true,
  "message": "Fee split manager created",
  "managerAddress": "0x6baa4ec493a9698dc7388c0f290e29ea3d149f99",
  "txHash": "0x04e594ee46312eecee8827aa2fef777dd2a94d247b723662be3a6daabb300028",
  "owner": "0x9876543210987654321098765432109876543210",
  "recipients": [
    {
      "address": "0x1234567890123456789012345678901234567890",
      "percentage": "33.33333",
      "originalInput": {"type": "email", "id": "founder@example.com"}
    },
    {
      "address": "0xabcdefabcdefabcdefabcdefabcdefabcdefabcd", 
      "percentage": "33.33333",
      "originalInput": {"type": "twitter", "id": "justinavery"}
    },
    {
      "address": "0x1234567890123456789012345678901234567890",
      "percentage": "33.33334",
      "originalInput": {"type": "wallet", "id": "0x1234567890123456789012345678901234567890"}
    }
  ],
  "totalRecipients": 3
}
```

## Token Metadata Upload

The `/api/v1/upload-metadata` endpoint uploads token metadata to IPFS via Pinata and returns the IPFS hash and token URI. This endpoint is similar to the metadata upload step in the Launch Token flow but is available as a standalone service.

<mark style="color:yellow;">`POST`</mark> `/api/v1/upload-metadata`

**Request Body**

{% code overflow="wrap" %}

```json
{ 
    "name": "string (required)", 
    "symbol": "string (required)", 
    "description": "string (required)", 
    "imageIpfs": "string (required)", 
    "websiteUrl": "string (optional)", 
    "discordUrl": "string (optional)", 
    "twitterUrl": "string (optional)", 
    "telegramUrl": "string (optional)",
}
```

{% endcode %}

**Parameters**

Required.

| Name          | Value                                                                                                                          |
| ------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `name`        | The token name                                                                                                                 |
| `symbol`      | The token symbol                                                                                                               |
| `description` | Token description                                                                                                              |
| `imageIpfs`   | IPFS hash of the token image (without ipfs\:// prefix). Use [Image Upload](#image-upload) endpoint to generate an `imageIPFS`. |

Optional.

| Name          | Value                      |
| ------------- | -------------------------- |
| `websiteUrl`  | Project website URL        |
| `discordUrl`  | Discord server URL         |
| `twitterUrl`  | Twitter/X profile URL      |
| `telegramUrl` | Telegram channel/group URL |

**Response**

{% tabs %}
{% tab title="Success 200" %}

```json
{ 
    "success": true, 
    "ipfsHash": "QmY7Yh4UquoXHLPFo2XbhXkhBvFoPwmQUSa92pxnxjQuPU", 
    "tokenURI": "ipfs://QmY7Yh4UquoXHLPFo2XbhXkhBvFoPwmQUSa92pxnxjQuPU" 
}
```

{% endtab %}

{% tab title="Error 400/500" %}

```json
{ 
    "success": false, 
    "error": "Error message describing what went wrong" 
}
```

{% endtab %}
{% endtabs %}

**Example Usage**

#### *Basic Metadata Upload*

{% code overflow="wrap" %}

```bash
curl -X POST http://web2-api.flaunch.gg/api/v1/upload-metadata
-H "Content-Type: application/json"
-d '{ "name": "My Token", "symbol": "MTK", "description": "A sample token for demonstration", "imageIpfs": "QmSampleImageHash123", "websiteUrl": "https://mytoken.com", "twitterUrl": "https://twitter.com/mytoken" }'

```

{% endcode %}

The endpoint creates ERC-20/ERC-721 compatible metadata with this structure:

```json
  {
    "name": "My Token",
    "description": "A sample token for demonstration",
    "image": "ipfs://QmSampleImageHash123",
    "properties": {
      "websiteUrl": "https://mytoken.com",
      "twitterUrl": "https://twitter.com/mytoken",
    }
  }
```

## Image Upload

<mark style="color:yellow;">`POST`</mark> `/api/v1/upload-image`

Uploads and validates an image before creating a memecoin. Images are checked for appropriate content and stored on IPFS.

{% hint style="info" %}
**Rate Limit:** Maximum 4 image uploads per minute per IP address.
{% endhint %}

**Headers**

<table><thead><tr><th width="270.48968505859375">Name</th><th>Value</th></tr></thead><tbody><tr><td>Content-Type</td><td><code>application/json</code></td></tr></tbody></table>

**Body**

```json
{
  // Base64 Encoded Image String (https://www.base64-image.de/)
  "base64Image": "data:image/jpeg;base64,/9j/4AAQSkZJRgAB...FwySj0f/2Q=="
}
```

**Response**

{% tabs %}
{% tab title="\[200] Success Response" %}

```json
{
  "success": true,
  "ipfsHash": "QmX7UbPKJ7Drci3y6p6E8oi5TpUiG7NH3qSzcohPX9Xkvo",
  "tokenURI": "ipfs://QmX7UbPKJ7Drci3y6p6E8oi5TpUiG7NH3qSzcohPX9Xkvo",
  "nsfwDetection": null
}
```

{% endtab %}

{% tab title="\[400] Generic Error" %}

```json
{
  "success": false,
  "error": "Error message"
}
```

{% endtab %}

{% tab title="\[400] NSFW Image Uploaded" %}

```json
{
  "success": false,
  "error": "Content flagged: Suggestive content",
  "nsfwDetection": {
    "isNSFW": true,
    "score": 0.92,
    "message": "Content flagged: Suggestive content",
    "details": []
  }
}
```

{% endtab %}
{% endtabs %}

## Video Upload

Upload a video file to Cloudflare Stream for use in token creation.

```http
POST /api/v1/upload-video
```

#### Request Body

| Field                | Type     | Description                                                              |
| -------------------- | -------- | ------------------------------------------------------------------------ |
| `maxDurationSeconds` | `number` | Maximum video duration in seconds (default: 300, max: 300)               |
| `maxSizeBytes`       | `number` | Maximum file size in bytes (default: 52,428,800, max: 52,428,800 = 50MB) |
| `userId`             | `string` | User identifier for tracking (default: "anonymous")                      |

#### Rate Limiting

* **10 uploads per hour** per IP address
* API enforces maximum limits of **50MB** and **5 minutes duration**
* Users can specify lower limits via request parameters

#### Request Example

```json
{
  "maxDurationSeconds": 300,
  "maxSizeBytes": 52428800,
  "userId": "user123"
}
```

#### Success Response

```json
{
  "success": true,
  "uploadURL": "https://upload.videodelivery.net/...",
  "videoUID": "c0ee021fd95c4f0d8cc13c70c6172d37",
  "message": "Upload URL generated successfully"
}
```

#### Error Responses

```json
{
  "success": false,
  "error": "Rate limit exceeded. Maximum 10 uploads per hour."
}
```

```json
{
  "success": false,
  "error": "Invalid duration. Maximum 300 seconds allowed."
}
```

#### Upload Process

1. **Request upload URL** from this endpoint
2. **Upload video file** directly to the returned `uploadURL` using a `POST` request with form data
3. **Monitor processing status** using the Video Status endpoint
4. **Use `videoUID`** in token creation once processing is complete

***

### Video Status

Check the processing status of an uploaded video.

```http
GET /api/v1/video-status?uid={videoUID}
```

#### Query Parameters

| Parameter | Type     | Required | Description                             |
| --------- | -------- | -------- | --------------------------------------- |
| `uid`     | `string` | Yes      | Video UID returned from upload endpoint |

#### Response

```json
{
  "success": true,
  "video": {
    "uid": "c0ee021fd95c4f0d8cc13c70c6172d37",
    "state": "nsfw_approved",
    "thumbnailUrl": "https://customer-xyz.cloudflarestream.com/.../thumbnail.jpg",
    "thumbnailIpfsHash": "QmXXXXXXXXX",
    "streamUrl": "https://customer-xyz.cloudflarestream.com/.../manifest/video.m3u8",
    "duration": 15.2,
    "width": 640,
    "height": 480,
    "size": 2097849,
    "created": "2025-06-27T08:31:13.023047Z"
  }
}
```

#### Video States

| State           | Description                                   |
| --------------- | --------------------------------------------- |
| `uploading`     | Video is being uploaded to Cloudflare         |
| `processing`    | Video is being processed and encoded          |
| `nsfw_checking` | Content moderation in progress                |
| `nsfw_approved` | ✅ Video approved and ready for use            |
| `nsfw_rejected` | ❌ Video rejected due to inappropriate content |
| `error`         | Processing failed                             |

***

When [launching your token](#launch-token) you can now include the additional `videoUID` value.

```json
{
  "name": "MyMemeCoin",
  "symbol": "MMC",
  "description": "A memecoin with video content",
  "videoUID": "c0ee021fd95c4f0d8cc13c70c6172d37",
    ... other details
}
```

This will use an automatically generated image from your video. If you would like to customise the thumbnail used for the token you can use the [Image Upload api](#image-upload) and include the resulting IPFS hash in your token creation.

```json
{
  "name": "MyMemeCoin",
  "symbol": "MMC",
  "description": "A memecoin with video content",
  "videoUID": "c0ee021fd95c4f0d8cc13c70c6172d37",
  "imageIpfs": "QmCustomImageHash",

}
```

### List User Videos

Get all videos uploaded by a specific user.

```http
POST /api/v1/video-status
```

#### Request Body

```json
{
  "userId": "user123"
}
```

#### Response

```json
{
  "success": true,
  "videos": [
    {
      "uid": "video1",
      "state": "nsfw_approved",
      "thumbnailIpfsHash": "QmXXXXXX",
      "created": "2025-06-27T08:31:13.023047Z"
    }
  ],
  "count": 1
}

```

### Add video to your app

#### Enhanced Token Metadata

When a video is included, the token metadata structure is enhanced:

```json
{
  "name": "MyMemeCoin",
  "description": "A memecoin with video content",
  "image": "ipfs://QmCustomImageHash",
  "animation_url": "https://customer-xyz.cloudflarestream.com/.../manifest/video.m3u8",
  "properties": {
    "websiteUrl": "",
    "discordUrl": "",
    "twitterUrl": "",
    "telegramUrl": ""
  },
  "video": {
    "uid": "c0ee021fd95c4f0d8cc13c70c6172d37",
    "duration": 15.2,
    "thumbnail": "https://customer-xyz.cloudflarestream.com/.../thumbnail.jpg",
    "streamUrl": "https://customer-xyz.cloudflarestream.com/.../manifest/video.m3u8",
    "width": 640,
    "height": 480,
    "size": 2097849,
    "created": "2025-06-27T08:31:13.023047Z"
  }
}
```

You can use the `streamUrl` and `thumbnail` in your app to showcase your videos.

## Launch Token

<mark style="color:yellow;">`POST`</mark> `/api/v1/{{ base | base-sepolia | robinhood }}/launch-memecoin`

{% hint style="info" %}
Tokens can be launched on `base`, `base-sepolia` or `robinhood`. See [Supported Chains](#supported-chains) for what each one allows.
{% endhint %}

Creates a new memecoin token on the selected network with the following default parameters:

* $10k starting market cap
* 80% dev / 20% community split
* No revenue manager
* Launched immediately; fair launch and sniper protection are currently paused

After a token has been flaunched, a `jobId` will be returned in the response. This `jobId` signifies its position in a queue to be flaunched. It can then be referenced when querying the `launch-status` endpoint to retrieve the status of the token and subsequent deployed contract address of the token.<br>

**Required Fields**

<table><thead><tr><th width="270.1324462890625">Name</th><th>Value</th></tr></thead><tbody><tr><td><code>name</code></td><td>Token name.</td></tr><tr><td><code>symbol</code></td><td>Token symbol (max 8 characters).</td></tr><tr><td><code>imageIpfs</code></td><td>IPFS hash from the image upload endpoint. Optional only if you supply an approved <code>videoUID</code> instead, in which case the video thumbnail is used.</td></tr></tbody></table>

{% hint style="info" %}
`description` is optional and defaults to an empty string.
{% endhint %}

\
**Creator Authentication Options (choose at most one)**

<table><thead><tr><th width="269.556396484375">Name</th><th>Value</th></tr></thead><tbody><tr><td><code>creatorAddress</code></td><td>Ethereum address to receive creator benefits.</td></tr><tr><td><code>creatorEmail</code></td><td>Email address to create a managed wallet via Privy.</td></tr><tr><td><code>creatorTwitterUsername</code></td><td>Twitter username for verification and wallet creation.</td></tr><tr><td><code>creatorFarcasterUsername</code></td><td>Farcaster username for verification and wallet creation.</td></tr></tbody></table>

If no creator authentication option is provided, the creator fees will go to the Flaunch.gg wallet.

**Optional Fields**

<table><thead><tr><th width="270.21417236328125">Name</th><th>Value</th></tr></thead><tbody><tr><td><code>sniperProtection</code></td><td><code>boolean</code> : <strong>Currently paused.</strong> Must be omitted or <code>false</code>; sending <code>true</code> returns a <code>400</code>. See <a href="#antibot-protection">Antibot Protection</a>.</td></tr><tr><td><code>revenueManagerAddress</code></td><td>Ethereum address of a deployed revenue manager (must be valid address format)</td></tr><tr><td><code>feeSplitManagerAddress</code></td><td>Ethereum address of a deployed fee split manager (must be valid address format)</td></tr><tr><td><code>feeSplitRecipients</code></td><td>An array of Ethereum wallet addresses that will automatically receive an equal share of fees from the launched token <code>[0x123..., 0xabc...]</code></td></tr><tr><td><code>creatorShare</code></td><td>Only include when specifying <code>feeSplitRecipients</code> if you also want the creator to take a portion of the fees. (default: 0, basis points so 8000 = 80%)</td></tr><tr><td><code>marketCap</code></td><td>Initial market cap in USDC<br>(default: 4,000 = 4000000000)</td></tr><tr><td><code>creatorFeeSplit</code></td><td>Creator fee allocation in basis points<br>(default: 8000 = 80%)</td></tr><tr><td><code>videoUID</code></td><td>UID of a video that has passed moderation. Attaches video metadata to the token and, when no <code>imageIpfs</code> is given, uses the video thumbnail as the image.</td></tr><tr><td><code>websiteUrl</code></td><td>Website URL</td></tr><tr><td><code>telegramUrl</code></td><td>Telegram group URL</td></tr><tr><td><code>discordUrl</code></td><td>Discord server URL</td></tr><tr><td><code>twitterUrl</code></td><td>Twitter/X URL</td></tr></tbody></table>

{% hint style="info" %}
**Rate Limits:** Maximum 2 memecoin launches per minute per IP address
{% endhint %}

### Antibot Protection

{% hint style="warning" %}
**Currently paused.** Sniper protection depends on fair launch, and both are temporarily disabled. Sending `sniperProtection: true`, or a non-zero `fairLaunchSupply` or `fairLaunchDuration`, is rejected with a `400` before the launch is queued:

```json
{
  "success": false,
  "error": "Sniper protection has been temporarily paused (requires fair launch). Please omit this parameter or set to false."
}
```

Omit these fields, or send `sniperProtection: false` and `"0"` for the fair launch values. This page will be updated when they are re-enabled.
{% endhint %}

When active, `sniperProtection` caps any single wallet at 0.25% of total supply for the duration of the fair launch, then lifts the cap once fair launch ends.

### Treasury Management Options for Token Launches

The memecoin launch API supports four distinct treasury management options:

1. **No Treasury Management**: Default behavior with no fee splitting
2. **Revenue Manager**: Use a pre-deployed revenue manager contract
3. **Fee Split Manager**: Use a pre-deployed fee split manager contract
4. **Custom Fee Split**: Define recipients directly in the launch request

#### Field Documentation

| Name                     | Type              | Description                                                                                                                                                            |
| ------------------------ | ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `revenueManagerAddress`  | string (optional) | Address of a pre-deployed revenue manager contract                                                                                                                     |
| `feeSplitManagerAddress` | string (optional) | Address of a pre-deployed fee split manager contract                                                                                                                   |
| `feeSplitRecipients`     | Array (optional)  | Array of fee split recipients in one of three formats (see below). Remember to also inclue `creatorShare` if you want the token creator to take a portion of the fees. |

#### Mutual Exclusivity Rules

* You can specify either revenueManagerAddress OR feeSplitManagerAddress, never both
* You cannot specify manager addresses and feeSplitRecipients at the same time
* Choose only one treasury management option per token

#### Enhanced feeSplitRecipients Field

The feeSplitRecipients field supports three formats:

**1. Array of wallet addresses (legacy format)**

{% code overflow="wrap" %}

```json
"feeSplitRecipients": [
  "0x1234567890123456789012345678901234567890",
  "0xabcdefabcdefabcdefabcdefabcdefabcdefabcd"
]
```

{% endcode %}

**2. Array of objects with account types (even split):json**

```json
"feeSplitRecipients": [
  {"type": "email", "id": "user@example.com"},
  {"type": "twitter", "id": "username"}, 
  {"type": "farcaster", "id": "username"},
  {"type": "wallet", "id": "0x1234567890123456789012345678901234567890"}
]
```

**3. Array of objects with custom splits:json**

```json
"feeSplitRecipients": [
  {"type": "email", "id": "user@example.com", "split": "5000000"},
  {"type": "twitter", "id": "username", "split": "3000000"},
  {"type": "wallet", "id": "0x123...", "split": "2000000"}
]
```

#### Custom Split Rules

* When using custom splits, all recipients must have splits if any recipient has a custom split
* Splits must sum to exactly `10000000` (representing `100.00000%`)
* Split values are in micro-percentages: multiply UI percentage by `100000`
* Example: `33.33333`% = `"3333333"`, `50`% = `"5000000"`
* Maximum 100 recipients allowed
* 5 decimal precision supported

{% hint style="info" %}
If you also want the `creatorAddress` to receive a portion of the fees you need to specify a `creatorShare` as part of the `POST` body. Omiitting the value defaults to a 0 share or the creator.
{% endhint %}

#### Account Type Validation

| Type        | Validation Rule                                    | Example                                      |
| ----------- | -------------------------------------------------- | -------------------------------------------- |
| `wallet`    | Must be valid Ethereum address (0x + 40 hex chars) | "0x1234567890123456789012345678901234567890" |
| `email`     | Must be valid email format                         | "<user@example.com>"                         |
| `twitter`   | Alphanumeric + underscores, max 15 chars           | "justinavery"                                |
| `farcaster` | Alphanumeric + underscores, 1+ chars               | "javery"                                     |
|             |                                                    |                                              |

**Headers**

<table><thead><tr><th width="269.827880859375">Name</th><th>Value</th></tr></thead><tbody><tr><td>Content-Type</td><td><code>application/json</code></td></tr></tbody></table>

**Body**

{% code title="No Fee Management options" %}

```json
{
  "name": "Example Coin",
  "symbol": "EXCOIN",
  "description": "This is an example memecoin for demonstration purposes.",
  "imageIpfs": "QmR4Tnqvm4SahFwez3FBCbweYwUPUXo2SP8yePhLXYQJkd",
  "websiteUrl": "https://example.com",
  "discordUrl": "https://discord.gg/example",
  "twitterUrl": "https://twitter.com/example",
  "telegramUrl": "https://t.me/example",
  "creatorAddress": "0x498E93Bc04955fCBAC04BCF1a3BA792f01Dbaa96",
  "marketCap": "10000000000",
  "creatorFeeSplit": "8000",
}
```

{% endcode %}

{% code title="Fee Split" %}

```json
{
  "name": "Community Coin",
  "symbol": "COMM",
  "description": "A token with shared revenue among community members",
  "imageIpfs": "QmX7UbPKJ7Drci3y6p6E8oi5TpUiG7NH3qSzcohPX9Xkvo",
  "websiteUrl": "https://community.example.com",
  "creatorAddress": "0x498E93Bc04955fCBAC04BCF1a3BA792f01Dbaa96",
  "creatorShare": 5000 // creator receives 50% of the fees, the other 50% shared to feeSplitRecipients
  // NEW: Fee Split Recipients (choose this OR revenueManagerAddress, not both)
  "feeSplitRecipients": [
    "0x1234567890123456789012345678901234567890",
    "0xabcdefabcdefabcdefabcdefabcdefabcdefabcd",
    "0x9876543210987654321098765432109876543210"
  ],
  
  // Optional advanced settings
  "marketCap": "10000000000",
  "creatorFeeSplit": "8000",
}
```

{% endcode %}

```reason
{
  "name": "Community Coin",
  "symbol": "COMM",
  "description": "A token with shared revenue among community members",
  "imageIpfs": "QmX7UbPKJ7Drci3y6p6E8oi5TpUiG7NH3qSzcohPX9Xkvo",
  "websiteUrl": "https://community.example.com",
  "creatorAddress": "0x498E93Bc04955fCBAC04BCF1a3BA792f01Dbaa96",
  "revenueManagerAddress": "0x57ac78c4a704233e274bbcdeb057ba640b65de23",
  // Optional advanced settings
  "marketCap": "10000000000",
  "creatorFeeSplit": "8000",
}
```

#### Option 1: No Treasury Management

```json
{
  "name": "Simple Token",
  "symbol": "SIMPLE",
  "description": "A basic token with no fee management",
  "imageIpfs": "QmX7UbPKJ7Drci3y6p6E8oi5TpUiG7NH3qSzcohPX9Xkvo",
  "creatorAddress": "0x498E93Bc04955fCBAC04BCF1a3BA792f01Dbaa96"
}
```

#### Option 2: Revenue Manager (require [Revenue Manager](#create-a-revenue-manager-launchpad))

```json
{
  "name": "Revenue Token",
  "symbol": "REV", 
  "description": "A token using a revenue manager",
  "imageIpfs": "QmX7UbPKJ7Drci3y6p6E8oi5TpUiG7NH3qSzcohPX9Xkvo",
  "creatorAddress": "0x498E93Bc04955fCBAC04BCF1a3BA792f01Dbaa96",
  "revenueManagerAddress": "0x712fa8ddc7347b4b6b029aa21710f365cd02d898"
}
```

#### Option 3: Fee Split Manager (require [Fee Split Manager](#create-a-fee-split-manager-launchpad))

```json
{
  "name": "Split Token",
  "symbol": "SPLIT",
  "description": "A token using a pre-deployed fee split manager", 
  "imageIpfs": "QmX7UbPKJ7Drci3y6p6E8oi5TpUiG7NH3qSzcohPX9Xkvo",
  "creatorAddress": "0x498E93Bc04955fCBAC04BCF1a3BA792f01Dbaa96",
  "feeSplitManagerAddress": "0xb31435D40c0cB02c27bf732940dB3d9e4A3b253A"
}
```

{% hint style="info" %}
**Which manager gets deployed.** `feeSplitRecipients` deploys a fee split manager as part of the launch. On Base and Base Sepolia that is a static `AddressFeeSplitManager`; on Robinhood it is a `DynamicAddressFeeSplitManager`, whose recipient shares can be changed after deployment by the moderator (the resolved creator). The request and the response are the same either way — the deployed instance is returned as `feeSplitManagerAddress` on the status endpoint.
{% endhint %}

#### Option 4: Custom Fee Split (Even Distribution, no fees for the creator)

```json
{
  "name": "Community Token",
  "symbol": "COMM",
  "description": "A token with shared revenue among community members",
  "imageIpfs": "QmX7UbPKJ7Drci3y6p6E8oi5TpUiG7NH3qSzcohPX9Xkvo",
  "creatorAddress": "0x498E93Bc04955fCBAC04BCF1a3BA792f01Dbaa96",
  "feeSplitRecipients": [
    {"type": "email", "id": "founder@example.com"},
    {"type": "twitter", "id": "justinavery"},
    {"type": "farcaster", "id": "javery"},
    {"type": "wallet", "id": "0x1234567890123456789012345678901234567890"}
  ]
}
```

#### Option 5: Custom Fee Split (Custom Percentages, 20% of the fees to the creator)

```json
{
  "name": "Weighted Token", 
  "symbol": "WCOMM",
  "description": "A token with custom revenue splits",
  "imageIpfs": "QmX7UbPKJ7Drci3y6p6E8oi5TpUiG7NH3qSzcohPX9Xkvo",
  "creatorAddress": "0x498E93Bc04955fCBAC04BCF1a3BA792f01Dbaa96",
  "creatorShare": 2000
  "feeSplitRecipients": [
    {"type": "email", "id": "founder@example.com", "split": "5000000"},
    {"type": "twitter", "id": "justinavery", "split": "3000000"}, 
    {"type": "wallet", "id": "0x123...", "split": "2000000"}
  ]
}
```

**Response**

{% tabs %}
{% tab title="\[200] Success Response" %}

```json
{
  "success": true,
  "message": "Memecoin launch request queued",
  "jobId": "40",
  
  // Queue status will show how long the expected flaunch time should be. The
  // `estimatedWaitSeconds` can offset the initial "Check Launch Status" delay.
  "queueStatus": {
    "position": 0,
    "waitingJobs": 0,
    "activeJobs": 1,
    "estimatedWaitSeconds": 0
  },
  
  // Privy data will vary depending on the `creatorType` specified
  "privy": {
    "type": "wallet",
    "address": "0x498E93Bc04955fCBAC04BCF1a3BA792f01Dbaa96"
  }
}
```

{% endtab %}

{% tab title="\[400] Missing Data" %}

```json
{
  "success": false,
  "error": "Missing required fields: name, symbol, description, imageIpfs"
}

{
  "success": false,
  "error": "Cannot specify both revenueManagerAddress and feeSplitRecipients. Choose only one treasury option."
}

{
  "success": false,
  "error": "Invalid fee split recipient address: 0xinvalidaddress"
}

{
  "success": false,
  "error": "Duplicate addresses found in fee split recipients"
}
```

{% endtab %}
{% endtabs %}

## Check Launch Status

<mark style="color:green;">`GET`</mark> `/api/v1/launch-status/{{ jobId }}`

Retrieves the launch status of a `jobId`. This endpoint is chainless — the job already knows which chain it was queued for.

**Headers**

<table><thead><tr><th width="270.22760009765625">Name</th><th>Value</th></tr></thead><tbody><tr><td>Content-Type</td><td><code>application/json</code></td></tr></tbody></table>

**Response**

{% tabs %}
{% tab title="\[200]  Job Complete" %}

```json
{
  "success": true,
  "state": "completed",
  "queuePosition": 0,
  "estimatedWaitTime": 0,
  "transactionHash": "0x04e594ee46312eecee8827aa2fef777dd2a94d247b723662be3a6daabb300028",
  "collectionToken": {
    "address": "0x06199b4b69f815141C197D034698d9E67Cdd265b",
    "imageIpfs": "QmQX8pdLRGeNps92Ma4esew7cbnYuBxQK7xUvp5soe3Lec",
    "name": "Community Coin",
    "symbol": "COMM",
    "tokenURI": "ipfs://QmSxzzNaeHbYZbPyFF29Z1PrhrsfNNMyFvebZeuLPrkzvA",
    "creator": "0x498E93Bc04955fCBAC04BCF1a3BA792f01Dbaa96"
  },
  "revenueManagerAddress": null,
  "feeSplitManagerAddress": "0x6baa4ec493a9698dc7388c0f290e29ea3d149f99",

  // Each entry carries the resolved wallet, its share, and the value you
  // originally supplied (an email or handle resolves to an address here).
  // `null` when the launch had no fee split.
  "feeSplitRecipients": [
    {
      "address": "0x1234567890123456789012345678901234567890",
      "percentage": "40.00000",
      "originalInput": "someone@example.com"
    },
    {
      "address": "0xabcdefabcdefabcdefabcdefabcdefabcdefabcd",
      "percentage": "60.00000",
      "originalInput": "0xabcdefabcdefabcdefabcdefabcdefabcdefabcd"
    }
  ]
}
```

{% endtab %}

{% tab title="\[200] Job Pending" %}

```json
{
  "success": true,
  "state": "waiting",
  "queuePosition": 2,
  "estimatedWaitTime": 120
}
```

{% endtab %}

{% tab title="\[200] Job Active" %}

```json
{
  "success": true,
  "state": "active",
  "queuePosition": 0,
  "estimatedWaitTime": 0
}
```

{% endtab %}

{% tab title="\[200] Job Failed" %}

```json
{
  "success": true,
  "state": "failed",
  "queuePosition": 0,
  "estimatedWaitTime": 0,
  "transactionHash": null,
  "error": "Reason the launch failed",
  "collectionToken": null
}
```

If the transaction was already broadcast before the failure, the hash is preserved and the response is annotated. **Check the block explorer before retrying — the launch may in fact have succeeded.**

```json
{
  "success": true,
  "state": "failed",
  "transactionHash": "0x04e594ee...",
  "transactionMayHaveSucceeded": true,
  "error": "<reason>. Note: Transaction was submitted (0x04e594ee...) - please check block explorer to verify status."
}
```

{% endtab %}

{% tab title="\[404] Job Unknown" %}

```json
{
  "success": false,
  "error": "Job not found"
}
```

{% endtab %}
{% endtabs %}


# REST Data API

## Flaunch V1 API Documentation

{% hint style="info" %}
If you are looking to upload images, create revenue managers, or create tokens, [check out the API section](/references/api).
{% endhint %}

### Overview

The Flaunch V1 API provides comprehensive access to token data, trading information, and holder analytics across supported blockchain networks. All endpoints are publicly accessible (no authentication required) and return JSON responses with consistent formatting.

**Base URL**: `https://dev-api.flayerlabs.xyz`

### Supported Networks

The API supports multiple blockchain networks through the `:chain` parameter:

* `base` - Base Mainnet
* `base-sepolia` - Base Testnet

### Global Features

#### Pagination

Most list endpoints support pagination with these query parameters:

* `limit` - Number of items to return (default: 50, max: 100)
* `offset` - Number of items to skip (default: 0)

#### Caching

All endpoints implement intelligent caching with appropriate cache headers for optimal performance.

#### Error Handling

The API returns standard HTTP status codes:

* `200` - Success
* `400` - Bad Request (invalid parameters)
* `404` - Not Found (token/data not found)
* `500` - Internal Server Error

***

### Endpoints

#### 1. Get All Tokens

**Endpoint**: `GET /v1/:chain/tokens`

Returns a paginated list of all tokens sorted by market capitalization (highest first).

**Parameters**

* `chain` (path) - Network identifier (required)
* `limit` (query) - Items per page (optional, default: 50, max: 100)
* `offset` (query) - Items to skip (optional, default: 0)
* `manager` (query) - Filter for tokens with this manager (optional)
* `ownerAddress` (query) - Filter for tokens with this owner (optional)

**Example Request**

```bash
curl "https://dev-api.flayerlabs.xyz/v1/base/tokens?limit=10&offset=0"
```

**Example Response**

```json
{
  "data": [
    {
      "tokenAddress": "0x1c93d155bd388241f9ab5df500d69eb529ce9583",
      "symbol": "FLOKI",
      "name": "Floki Inu",
      "marketCapETH": "1234.567890123456789",
      "createdAt": 1703980800,
      "fairLaunchActive": true,
      "image": "https://example.com/floki.png",
      "description": "Community-driven meme token"
    }
  ],
  "pagination": {
    "limit": 10,
    "offset": 0
  },
  "meta": {
    "network": "mainnet",
    "timestamp": 1703980800
  }
}
```

***

#### 2. Get New Tokens

**Endpoint**: `GET /v1/:chain/tokens/new`

Returns a paginated list of recently created tokens sorted by creation time (newest first).

**Parameters**

* `chain` (path) - Network identifier (required)
* `limit` (query) - Items per page (optional, default: 50, max: 100)
* `offset` (query) - Items to skip (optional, default: 0)
* `manager` (query) - Filter for tokens with this manager (optional)
* `ownerAddress` (query) - Filter for tokens with this owner (optional)

**Example Request**

```bash
curl "https://dev-api.flayerlabs.xyz/v1/base/tokens/new?limit=5"
```

**Example Response**

```json
{
  "data": [
    {
      "tokenAddress": "0x9876543210abcdef9876543210abcdef98765432",
      "symbol": "NEWMEME",
      "name": "New Meme Token",
      "marketCapETH": "0.123456789",
      "createdAt": 1703980800,
      "isActive": true,
      "image": "https://example.com/newmeme.png",
      "description": "Brand new meme token just launched"
    }
  ],
  "pagination": {
    "limit": 5,
    "offset": 0
  },
  "meta": {
    "network": "mainnet",
    "timestamp": 1703980800
  }
}
```

***

#### 3. Get Token Basic Details

**Endpoint**: `GET /v1/:chain/tokens/:tokenAddress`

Returns basic information about a specific token including metadata and social links.

**Parameters**

* `chain` (path) - Network identifier (required)
* `tokenAddress` (path) - Token contract address (required)

**Example Request**

```bash
curl "https://dev-api.flayerlabs.xyz/v1/base/tokens/0x1c93d155bd388241f9ab5df500d69eb529ce9583"
```

**Example Response**

```json
{
  "tokenAddress": "0x1c93d155bd388241f9ab5df500d69eb529ce9583",
  "symbol": "FLOKI",
  "name": "Floki Inu",
  "marketCapETH": "1234.567890123456789",
  "createdAt": 1703980800,
  "image": "https://example.com/floki.png",
  "description": "Community-driven meme token with strong fundamentals",
  "socials": {
    "website": "https://floki.com",
    "twitter": "https://twitter.com/floki",
    "telegram": "https://t.me/floki",
    "discord": "https://discord.gg/floki",
    "farcaster": "https://warpcast.com/floki"
  },
  "meta": {
    "network": "mainnet",
    "timestamp": 1703980800
  }
}
```

***

#### 4. Get Token Full Details

**Endpoint**: `GET /v1/:chain/tokens/:tokenAddress/details`

Returns comprehensive token information including trading data, bid wall information, and detailed metrics.

**Parameters**

* `chain` (path) - Network identifier (required)
* `tokenAddress` (path) - Token contract address (required)

**Example Request**

```bash
curl "https://dev-api.flayerlabs.xyz/v1/base/tokens/0x1c93d155bd388241f9ab5df500d69eb529ce9583/details"
```

**Example Response**

```json
{
  "tokenAddress": "0x1c93d155bd388241f9ab5df500d69eb529ce9583",
  "price": {
    "marketCapETH": "1234.567890123456789",
    "priceChange24h": "12.45",
    "startingMarketCapETH": "100.0"
  },
  "volume": {
    "volume24h": "456.789"
  },
  "trading": {
    "bidWallBalance": "1000.0",
    "bidWallLifetime": "3600",
    "bidWallRemaining": "800.0",
    "bidWallRemainingPercentage": 80.0,
    "buybackBalance": "1000.0",
    "buybackProgress": 20.0
  },
  "status": {
    "fairLaunchActive": true,
    "createdAt": 1703980800,
    "owner": "0xowner123..."
  },
  "socials": {
    "website": "https://floki.com",
    "twitter": "https://twitter.com/floki",
    "telegram": "https://t.me/floki",
    "discord": "https://discord.gg/floki",
    "farcaster": "https://warpcast.com/floki"
  },
  "meta": {
    "network": "mainnet",
    "timestamp": 1703980800
  }
}
```

***

#### 5. Get Token Price Data

**Endpoint**: `GET /v1/:chain/tokens/:tokenAddress/price`

Returns detailed price information with historical time series data across multiple timeframes.

**Parameters**

* `chain` (path) - Network identifier (required)
* `tokenAddress` (path) - Token contract address (required)

**Example Request**

```bash
curl "https://dev-api.flayerlabs.xyz/v1/base/tokens/0x1c93d155bd388241f9ab5df500d69eb529ce9583/price"
```

**Example Response**

```json
{
  "tokenAddress": "0x1c93d155bd388241f9ab5df500d69eb529ce9583",
  "price": {
    "current": "1234.567890123456789",
    "marketCapETH": "1234.567890123456789",
    "priceETH": "0.001234567",
    "priceChange24h": "12.45",
    "priceChange24hPercentage": 12.45,
    "allTimeHigh": "2000.0",
    "allTimeLow": "50.0",
    "startingMarketCapETH": "100.0"
  },
  "volume": {
    "volume24h": "456.789",
    "volume7d": "3200.123"
  },
  "trading": {
    "bidWallBalance": "1000.0",
    "bidWallLifetime": "3600",
    "bidWallRemaining": "800.0",
    "bidWallRemainingPercentage": 80.0,
    "buybackBalance": "1000.0",
    "buybackProgress": 20.0
  },
  "priceHistory": {
    "daily": [
      {
        "timestamp": 1703980800,
        "date": 19722,
        "open": "1200.0",
        "high": "1300.0",
        "low": "1100.0",
        "close": "1234.5",
        "volume": "100.5",
        "marketCap": "1234.5",
        "price": "0.001234"
      }
    ],
    "hourly": [
      {
        "timestamp": 1703980800,
        "open": "1230.0",
        "high": "1240.0",
        "low": "1220.0",
        "close": "1234.5",
        "volume": "10.5",
        "marketCap": "1234.5",
        "price": "0.001234"
      }
    ],
    "minutely": [
      {
        "timestamp": 1703980800,
        "open": "1233.0",
        "high": "1235.0",
        "low": "1232.0",
        "close": "1234.5",
        "volume": "1.5",
        "marketCap": "1234.5",
        "price": "0.001234"
      }
    ],
    "secondly": [
      {
        "timestamp": 1703980800,
        "open": "1234.0",
        "high": "1235.0",
        "low": "1233.0",
        "close": "1234.5",
        "volume": "0.1",
        "marketCap": "1234.5",
        "price": "0.001234"
      }
    ]
  },
  "status": {
    "isActive": true,
    "createdAt": 1703980800,
    "owner": "0xowner123..."
  },
  "meta": {
    "network": "mainnet",
    "timestamp": 1703980800,
    "timeRanges": {
      "dailyStart": 1703376000,
      "hourlyStart": 1703894400,
      "minutelyStart": 1703970000,
      "secondlyStart": 1703980500
    }
  }
}
```

***

#### 6. Get Token Holders

**Endpoint**: `GET /v1/:chain/tokens/:tokenAddress/holders`

Returns a paginated list of token holders sorted by balance (highest first).

**Parameters**

* `chain` (path) - Network identifier (required)
* `tokenAddress` (path) - Token contract address (required)
* `limit` (query) - Items per page (optional, default: 50, max: 100)
* `offset` (query) - Items to skip (optional, default: 0)

**Example Request**

```bash
curl "https://dev-api.flayerlabs.xyz/v1/base/tokens/0x1c93d155bd388241f9ab5df500d69eb529ce9583/holders?limit=10&offset=0"
```

**Example Response**

```json
{
  "tokenAddress": "0x1c93d155bd388241f9ab5df500d69eb529ce9583",
  "totalHolders": "3162",
  "holders": [
    {
      "id": "0x498581ff718922c3f8e6a244956af099b2652b2b",
      "balance": "16544363767544050103679622889"
    },
    {
      "id": "0x742d35cc6354c7deae7a5d3f2f4c2f8b8a8b9e6c",
      "balance": "8272181883772025051839811444"
    },
    {
      "id": "0x1a2b3c4d5e6f7890abcdef1234567890abcdef12",
      "balance": "4136090941886012525919905722"
    }
  ]
}
```

***

### Rate Limits

The API implements reasonable rate limiting to ensure fair usage:

* No authentication required for public endpoints
* Implement reasonable delays between requests (100-200ms recommended)
* Bulk operations should use pagination rather than rapid sequential requests

***

### Support and Resources

* **API Issues**: Report any API issues or bugs through Discord
* **Rate Limiting**: There are no limits, but don't abuse the opportunity otherwise people won't be able to have nice things. Contact the team on Discord if you will be using higher limits for production applications
* **Feature Requests**: Suggest new endpoints or data points you'd like to see added

This documentation provides everything needed to integrate with the FlayerLabs Flaunch V1 API. The examples are production-ready and include proper error handling, caching, and rate limiting considerations.


# Subgraph

## The Flaunch Subgraph

Flaunch uses subgraphs for indexing and organizing data from the Flaunch smart contracts. These subgraphs are hosted on The Graph decentralised service and can be used to query Flaunch data.

### Versions and Production Endpoints <a href="#versions-and-production-endpoints" id="versions-and-production-endpoints"></a>

Flaunch has its own dedicated subgraph for each chain it has been deployed on.

Each subgraph has a dedicated endpoint for querying data, as well as a page on [The Graph explorer](https://thegraph.com/explorer?search=flaunch) that exposes the schema and available fields to query.

**Base Mainnet**

* [Subgraph](https://thegraph.com/explorer/subgraphs/bbWLZuPrmoskDaU64xycxZFE6EvSkMQALKkDpsz5ifF?view=Indexers\&chain=arbitrum-one)
* Graphql Endpoint: `https://gateway.thegraph.com/api/<YOUR_API_KEY_HERE>/subgraphs/id/5zvR82QoaXYFyDEKLZ9t6v9adgnptxYpKpSbxtgVENF`

**Base Sepolia**

* [Subgraph](https://thegraph.com/explorer/subgraphs/9EWUonPMbQVTeXMUZXhEmcvJYmQ95uLe4ggNCKdEhxrw?view=Query\&chain=arbitrum-one)
* Graphql Endpoint: `https://gateway.thegraph.com/api/{api-key}/subgraphs/id/9EWUonPMbQVTeXMUZXhEmcvJYmQ95uLe4ggNCKdEhxrw`


# Solidity Cookbook

This page contains a Solidity-focused technical reference for developers integrating with the Flaunch protocol. All liquidity on Flaunch is built on top of **Uniswap V4**, and swaps are executed using the **Universal Router**.

In addition to swap examples, this reference covers how revenue from launched coins is allocated and claimed using the Flaunch **Escrow** mechanism. You'll also find utilities for **indexing pool metadata**, looking up PoolKeys from PoolIds, and retrieving token ownership data via the Flaunch **Indexer**.

The provided code examples are educational and **not audited or production-ready**. Developers are encouraged to use them as a starting point for understanding how to interact with the Flaunch stack but should conduct proper audits before deploying any derived code to mainnet.

{% hint style="warning" %}
Note that code has not been tested and is provided as-is, as a learning resource, and should not be used in production without proper audits and review.
{% endhint %}

<details>

<summary>Making a Swap</summary>

All of the Flaunch liquidity is powered by Uniswap V4, meaning that swaps can be easily executed using the [Uniswap V4 Universal Router](https://docs.uniswap.org/contracts/v4/guides/swap-routing).

All liquidity on Flaunch is created as FLETH : COIN, meaning that to make a swap between ETH and Token, we will need an intermediary step to either wrap or unwrap ETH <> FLETH.

#### Swapping ETH to / from Token

In the following example we make a 2-step swap to convert ETH to FLETH to COIN.

```solidity
// Encode the Universal Router command
bytes memory commands = abi.encodePacked(uint8(Commands.V4_SWAP));
bytes[] memory inputs = new bytes[](1);

// Encode V4Router actions
bytes memory actions = abi.encodePacked(
    uint8(Actions.SWAP_EXACT_IN_SINGLE),
    uint8(Actions.SWAP_EXACT_IN_SINGLE),
    uint8(Actions.SETTLE_ALL),
    uint8(Actions.TAKE_ALL)
);

// Set the amount being spent
int amountIn = -1e18;

// Set the minimum amount of tokens to receive
uint minAmountOut = 0;

// Set an optional referrer address
address referrer = address(0);

// Define the PoolKey for ETH/FLETH
PoolKey memory ethPoolKey = PoolKey({
    currency0: 0x0000000000000000000000000000000000000000, // ETH
    currency1: 0x000000000d564d5be76f7f0d28fe52605afc7cf8, // FLETH
    fee: 0,
    tickSpacing: 60,
    hooks: IHooks(0x9e433f32bb5481a9ca7dff5b3af74a7ed041a888)
});

// Define the PoolKey for FLETH/COIN
PoolKey memory memePoolKey = PoolKey({
    currency0: 0x000000000d564d5be76f7f0d28fe52605afc7cf8, // FLETH
    currency1: TOKEN,
    fee: 0,
    tickSpacing: 60,
    hooks: IHooks(0x51Bba15255406Cfe7099a42183302640ba7dAFDC)
});

// Prepare parameters for each action
bytes[] memory params = new bytes[](4);

// Param: Swapping ETH to FLETH
params[0] = abi.encode(
    IV4Router.ExactInputSingleParams({
        poolKey: ethPoolKey,
        zeroForOne: true,
        amountIn: amountIn,
        amountOutMinimum: minAmountOut,
        sqrtPriceLimitX96: TickMath.MAX_TICK - 1,
        hookData: bytes('')
    })
);

// Param: Swapping FLETH to COIN
params[1] = abi.encode(
    IV4Router.ExactInputSingleParams({
        poolKey: key,
        zeroForOne: true,
        amountIn: amountIn,
        amountOutMinimum: minAmountOut,
        sqrtPriceLimitX96: TickMath.MAX_TICK - 1,
        hookData: abi.encode(referrer)
    })
);

// Param: Settling spent ETH
params[2] = abi.encode(key.currency0, amountIn);

// Param: Confirming expected min Coin received
params[3] = abi.encode(key.currency1, minAmountOut);

// Combine actions and params into inputs
inputs[0] = abi.encode(actions, params);

// Execute the swap
router.execute(commands, inputs, block.timestamp);
```

</details>

<details>

<summary>Claiming Revenue</summary>

In an effort to simplify the user claiming experience of revenue, as well as to improve security and save gas during transactions under the hood, Flaunch uses an Escrow contract to store flETH that is assigned to a user from all of their coin revenues.

Revenue from coins are allocated and are claimable per-user, as opposed to per-coin or per-user-per-coin. This is beneficial from a protocol perspective, but external protocols may find it hard to track and query fees onchain.

When fees are allocated we assign them to the owner of the coin at the time of allocation, and we also track the total amount of fees that a `PoolId` has generated. These attributes are tracked both onchain in the `FeeEscrow` contract, and in the subgraph.

```solidity
/// Maps a user to an ETH equivalent token balance available in escrow
mapping (address _recipient => uint _amount) public balances;

/// Maps the total fees that a PoolId has accrued
mapping (PoolId _poolId => uint _amount) public totalFeesAllocated;
```

***

If you are wanting to query the amount that an individual coin has earned, that it would be recommended to take one of two approaches.

#### Approach 1: Subgraph Queries

Although this can't be queried directly onchain (without using a platform like [**Chainlink**](https://chain.link/)) it is possible to pull through a coin's lifetime fees via [**The Graph**](https://thegraph.com/).

```graphql
{
  collectionFees(where: {id: 0x...}) {
    lifetimeFees
  }
}
```

{% hint style="info" %}
You can check out our subgraphs below for both mainnet and sepolia:

<https://g.flayerlabs.xyz/flaunch/base-mainnet/graphql>

<https://g.flayerlabs.xyz/flaunch/base-sepolia/graphql>
{% endhint %}

#### Approach 2: Check the onchain FeeEscrow mapping

If you want to be able to query the revenue of the coin onchain, then the mapping in the `FeeEscrow` contract can be used

```solidity
// Get the PoolId of an ERC721
PoolId poolId = FLAUNCH.poolId(ERC721_TOKEN_ID);

// Get the total fees claimed
uint startTotalFeesClaimed = FEE_ESCROW.totalFeesAllocated(poolId);

// Make our claim to retrieve fees
FEE_ESCROW.withdrawFees(address(this), true);

// Find the new pool fees claimed
uint newTotalFeesClaimed = FEE_ESCROW.totalFeesAllocated(poolId);

// Calculate the change in fees
uint feeChange = newTotalFeesClaimed - startTotalFeesClaimed;
```

</details>

<details>

<summary>Lookup PoolId</summary>

Events emitted by the Flaunch protocol will likely be indexed by the Uniswap V4 `PoolId` , as this is unique for the individual token deployment. This is beneficial for event monitoring and subgraph navigation, but if a query then needs to be made onchain to retrieve Pool information this can prove difficult.

To facilitate this lookup functionality, we implemented an `Indexer` subscriber to the **Notifier** hook that captures initialized tokens and then stores various pieces of information that may be beneficial to third party developers, mapped to the `PoolId` as the key. This is mapped to:

```solidity
/*
 * @member flaunch The {Flaunch} contract that launched the token
 * @member memecoin The ERC20 coin address
 * @member memecoinTreasury The contract address for the coin treasury
 * @member tokenId The ERC721 {Flaunch} token created with the coin
 */
struct Index {
    address flaunch;
    address memecoin;
    address memecoinTreasury;
    uint tokenId;
}
```

#### I have a PoolId and want to...

**Find the Pool Key**

In the Uniswap V4 ecosystem, the `PoolId` is calculated by hashing the `PoolKey` struct:

```solidity
/// @notice Returns value equal to keccak256(abi.encode(poolKey))
function toId(PoolKey memory poolKey) internal pure returns (PoolId poolId) {
  assembly ("memory-safe") {
    // 0xa0 represents the total size of the poolKey struct (5 slots of 32 bytes)
    poolId := keccak256(poolKey, 0xa0)
  }
}
```

As this is a one-way encoding, we cannot simply decode the `PoolId`. To achieve this lookup, we first need to [find the ERC20 coin address](#find-the-erc20-memecoin-address) from the `PoolId` and then make a call against the linked `Flaunch` contract's `PositionManager` . This is quite a roundabout way of finding the required information, but through inheritance it's the most optimal route.

```solidity
IndexerSubscriber indexer = IndexerSubscriber(0x..);
(address flaunch, address memecoin,,) = indexer.poolIndex(POOL_ID);
PoolKey memory poolKey = IFlaunch(flaunch).positionManager().poolKey(memecoin);
```

**Find the ERC20 coin address**

Finding the ERC20 coin address of a `PoolId` can be beneficial to quickly determine a swap path for tokens or just confirm the token information that will be displayed. The coin will be stored directly in `Index` struct, so it can be quickly accessed.

```solidity
IndexerSubscriber indexer = IndexerSubscriber(0x..);
(, address memecoin,,) = indexer.poolIndex(POOL_ID);
```

{% hint style="info" %}
The ERC20 coin will always be paired with FLETH.
{% endhint %}

**Find the ERC721 token that owns the PoolId**

When a token is flaunched, an ERC721 token is created to prove ownership and the holder will receive the token dev revs. If you know the `PoolId` you can lookup the ERC721 token and subdequently the holder, `tokenUri` and other important variables.

```solidity
IndexerSubscriber indexer = IndexerSubscriber(0x..);
(address flaunch,,, uint tokenId) = indexer.poolIndex(POOL_ID);

address owner = IERC721(flaunch).ownerOf(tokenId);
```

#### Indexing a Legacy Token

If your token was deployed before the indexed was registered, then it can be added by making a public call to the `addIndex` function on the Indexer. The data is validated internally to confirm that the mapping is legitimate before storing.

```solidity
/**
 * For tokens that were flaunched before this Notifier was put in place, we allow the
 * information to be back-filled. The data is validated before being written and will
 * revert if it is deemed invalid.
 *
 * @param _poolId Array of PoolIds
 * @param _flaunch Array of the flaunch contracts for each tokenId
 * @param _tokenId Array of tokenIds
 */
function addIndex(PoolId[] calldata _poolId, address[] calldata _flaunch, uint[] calldata _tokenId) external;
```

#### Deployed Indexer Addresses

<table><thead><tr><th width="182.1563720703125">Chain</th><th>Deployment Address</th></tr></thead><tbody><tr><td>Base</td><td><em>Coming soon</em></td></tr><tr><td>Base Sepolia</td><td><code>0x9fa6c64c5fe954f7da1832dc190bbabc0c234989</code></td></tr></tbody></table>

</details>

### What is FLETH?

Flaunch introduces its own wrapped ETH equivalent token called **FLETH**, and all token liquidity is paired as **FLETH : COIN**. This means standard ETH ↔ COIN swaps require a two-step conversion process through FLETH.


# Hooks

## Introduction <a href="#core-hook-functions" id="core-hook-functions"></a>

Flaunch extensively uses Uniswap V4 hooks in the `PositionManager` to allow for custom logic to be actioned during any swap and interaction against our pools.

> Uniswap V4 introduces Hooks, a system that allows developers to customize and extend the behavior of liquidity pools.
>
> Hooks are external smart contracts that can be attached to individual pools. Every pool can have one hook but a hook can serve an infinite amount of pools to intercept and modify the execution flow at specific points during pool-related actions.\\
>
> #### Key Concepts[​](https://docs.uniswap.org/contracts/v4/concepts/hooks#key-concepts) <a href="#key-concepts" id="key-concepts"></a>
>
> * Each liquidity pool in Uniswap V4 can have its own hook contract attached to it. Hooks are optional for Uniswap V4 pools.
> * The hook contract is specified when creating a new pool in the `PoolManager.initialize` function.
> * Having pool-specific hooks allows for fine-grained control and customization of individual pools.

## Position Manager

The PositionManager is a Uniswap V4 hook that controls the user journey from token creation, to fair launch, to ongoing swaps.

### Public Functions

{% hint style="info" %}
This does not included public functions found in the hooks implemented; these can be found under this subpage.
{% endhint %}

#### flaunch

Creates a new ERC20 memecoin token creating and an ERC721 that signifies ownership of the flaunched collection. The token is then initialized into a UV4 pool.

```solidity
/**
 * Creates a new ERC20 memecoin token creating and an ERC721 that signifies ownership
 * of the flaunched collection. The token is then initialized into a UV4 pool.
 *
 * The FairLaunch period will start in this call, as soon as the pool is initialized.
 *
 * @return memecoin_ The created ERC20 token address
 */
function flaunch(FlaunchParams calldata _params) external payable returns (address memecoin_) {
  // ..
}
```

#### poolKey

Returns the PoolKey mapped to the token address. If none is set then a zero value will be returned for the fields.

```solidity
/**
 * Returns the PoolKey mapped to the token address. If none is set then a zero value
 * will be returned for the fields.
 *
 * @dev The easiest way to check for an empty response is `tickSpacing = 0`
 *
 * @param _token The address of the ERC20 token
 *
 * @return The corresponding {PoolKey} for the token
 */
function poolKey(address _token) external view returns (PoolKey memory) {
  // ..
}
```

#### getFlaunchingFee

Gets the ETH fee that must be paid to flaunch a token.

```solidity
/**
 * Gets the ETH fee that must be paid to flaunch a token.
 *
 * @return The ETH value of the fee
 */
function getFlaunchingFee() public view returns (uint) {
  // ..
}
```

#### getFlaunchingMarketCap

Gets the ETH market cap for a new token that will be flaunched.

```solidity
/**
 * Gets the ETH market cap for a new token that will be flaunched.
 *
 * @return The ETH market cap value
 */
function getFlaunchingMarketCap() public view returns (uint) {
  // ..
}
```

### Structs

```solidity
/**
 * Defines our constructor parameters.
 *
 * @member nativeToken The native ETH equivalent token used by protocol
 * @member poolManager The Uniswap V4 {PoolManager} contract
 * @member feeDistribution The default fee distribution configuration
 * @member initialPrice Set initial price calculator address
 * @member protocolOwner The EOA that will be the initial owner
 * @member protocolFeeRecipient The recipient EOA of all
 * @member flayGovernance The $FLAY token governance address
 * @member feeExemptions The default global FeeExemption values
 */
struct ConstructorParams {
    address nativeToken;
    IPoolManager poolManager;
    FeeDistribution feeDistribution;
    IInitialPrice initialPrice;
    address protocolOwner;
    address protocolFeeRecipient;
    address flayGovernance;
    FeeExemptions feeExemptions;
}

/**
 * If the creator requests a premine amount of tokens, then these will be cast
 * to this structure.
 *
 * @member amountSpecified The amount of tokens requested to buy as creator
 * @member blockNumber The block that the premine is created and allocated
 */
struct PoolPremineInfo {
    int amountSpecified;
    uint blockNumber;
}

/**
 * Parameters required when flaunching a new token.
 *
 * @member name Name of the token
 * @member symbol Symbol of the token
 * @member tokenUri The generated ERC721 token URI
 * @member initialTokenFairLaunch The amount of tokens to add as single sided fair launch liquidity
 * @member premineAmount The amount of tokens that the creator will buy themselves
 * @member creator The address that will receive the ERC721 ownership and premined ERC20 tokens
 * @member creatorFeeAllocation The percentage of fees the creators wants to take from the BidWall
 * @member flaunchAt The timestamp at which the token will launch
 */
struct FlaunchParams {
    string name;
    string symbol;
    string tokenUri;
    uint initialTokenFairLaunch;
    uint premineAmount;
    address creator;
    uint24 creatorFeeAllocation;
    uint flaunchAt;
}
```

### Which Hooks are Used

This breaks down the functionality included on each Uniswap V4 hook call.

**`beforeInitialize`**

* We prevent external contracts from initializing a pool with this hook contract.

**`afterInitialize`**

* Emit PoolState update to Notifier subscribers and subgraph

**`beforeAddLiquidity`**

* If in fair launch window, we need to prevent liquidity being added by external parties

**`afterAddLiquidity`**

* Emit PoolState update to Notifier subscribers and subgraph

**`beforeRemoveLiquidity`**

* If in fair launch window, we need to prevent liquidity being removed by external parties

**`afterRemoveLiquidity`**

* Emit PoolState update to Notifier subscribers and subgraph

**`beforeSwap`**

* Check if the token is scheduled to be flaunched and only allow a swap to take place if there is a premine call available
* If the FairLaunch window has ended, but our position is still open, then we need to close the position
* We attempt to fill the swap request from our FairLaunch position. If the swap parameters surpass the FairLaunch position, or the window has closed since the last swap, then this call will also close the position and create our new range.
* We want to see if we have any token1 fee tokens that we can use to fill the swap before it hits the Uniswap pool. This prevents the pool from being affected and reduced gas costs. This also allows us to benefit from the Uniswap routing infrastructure. This frontruns Uniswap to sell undesired token amounts from our fees into desired tokens ahead of our fee distribution. This acts as a partial orderbook to remove impact against our pool.

**`afterSwap`**

* Captures fees from the swap to either distribute or send to ISP
* Once a swap has been made, we distribute fees to our LPs and emit our price update event
* If we have a feeCalculator, then we want to track the swap data for any dynamic calculations
* Emit PoolState update to Notifier subscribers and subgraph

**`beforeDonate`**

* Not used

**`afterDonate`**

* Emit PoolState update to Notifier subscribers and subgraph

{% embed url="<https://github.com/flayerlabs/flaunch-contracts/blob/main/src/contracts/PositionManager.sol>" %}
PositionManager.sol
{% endembed %}


# Spend-Gated Launches

A spend-gated launch is a Flaunch pool that refuses swaps unless they carry a signature from a nominated off-chain signer, and that signature names the maximum ETH the swap may spend. It is the mechanism behind [Game Mode](/game-mode/game-mode), and it is general: anything that can decide how much a given wallet should be allowed to spend can drive it.

This page covers the architecture. The two pages beside it go deeper on [the signer](/references/spend-gate/signer) and on [enforcement inside the V4 hook](/references/spend-gate/hook-path).

## The problem: one calculator slot

Flaunch's `PositionManager` has exactly one `feeCalculator`, set by the protocol owner. Every pool routes through it. That is fine while there is one fee policy, and blocking the moment you want a gated launch sitting alongside ordinary ones.

`FeeCalculatorDispatcher` occupies that single slot and routes per pool:

```
                                    ┌─ StaticFeeCalculator      (every ordinary pool)
PositionManager ─> FeeCalculatorDispatcher ─┤
                                    └─ SpendGatedSignerFeeCalculator  (gated pools)
```

A launch opts into a sub-calculator by prefixing its `feeCalculatorParams` with a routing marker:

```solidity
bytes32 constant ROUTING_PREFIX = keccak256('flaunch.dispatcher.route.v1');

feeCalculatorParams = abi.encode(ROUTING_PREFIX, address subCalculator, bytes subParams);
```

A launch without the prefix routes to the default calculator and behaves exactly as it did before the dispatcher existed. Pools configured before the dispatcher was installed keep working too — the dispatcher does not forward `setFlaunchParams` to the default calculator, which is safe precisely because that default is stateless.

Only calculators the dispatcher's owner has registered can be routed to.

## The flow

```
player ──────> game server ──────> signed SpendAuthorization
                                            │
                                            ▼
player's wallet ─── swap(…, hookData) ──> PositionManager
                                            │  afterSwap
                                            ▼
                                    FeeCalculatorDispatcher
                                            │  routed by poolId
                                            ▼
                          SpendGatedSignerFeeCalculator.trackSwap
                                    │
                                    ├─ recover signer, check against the pool's signer
                                    ├─ bind the authorization to its submitter
                                    ├─ measure real ETH input against maxSpendWei
                                    ├─ accumulate against the per-wallet cap
                                    └─ burn the signature
```

Enforcement runs in `afterSwap`, so it measures what the swap actually did rather than what it claimed it would do.

## Configuring the gate at launch

Gate settings are written once per pool, at flaunch time, through `setFlaunchParams`. Two encodings are accepted:

{% tabs %}
{% tab title="Tagged (192 bytes)" %}
The full form. This is the only one that can enable an enforcing gate.

```solidity
abi.encode(
    GATE_PARAMS_TAG,   // keccak256('flaunch.spendGate.params')
    bool   enabled,
    uint   walletCapWei,
    address signer,    // authorizes swaps for this pool
    address settler,   // may rotate or retire the signer
    uint   endsAt      // the gate expires here, on chain
)
```

Naming the signer at launch is what lets a working gate be installed in a **single transaction** — otherwise the signer arrives in a follow-up call, and until it lands nobody can produce a signature the pool accepts.
{% endtab %}

{% tab title="Short (64 bytes)" %}

```solidity
abi.encode(bool enabled, uint walletCapWei)
```

Kept decodable for existing callers. It cannot express an expiry, and an enforcing gate must have one, so in practice this form launches ungated.
{% endtab %}
{% endtabs %}

Anything else reverts with `UnrecognisedGateParams`.

{% hint style="warning" %}
The tag is not decoration. `feeCalculatorParams` is caller-controlled, and length alone is not a discriminator — any other encoding that happened to be six words long would be reinterpreted field for field. A dynamic type sitting in the signer's position decodes its ABI offset as an address, which installs a permanent per-pool signer that nobody holds the key to.
{% endhint %}

`setFlaunchParams` is a launch-time hook and runs at most once per pool. A second call reverts with `GateAlreadyConfigured`, which bounds the damage a compromised `POSITION_MANAGER` role could do to pools that have not launched yet.

## Three roles, and what each one cannot do

<table><thead><tr><th width="150">Role</th><th>Can</th><th>Cannot</th></tr></thead><tbody><tr><td><strong>Creator</strong><br>(holds the Flaunch ERC-721)</td><td>Choose the window, the cap, the signer and the settler at launch</td><td>Touch the signer afterwards — not even to retire it</td></tr><tr><td><strong>Signer</strong></td><td>Issue authorizations that the pool accepts</td><td>Change any pool setting, or authorize past <code>endsAt</code></td></tr><tr><td><strong>Settler</strong></td><td>Rotate the signer, or zero it to open trading early</td><td>Extend the window, or move the cap</td></tr></tbody></table>

The creator's exclusion is the surprising one, and it is deliberate. In Game Mode the launching **player** is the memecoin's creator — that is what makes the round theirs. Zeroing the signer is how that player would buy their own fair launch ungated, for as much as they liked, while everyone else was still earning allowance a point at a time. Nothing downstream would catch it: an ungated swap is indistinguishable from an authorized one to a watcher polling `Swap`.

Nor could the power be pinned to the launching player even if you wanted to. `IMemecoin.creator()` reads the ERC-721 owner live, so the role transfers with a secondary sale of the NFT — it was sellable mid-round to someone the round had never met.

## Expiry is the guarantee

An enforcing gate **must** carry an `endsAt`, and it must be within `MAX_GATE_DURATION` (30 days) of launch. Past that timestamp the calculator stops enforcing outright: no signature demanded, no spend tracked, the pool is an ordinary pool.

This exists because neither the launcher nor the signer is vetted, and they are routinely the same party. `flaunch()` is permissionless and `feeCalculatorParams` is caller-supplied, so a launch can name itself as both its own signer and its own settler. Since the gate enforces on sells as well as buys, such a launcher would otherwise hold a permanent veto over every holder's exit — issue buy authorizations, then simply stop signing, and the position is trapped for as long as the key stays silent.

The expiry makes the exit a property of the pool. It needs no transaction from the launcher, the settler, or the contract owner.

A launch that names a signer but no settler is refused outright (`SettlerRequired`), because the signer *is* the gate and the settler is the only party who can lift it early. One reverted flaunch is a much cheaper failure than a coin nobody can open, discovered when a round tries to settle and cannot.

## Deployments

Game Mode runs on **Ethereum (1)**, **Arbitrum One (42161)**, **Base (8453)** and **Robinhood chain (4663)**, with a test stack on **Base Sepolia (84532)**. Each chain's current stack is the Flaunch v1.3 generation (v1.4.x on Ethereum and Arbitrum, same ABI family), which measures spend in the pool's own paired token: ETH, or any token the chain's `PairedTokenRegistry` has approved.

<table><thead><tr><th width="220">Contract</th><th>Ethereum (1)</th><th>Arbitrum One (42161)</th><th>Base (8453)</th><th>Robinhood (4663)</th><th>Base Sepolia (84532)</th></tr></thead><tbody><tr><td><code>PositionManager</code></td><td><code>0xb741a710E456FC6d7f76c88F5C56B27D05e8A5DC</code></td><td><code>0xCAb62e007AB6656877Ab556cEa330De27AE025DC</code></td><td><code>0x588C683EcC450F8b2aAdb13D7f63792b840425DC</code></td><td><code>0x8D346f24278C5CD786309161aAC0fC2bbe4c25dc</code></td><td><code>0x8D346f24278C5CD786309161aAC0fC2bbe4c25dc</code></td></tr><tr><td><code>FeeCalculatorDispatcher</code></td><td><code>0x99922f8E94E67AB29401F67eBa30163D1e9eb994</code></td><td><code>0xc5eE9697de8544Dc3f63A943A80Bd388Ac30968A</code></td><td><code>0xdbC2F399BbAC8CD766F20C9B917A9A6ECAD5bc4b</code></td><td><code>0x981b0F51667A250Af9DADB86056bf22914F53F27</code></td><td><code>0xd381f8ea57df43c57cfe6e5b19a0a4700396f28c</code></td></tr><tr><td><code>SpendGatedSignerFeeCalculator</code> (what a released gate signs against)</td><td><code>0x8eD725D61AA687951F430Dd6E76e3A0108436005</code></td><td><code>0x9Ef19e3033c23AEECEb96e4C28faCaa15098d0dA</code></td><td><code>0xd8e46a2ca31915d9b76cc8e6b365b7ed46b77b01</code></td><td><code>0x120a2e0f8f431136897dc78c24b069146a65d79a</code></td><td><code>0x54cdcf0bcbc3a33f470e07134c10582f93058a32</code></td></tr><tr><td><code>PoolSwap</code> (approved router, reports <code>msgSender()</code>)</td><td><code>0x05c6C717B2a985809a83D27F779044c2da27fd56</code></td><td><code>0x206cD26d8567Ea76Ffa719995251a3878073Fb8A</code></td><td><code>0x1B8065a099AdcD7aa7c5e241e3596B56ec98bA5a</code></td><td><code>0xD33dD3B3Aea607F2cC38cdd154eF5d48847Aa764</code></td><td><code>0xf0f388a31a1745a5e2378b812ed51525f70595be</code></td></tr><tr><td><code>PairedTokenRegistry</code></td><td><code>0xFc28B339376018727eFcD45fdb257D0A0861A391</code></td><td><code>0x16EF4F8e1d41cE4727d98ae0E9EC4e9cDDd14Ac4</code></td><td><code>0x26958422636655b5a4eCE23a062e2EB61332c6da</code></td><td><code>0xC3F4E72DE4D37988F12C101b0766Fd8462F6Faf9</code></td><td><code>0x23cb441d18CA75c6a14964B06806dF668d45A1C6</code></td></tr></tbody></table>

Every row was read back from its chain on 2026-09-20: each `PositionManager` reports its dispatcher from `feeCalculator()`, each dispatcher has its calculator in `registeredCalculators`, each calculator grants its dispatcher the `PositionManager` role and has its `PoolSwap` in `approvedRouters`. Those four reads are exactly what a gate performs at boot, so a stack that passes them here boots. The `PositionManager` names its registry on chain (`pairedTokenRegistry()`), so a gate discovers the approved pairings and their price calculators without configuration. The dispatcher is installed on the `PositionManager`, with the chain's `StaticFeeCalculator` as its fallback — every non-game launch passes through untouched.

The gate package ships an address book only for Base Sepolia. On every other chain, name the stack in the environment and the gate verifies the wiring above before it serves anything:

```bash
CHAIN_ID=42161
POSITION_MANAGER=0xCAb62e007AB6656877Ab556cEa330De27AE025DC
SPEND_GATED_CALCULATOR=0x9Ef19e3033c23AEECEb96e4C28faCaa15098d0dA
POOL_SWAP=0x206cD26d8567Ea76Ffa719995251a3878073Fb8A
FLAUNCH_VARIANT=v1_3
```

{% hint style="info" %}
**Ethereum** joined the Game Mode parity set on 2026-09-21: the vested launch stack, the v2 calculator and the game developer fee-split manager sit at the same addresses as on Base, Robinhood and Arbitrum, and the protocol Safe has wired them (factory role, indexer mapping, calculator registration, manager approval). Contracts release v1.5.0 carries the record.
{% endhint %}

{% hint style="info" %}
**Superseded stacks keep serving their coins; coins never migrate.** Robinhood's v1.3.1 stack (`PositionManager` `0x588C683E…`, dispatcher `0xe3fDDf48…`, calculator `0xB246b270…`, `PoolSwap` `0x8476ED15…`) and its first-generation stack (`PositionManager` `0x5Cf8e499…`, dispatcher `0x04cDDed8…`, calculator `0xc65fC67F…`, `PoolSwap` `0xb45e89f4…`) predate the table above. Router approval is per calculator, so a gate pointed at a superseded router refuses every smart-wallet buy. New launches use the table above.
{% endhint %}

A second calculator, `SpendGatedSignerFeeCalculator` **v2** (cumulative spend ceilings) is registered on all four mainnets at `0x91938A66323725252043c03ad3066542Ac793057` (Ethereum since 2026-09-21). Game Mode SDK 0.7.0 gates sign against it; a gate switches to it between rounds, after its last v1 round's books close.

## Limitations worth knowing before you build

* **Spend is measured in the pool's paired token.** On the current stack that is ETH or any token the chain's `PairedTokenRegistry` approves, and every signed amount is in that token's base units — `maxSpendWei` keeps its name for signature compatibility but is not always wei. Only the retired first-generation Robinhood calculator assumed an ETH-paired pool and refused anything else with `InvalidPoolKey`.
* **Exact-output swaps are refused.** They cannot be measured safely — see [the enforcement page](/references/spend-gate/hook-path) for why a zero-measured buy would otherwise be repeatable.
* **One gate, one signer, one pool.** There is no notion of multiple concurrent signers per pool; the per-pool signer overrides the protocol-wide trusted set entirely.


# The Trusted Signer

The signer is the off-chain half of a spend-gated launch. It decides how much ETH a wallet may spend against a pool, and says so in an EIP-712 signature the [calculator](/references/spend-gate/hook-path) verifies on every swap.

Nothing about the signer is Flaunch-specific. It is a key, a rule for deciding allowance, and an endpoint that hands out signatures. In Game Mode the rule is "how well did you shoot"; it could as easily be "did you answer the question", "were you on the allowlist", or "did you win the raffle".

## The authorization

```solidity
bytes32 constant SPEND_AUTHORIZATION_TYPEHASH = keccak256(
    'SpendAuthorization(address buyer,bytes32 poolId,uint256 deadline,uint256 maxSpendWei,uint256 nonce)'
);
```

<table><thead><tr><th width="170">Field</th><th>Meaning</th></tr></thead><tbody><tr><td><code>buyer</code></td><td>The wallet this authorization belongs to. Binding it is what stops a front-runner copying the message out of public calldata.</td></tr><tr><td><code>poolId</code></td><td>The pool it is valid against. A signature for one pool is worthless on another.</td></tr><tr><td><code>deadline</code></td><td>Expiry timestamp. Keep it short — it is the window in which a leaked signature is useful.</td></tr><tr><td><code>maxSpendWei</code></td><td>The maximum native input the swap may consume. Measured against the swap's real ETH input.</td></tr><tr><td><code>nonce</code></td><td>Distinguishes two otherwise-identical authorizations, so a retried buy is not mistaken for a replay of the first.</td></tr></tbody></table>

The EIP-712 domain is:

```typescript
const domain = {
  name: 'FlaunchSpendGate',
  version: '1',
  chainId,             // the chain the pool is on
  verifyingContract,   // the SpendGatedSignerFeeCalculator
};
```

{% hint style="danger" %}
**Do not reimplement the digest.** Derive it from the contract:

```solidity
function hashSpendAuthorization(
    address _buyer, bytes32 _poolId, uint _deadline, uint _maxSpendWei, uint _nonce
) public view returns (bytes32 digest_);
```

That function is public for exactly this reason. A domain mismatch is otherwise a silent `InvalidSigner` at swap time — a failure that surfaces in a user's wallet, minutes and one gas payment away from the signing bug that caused it.
{% endhint %}

### Why the domain matters

Earlier revisions signed an EIP-191 personal-sign over `keccak256(abi.encodePacked(...))`. That preimage committed to the five fields and nothing else — no chain id, no verifying contract.

Flaunch deploys deterministically across chains, so the same `poolId` genuinely recurs on more than one of them. One signing key shared between two environments therefore made an authorization issued for one valid on the other. The EIP-712 domain closes it by construction.

## Signing

```typescript
import { privateKeyToAccount } from 'viem/accounts';

const SPEND_AUTHORIZATION_TYPES = {
  SpendAuthorization: [
    { name: 'buyer', type: 'address' },
    { name: 'poolId', type: 'bytes32' },
    { name: 'deadline', type: 'uint256' },
    { name: 'maxSpendWei', type: 'uint256' },
    { name: 'nonce', type: 'uint256' },
  ],
} as const;

const account = privateKeyToAccount(SIGNER_PRIVATE_KEY);

const signature = await account.signTypedData({
  domain,
  types: SPEND_AUTHORIZATION_TYPES,
  primaryType: 'SpendAuthorization',
  message: { buyer, poolId, deadline, maxSpendWei, nonce },
});
```

### Nonces

The chain only needs each nonce to be **unique** — it feeds the digest so two otherwise-identical claims stay distinct. Replay protection is the contract's consumed-signature ledger, not the nonce, and ordering carries no meaning.

A time-major layout keeps nonces unique across process restarts with no persistence at all:

```typescript
let seq = 0n;
function nextNonce(): bigint {
  seq = (seq + 1n) & 0xfffffn;
  return (BigInt(Date.now()) << 20n) | seq;
}
```

## Encoding the swap

The authorization travels as Uniswap V4 `hookData`, behind the referrer field Flaunch already puts there:

```solidity
abi.encode(
    address referrer,
    SignedMessage {
        address buyer;
        bytes32 poolId;
        uint256 deadline;
        uint256 maxSpendWei;
        uint256 nonce;
        bytes   signature;
    }
)
```

```typescript
const hookData = encodeAbiParameters(
  [
    { type: 'address' },
    {
      type: 'tuple',
      components: [
        { name: 'buyer', type: 'address' },
        { name: 'poolId', type: 'bytes32' },
        { name: 'deadline', type: 'uint256' },
        { name: 'maxSpendWei', type: 'uint256' },
        { name: 'nonce', type: 'uint256' },
        { name: 'signature', type: 'bytes' },
      ],
    },
  ],
  [referrer, { buyer, poolId, deadline, maxSpendWei, nonce, signature }],
);
```

## Installing the signer

Two routes, and they differ in how many transactions they cost:

1. **At launch**, by naming `signer` in the tagged gate params. The gate is live the moment the pool exists. This is the single-transaction path and the one Game Mode uses.
2. **Afterwards**, via `setTrustedPoolKeySigner(poolKey, signer)` — callable only by the pool's **settler** or the contract owner. Until it lands, nobody can produce a signature the pool accepts.

There is also a protocol-wide trusted signer set (`addTrustedSigner`), administered by the contract owner, used by pools that do not nominate their own. A per-pool signer overrides it entirely.

Zeroing the per-pool signer is the gate's off-switch: enforcement stops and the pool trades openly. That is how a round settles early.

## Running one in production

**Clamp what you issue to what the chain will accept.** Read `walletSpentWei[poolId][buyer]` and cap each authorization at `walletCapWei − walletSpentWei`. Otherwise you will hand out allowance the gate refuses with `WalletCapExceeded` — users earning spend they cannot use, which reads to them as a broken product rather than a cap working as designed.

**Keep deadlines short.** The signature is public calldata the moment it is submitted. The buyer binding means a copy is useless to anyone else, but a short deadline bounds the damage if your own key or your own issuance logic misbehaves.

**Persist issuance.** If your server forgets which authorizations it has already handed out, a restart re-offers the same allowance — and now two live signatures exist against one balance. The contract's replay ledger stops the *same* signature being used twice; it does nothing about two distinct signatures you never meant to issue.

**One key, one chain.** The domain binds `chainId` and `verifyingContract`, so a key used on two deployments is safe in a way it was not before. Sharing state between them is still not: pool ids, addresses and spend records mean nothing outside their own chain.

**Reconcile.** The calculator emits `SpendRecorded(poolId, buyer, ethSpent)` on every enforced swap, including sells, where the amount is zero. Comparing that stream against what you issued is the only way to notice a divergence between your ledger and the chain's.


# Enforcement in the V4 Hook

Flaunch's `PositionManager` is a Uniswap V4 hook. On every swap it calls the protocol's fee calculator, which — on a spend-gated pool — is `SpendGatedSignerFeeCalculator`, reached through the [dispatcher](/references/spend-gate).

Two entry points matter:

* `determineSwapFee` runs in `beforeSwap` and, for this calculator, does nothing. The gate never alters the fee; it returns the base fee unchanged.
* `trackSwap` runs in `afterSwap` and is where all enforcement happens.

Enforcement lives in `afterSwap` because that is the only place the swap's **real** native input is knowable. A gate that checked an intended amount beforehand would be checking a promise.

## What `trackSwap` checks, in order

```solidity
function trackSwap(
    address _sender,          // who called PoolManager.swap, forwarded by the hook
    PoolKey calldata _poolKey,
    SwapParams calldata _params,
    BalanceDelta _delta,      // what the swap actually moved
    bytes calldata _hookData  // carries the signed authorization
) public nonReentrant;
```

1. **Caller holds `POSITION_MANAGER`.** In a dispatcher deployment that role belongs to the dispatcher. Anyone else reverts `CallerNotPositionManager`.
2. **Gate enabled?** If not, return immediately — nothing to enforce.
3. **Past `endsAt`?** Return. The gate has expired on its own and the pool is now ordinary.
4. **Per-pool signer zeroed?** Return. This is the settler's early off-switch.
5. **Decode and pre-check the authorization** — `deadline` not passed, `poolId` matches.
6. **Bind the buyer to the submitter.**
7. **Reject a consumed signature.**
8. **Recover the signer** and check it against the per-pool signer, or the protocol-wide trusted set.
9. **Refuse exact output.**
10. **Measure native spend** and enforce `maxSpendWei`.
11. **Accumulate against the wallet cap**, emit `SpendRecorded`, burn the signature.

Steps 2–4 are the three ways a gated pool stops being gated, and none of them need a transaction from the game server.

## Buyer binding

The signed message is public calldata. Without a binding, a front-runner could copy a victim's authorization out of the mempool, receive the tokens, consume the victim's allowance, and burn the signature.

```solidity
if (signedMessage.buyer != tx.origin) {
    if (!approvedRouters[_sender]) revert BuyerNotSubmitter(...);
    try IMsgSender(_sender).msgSender() returns (address reported) {
        if (reported != signedMessage.buyer) revert BuyerNotSubmitter(...);
    } catch { revert BuyerNotSubmitter(...); }
}
```

An EOA submitting its own transaction satisfies the binding through `tx.origin`. That alone would exclude smart-contract wallets and account abstraction entirely — under a 7702 relay or a 4337 bundler, `tx.origin` is the relayer, not the user.

So the binding is also satisfied by the `msgSender()` an **approved router** reports. Approval matters: any other contract could simply lie about its original caller. A front-runner replaying the message through an approved router is still refused, because the router honestly reports the front-runner.

{% hint style="info" %}
Approving a router is a statement that it truthfully reports the account that initiated the swap. On Robinhood chain the approved set is the canonical Universal Router and Flaunch's own `msgSender`-aware `PoolSwap`. The chain's older swap helper predates `msgSender()` and is deliberately **not** approved — a swap through it cannot be attributed to its sender, which is the property the whole gate hangs on.
{% endhint %}

## Measuring spend

```solidity
int128 nativeDelta = nativeIsZero ? _delta.amount0() : _delta.amount1();
if (nativeDelta < 0) ethSpent_ = uint(uint128(-nativeDelta));

// exact-input native swaps: also consider the specified amount, enforce the larger
if (nativeIsInput && _params.amountSpecified < 0) {
    uint specified = uint(-_params.amountSpecified);
    if (specified > ethSpent_) ethSpent_ = specified;
}
```

The primary measure is the swap's `BalanceDelta` — a negative native-side amount is what the swapper paid. The specified input is a backstop, and the **larger** of the two is enforced, so hook-side fills that adjust the visible delta can only ever make enforcement stricter.

### Why exact output is refused

The delta `afterSwap` receives is already net of any `beforeSwapDelta`, and Flaunch's `InternalSwapPool` fills buys out of accrued memecoin inventory through exactly that mechanism. Native taken for such a fill never appears in the delta, and the `amountSpecified` backstop only covers exact input.

An exact-output buy that inventory could cover outright would therefore measure as **zero spend**. Zero passes any `maxSpendWei` and never reaches `walletSpentWei`, so neither cap could see it — and the buy would be repeatable with every fresh authorization.

Refusing exact output is the safe direction. The gate exists to bound native input, and every buy path a gated round actually uses is exact-input native.

## The revert matrix

<table><thead><tr><th width="270">Revert</th><th>Cause</th></tr></thead><tbody><tr><td><code>TokenNotFlaunched</code></td><td>A buy before the window opens. Raised by the <code>PositionManager</code> from the launch's <code>flaunchAt</code>, so it binds the game server exactly as hard as it binds a player.</td></tr><tr><td><code>CallerNotPositionManager</code></td><td>Something other than the PositionManager (or the dispatcher acting for it) tried to report a swap.</td></tr><tr><td><code>DeadlineExpired</code></td><td>The authorization is past its <code>deadline</code>.</td></tr><tr><td><code>InvalidPoolKey</code></td><td>The authorization was signed for a different pool. On the retired first-generation Robinhood calculator, also what a non-ETH-paired pool hit; the current stack measures spend in the pool's paired token.</td></tr><tr><td><code>BuyerNotSubmitter</code></td><td>Someone other than the signed buyer submitted it, via an unapproved router or a mismatched <code>msgSender()</code>.</td></tr><tr><td><code>SignatureAlreadyUsed</code></td><td>The digest has been consumed.</td></tr><tr><td><code>InvalidSigner</code></td><td>Recovered signer is not the pool's signer, nor in the trusted set. Very often a domain mismatch rather than a wrong key — see <a href="/references/spend-gate/signer">the signer page</a>.</td></tr><tr><td><code>ExactOutputNotSupported</code></td><td><code>amountSpecified > 0</code>. Unmeasurable, so refused.</td></tr><tr><td><code>SpendCapExceeded</code></td><td>The swap's real native input exceeded the signed <code>maxSpendWei</code>.</td></tr><tr><td><code>WalletCapExceeded</code></td><td>Cumulative spend for this wallet on this pool passed <code>walletCapWei</code>.</td></tr><tr><td><code>UnrecognisedGateParams</code></td><td>Launch params were neither the tagged 192-byte form nor the 64-byte short form.</td></tr><tr><td><code>SettlerRequired</code></td><td>An enforcing gate named a signer but no settler — nobody could ever lift it.</td></tr><tr><td><code>GateExpiryRequired</code> / <code>GateExpiryTooDistant</code></td><td>An enforcing gate had no <code>endsAt</code>, or one beyond <code>MAX_GATE_DURATION</code>.</td></tr><tr><td><code>GateAlreadyConfigured</code></td><td>A second attempt to write gate params for a pool.</td></tr></tbody></table>

## Recording spend

```solidity
uint walletSpent = walletSpentWei[poolId][signedMessage.buyer] + ethSpent;
if (settings.walletCapWei != 0 && walletSpent > settings.walletCapWei) {
    revert WalletCapExceeded(walletSpent, settings.walletCapWei);
}

walletSpentWei[poolId][signedMessage.buyer] = walletSpent;
emit SpendRecorded(poolId, signedMessage.buyer, ethSpent);
_usedSignatures[messageHash] = true;
```

The write and the event are unconditional, **including when the amount is zero**. A zero is a sell — the swapper receives native — which legitimately consumes an authorization without spending anything. Emitting it anyway keeps the on-chain record complete for off-chain reconciliation; guarding on a non-zero amount meant a consumed signature could leave no trace at all.

## Two endings

A gated pool becomes an ordinary pool in one of two ways, and the difference matters:

* **The settler zeroes the signer.** Immediate, and requires a transaction from a live key. This is how a round opens trading early.
* **`endsAt` passes.** Automatic, on chain, requiring nothing from anyone. This is the guarantee that survives the game server vanishing mid-round.

Design for the second and treat the first as an optimisation. A gate whose only exit needs the gatekeeper to come back is not a gate.


# Zaps

We provide zap contracts that combine logic and functionality into a single transaction. This section will provide detail on each zap contract.


# Old Contract Addresses


# 12 December: Solana Imports, Custom Token Supply, and Smarter Liquidity SDK Upgrades

## What’s New

* **Cross-Chain Import: Solana Support**\
  Added Solana verifier integration for token imports. You can now verify Solana-based tokens via `Verifier.SOLANA` with support on Base mainnet and Sepolia.
* **Token ID Lookup for Memecoins**\
  Use `getFlaunchTokenIdForMemecoin()` to fetch the Flaunch NFT token ID and contract for any memecoin address.
* **Custom Token Supply for Imports**\
  All import and liquidity methods now support a `tokenSupply` param. Useful for tokens with non-standard decimals or fixed supply configs. Passed through to `getInitializeParams()` and used in tick and liquidity math.
* **Pool Event Parsing**\
  `getPoolCreatedFromTx()` extracts memecoin address, token ID, and config from a transaction hash by decoding the `PoolCreated` event.
* **Optional Slippage Control**\
  Added `slippagePercent` (default: 0.05%) across all liquidity types and methods. Customize the slippage buffer used during liquidity operations for finer execution control.

## Fixes & Improvements

* **ClankerWorld Support**:\
  Updated `ClankerWorldVerifierAddress` to support multiple token deployments.
* **Token Importer Contract Upgrade**:\
  New `TokenImporterAddress` deployed on Base mainnet with updated ABI and support for custom `_totalSupply` via a 5-parameter `initialize()` overload.


# 11 December: Flaunch Wrap Solana → Base Bridging for Token Creators

## What’s New

* **Solana to Base Token Bridge is Live**\
  Creators can now bridge their Solana coins to Base via [bridge.flaunch.gg](https://bridge.flaunch.gg/).
* **Zero Platform Fees on Bridged Tokens**\
  Bridged tokens retain **100% of creator fee earnings**.
* **Add Liquidity Instantly on Base**\
  Once bridged, creators can initialize liquidity directly on [flaunch.gg/add-liquidity](https://flaunch.gg/add-liquidity) adding single-sided or double-sided liquidity .

## **Why it matters**

Creators who launch on Solana can now seamlessly extend to Base and earn all the trading fees from their coin. This opens a cross-chain path to capture Base-native orderflow while keeping full control of your fees and liquidity setup.


# 17 November: Launch of Groups

## What’s New

* **Launch a Group**: Creators and communities can now launch their own *Groups*, forming coin economies around cultural memes, creator tokens, or even third-party assets.
* **Group Coin**: Each Group is centered around a **Group Coin**—a base token used to denominate and capture value from all trading and derivatives activity inside that Group.
* **Earn on Trading**: Group owners can enable a **10% creator revenue fee**—paid out automatically from trading activity within the Group.
* **Modular Permissions**: Set Group permissions to **open** (anyone can add coins) or **closed** (only the owner can), with full modularity for future permission models.
* **Group as Cultural Registry**: Groups serve as repositories of cultural and derivative assets tied to the Group Coin IP. Think memecoins, forks, extensions—fees from their trades go to the Group economy.
* **Withdrawals and Ownership**: Group owners can withdraw assets directly. Future support for **sub-Groups** allows fractional asset control without parent Group ownership transfer.

## Why it matters

* Groups shift coins from single tokens to structured economies. By aligning creator and community incentives around a Group Coin, cultural memes and onchain assets can compound value over time.
* Whether you’re launching your own token or building around another, Groups give you the rails to coordinate, monetize, and grow your coin’s ecosystem.

#### Links

* Launching a Group : <https://docs.flaunch.gg/for-creators/getting-started/launch-a-group>


# 23 August: Phase 2 — Groups & $1M Creator Revenue

## What’s New

* **Creators passed $1,000,000 in revenue** (paid in ETH; protocol take = 0).
* **Phase 2: Groups (announced):** Shared upside across multiple tokens (buybacks, rewards, airdrops to holders), not just single-asset flows.

## Why it matters

* Social coins → **economies**. Groups let value flow across everything a community creates.


# 13 March: Web2 API, New Homepage, Just Flaunch Launchpad

## Web2 Api

Users can now launch meme coins without needing a wallet or signing a transaction. The Web2 API leverages the Flaunch SDK to launch tokens with specific predefined rules including:

* 10k Market Cap
* 80% Creator Fees
* 20% Buy backs/Price protection

The API enables users to upload images to IPFS and provide coin and creator details before launching. Users can specify either a standard wallet address as the creator or use a Twitter, Farcaster, or email address—which automatically creates an associated wallet address through our Privy integration.

API limits are set on the endpoint (4 images per minute, 2 launches per minute). API keys are available for increased allowances upon request.

Want to know more, [check out the docs](https://docs.flaunch.gg/references/api).

## Homepage timeline updates

<figure><img src="https://1229184497-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoleIQgpsdD3uHYHcTay2%2Fuploads%2Fgit-blob-0d29dc0e7ef4ed0a442ac371e2b60b8c67bd122d%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

We've overhauled the homepage timeline to better showcase platform activity.

The sidebar now features customized sections displaying coins that are pumping in the last 24 hours and all current Fair launch coins, both with instant buy options.

The main feed highlights newly created coins and significant purchases.

## Just Flaunch Launched - a web 2 transactionless token creation

<figure><img src="https://1229184497-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoleIQgpsdD3uHYHcTay2%2Fuploads%2Fgit-blob-64520bc91aebfbf6992ae97c8b96a408ca85f333%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

To celebrate and showcase the Web 2 API, we've created a [just.flaunch.gg](http://just.flaunch.gg) landing page where users can launch tokens without needing a wallet.

This demonstrates the power of the Flaunch protocol and its integrations for Web2 users who have no existing wallets or crypto experience but can still participate.


