FwogSwap: Integration Guide

Download the IDL file below:

file-download
175KB

Overview

FwogSwap is a Constant Product Market Maker (CPMM) DEX on Solana with support for one-sided liquidity provisioning. It uses a concentrated liquidity model with configurable price ranges (sqrtMinPrice / sqrtMaxPrice), allowing pool creators to define the exact price boundaries for their liquidity.

Program ID: fwogV3pR5UgBUWTbg8UKYCQZUbuNKCSKC8CyBtxxU7J

Protocol fees are set to 0%.

Key Features

  • Concentrated Liquidity CPMM with customizable price range (sqrtMinPrice to sqrtMaxPrice)

  • One-Sided Liquidity: create pools where all initial liquidity is in a single token (e.g., launch a token without needing to pair it with SOL/USDC upfront)

  • SPL Token & Token-2022 support (including transfer fees, transfer hooks)

  • NFT-based positions: each liquidity position is represented by a Token-2022 NFT

  • Farming rewards: up to 2 reward tokens per pool

  • Position locking & vesting: lock positions with customizable vesting schedules

  • Dynamic fees: optional volatility-based fee adjustments

  • Fee schedulers: time-based or market-cap-based fee curves for token launches


Architecture

Core Accounts

Account
Description

Pool

Stores all pool state: reserves, price, fees, liquidity, reward info

Config

Predefined pool configuration (fees, price range, activation type). Used by initializePool

Position

Tracks a user's liquidity, pending fees, and pending rewards. Linked to an NFT mint

ProtocolConfig

Singleton storing protocol-wide fee percentages

Price Model

Prices are stored as sqrt prices in Q64.64 fixed-point format (u128):

Constants:

  • MIN_SQRT_PRICE = 4295048016

  • MAX_SQRT_PRICE = 79226673521066979257578248091

Fee Model

Fees use a numerator/denominator system:

  • Fee denominator: 1,000,000,000 (1e9)

  • Fee numerator range: 100,000 (0.01%) to 990,000,000 (99%)

  • Trade fees go to LPs. Protocol and partner fees are configurable percentages split from the trade fee.


Integration via IDL / ABI

The program is built with Anchor. You can integrate using the generated IDL at target/idl/cp_amm.json.

Setup

PDA Derivations

All accounts are derived deterministically using PDAs:


Creating a Customizable Pool (Two-Sided)

The initializeCustomizablePool instruction creates a pool where the creator specifies all parameters: price range, initial price, fees, and initial liquidity. This pool is unique per token pair (only one customizable pool per pair).

Sqrt Price Calculation

To compute the sqrtPrice from a human-readable price:

Encoding Base Fee Parameters

The base fee is encoded as a 30-byte data array. For a simple static fee, use the BorshFeeTimeScheduler codec:

Full Example: Two-Sided Pool


Creating a One-Sided Pool

One-sided liquidity is achieved by setting the initial price at one of the price boundaries. This makes the pool hold 100% of a single token at creation:

  • sqrtPrice = sqrtMinPrice: the pool contains only token A (selling token A as price goes up)

  • sqrtPrice = sqrtMaxPrice: the pool contains only token B

This is ideal for token launches where you want to seed the pool with your new token only, without needing to provide a quote token (SOL, USDC, etc.).

Example: One-Sided Pool (Token A Only)

Note: Even in a one-sided pool, the payer still needs to have at least 1 lamport worth of the other token to prove ownership of the mint. The program enforces total_amount = max(computed_amount, 1) for both tokens.


Swapping

The swap instruction routes through the pool. The input/output direction is determined by matching the inputTokenAccount mint against tokenAMint / tokenBMint.

Swap Modes

Mode
Value
Description

ExactIn

0

Swap exact input amount, receive at least amount1

PartialFill

1

Swap up to amount0 input, allowing partial fills at pool boundaries

ExactOut

2

Receive exactly amount0 output, spend at most amount1 input


Adding / Removing Liquidity

Add Liquidity

Remove Liquidity


Reading Pool State


Constants Reference

Constant
Value
Description

MIN_SQRT_PRICE

4295048016

Minimum allowed sqrt price

MAX_SQRT_PRICE

79226673521066979257578248091

Maximum allowed sqrt price

FEE_DENOMINATOR

1,000,000,000

Fee denominator (1e9)

MIN_FEE_NUMERATOR

100,000

Min fee (0.01%)

MAX_FEE_NUMERATOR

990,000,000

Max fee (99%)

PROTOCOL_FEE_PERCENT

0

Protocol fee percentage

Common Fee Numerator Values

Fee (bps)
Fee (%)
Numerator

1

0.01%

100,000

25

0.25%

2,500,000

30

0.30%

3,000,000

100

1.00%

10,000,000

500

5.00%

50,000,000


Pool Initialization Methods

Method
Description
Pool PDA

initializePool

Create pool from a pre-existing Config account (static config)

["pool", config, maxMint, minMint]

initializeCustomizablePool

Create pool with fully custom parameters, unique per token pair

["cpool", maxMint, minMint]

initializePoolWithDynamicConfig

Create pool from a dynamic Config with custom fee/price params

["pool", config, maxMint, minMint]


Important Notes

  • Compute budget: Pool initialization requires ~350,000 compute units. Always include ComputeBudgetProgram.setComputeUnitLimit({ units: 350_000 }).

  • Token ordering: When deriving PDAs, the larger pubkey comes first, smaller second. This ensures deterministic addresses regardless of input order.

  • Position NFTs: Positions are Token-2022 NFTs. The positionNftMint keypair must be a signer during pool initialization and position creation.

  • Activation: Pools can have delayed activation (slot-based or timestamp-based). Set activationPoint: null for immediate activation.

  • One customizable pool per pair: The initializeCustomizablePool instruction allows only one pool per token pair since the PDA doesn't include a config key.

Last updated