> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mobula.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Bonding Curves Mathematics

> Deep dive into bonding curve mechanics for Pumpfun, Meteora DBC, and other launchpads

# Bonding Curves: The Mathematics of Fair Launches

Bonding curves are smart contract mechanisms that automatically determine token prices based on supply and demand. They enable **fair launches** where everyone trades against the same mathematical formula, eliminating the need for market makers and preventing price manipulation.

<Info>
  **Why it matters**: Understanding bonding curve math helps you predict price movements, identify bonding thresholds, and build trading strategies around launchpad tokens.
</Info>

## What is a Bonding Curve?

A bonding curve is a mathematical function that defines the relationship between a token's price and its supply. As tokens are bought, the price increases along the curve. As tokens are sold, the price decreases.

```
Price = f(Supply)
```

The most common types are:

| Curve Type                    | Formula                      | Characteristics                             |
| ----------------------------- | ---------------------------- | ------------------------------------------- |
| **Constant Product (x\*y=k)** | `price = k / supply`         | Hyperbolic curve, used by Pumpfun           |
| **Exponential**               | `price = base^supply`        | Aggressive price growth                     |
| **Linear**                    | `price = m * supply + b`     | Predictable, steady growth                  |
| **Sqrt Price**                | `price = sqrtPrice² / 2^128` | Concentrated liquidity, used by Meteora DBC |

***

## Pumpfun: Constant Product AMM

Pumpfun uses a **constant product Automated Market Maker (AMM)** with virtual reserves. This is the same formula popularized by Uniswap V2.

### Core Formula

```
x * y = k (constant)
```

Where:

* `x` = Virtual SOL reserves (`reserve0`)
* `y` = Virtual Token reserves (`reserve1`)
* `k` = Constant product (invariant)

### Understanding Virtual vs Real Reserves

<Info>
  **Critical Concept**: Pumpfun uses TWO types of reserves:

  * **Virtual Reserves**: Used for price calculation (includes "phantom" liquidity)
  * **Real Reserves**: Actual tokens/SOL locked in the contract
</Info>

| Reserve Type           | SOL                  | Token                  | Purpose                           |
| ---------------------- | -------------------- | ---------------------- | --------------------------------- |
| **Virtual**            | `virtualSolReserves` | `virtualTokenReserves` | Price calculation via AMM formula |
| **Real**               | `realSolReserves`    | `realTokenReserves`    | Actual assets in contract         |
| **Initial Virtual**    | 30 SOL               | 1,073,000,000,000,000  | Starting point for price curve    |
| **Initial Real Token** | 0 SOL                | 793,100,000,000,000    | Tokens available for sale         |

**Why virtual reserves?** The virtual reserves create artificial depth at launch, preventing the first buyer from getting 100% of tokens for pennies. The 30 SOL virtual reserve means the price starts as if there's already 30 SOL of liquidity.

### Price Calculation

The price (exchange rate) is calculated as:

```typescript theme={null}
// Returns: how many tokens you get per 1 SOL
exchangeRate = virtualTokenReserves / virtualSolReserves
```

In code:

```typescript theme={null}
getPrice(pool: PumpfunPool): number {
  if (pool.reserve0 === 0n || pool.reserve1 === 0n) {
    return 0;
  }
  // reserve0 = virtualSolReserves, reserve1 = virtualTokenReserves
  // Returns tokens per SOL (exchange rate)
  return bigIntDiv(pool.reserve1, pool.reserve0);
}
```

To get the **token price in SOL**:

```typescript theme={null}
tokenPriceInSOL = virtualSolReserves / virtualTokenReserves
// Or simply: 1 / exchangeRate
```

### Initial Parameters

When a Pumpfun token is created, the bonding curve initializes with:

| Parameter                     | Value                                | Description                            |
| ----------------------------- | ------------------------------------ | -------------------------------------- |
| `initialVirtualSolReserves`   | **30 SOL** (30,000,000,000 lamports) | Virtual SOL for price calculation      |
| `initialVirtualTokenReserves` | **1,073,000,000,000,000**            | Virtual tokens (6 decimals = \~1.073B) |
| `initialRealTokenReserves`    | **793,100,000,000,000**              | Actual tokens for sale (\~793.1M)      |
| `bondedCriteria`              | **85.005 SOL**                       | Real SOL to trigger migration          |

<Warning>
  **Note**: The total supply is 1B tokens, but only \~793.1M are available for purchase. The difference (\~280M) is the virtual reserve that creates initial price depth.
</Warning>

### How Buying Works

When you buy tokens:

1. You send SOL to the bonding curve
2. The curve calculates tokens using the constant product formula:

```typescript theme={null}
// Classic AMM swap formula
tokens_out = (sol_in * virtualTokenReserves) / (virtualSolReserves + sol_in)
```

3. Both virtual AND real reserves update:
   * `virtualSolReserves += sol_in`
   * `virtualTokenReserves -= tokens_out`
   * `realSolReserves += sol_in`
   * `realTokenReserves -= tokens_out`

### How Selling Works

When you sell tokens:

```typescript theme={null}
sol_out = (tokens_in * virtualSolReserves) / (virtualTokenReserves + tokens_in)
```

### Bonding Percentage

The bonding progress shows how close the token is to migration:

```typescript theme={null}
// How many tokens have been sold vs total available
bondingPercentage = (initialVirtualTokenReserves - currentVirtualTokenReserves) * 100 
                    / initialRealTokenReserves
```

When tokens are bought, `virtualTokenReserves` decreases. The bonding percentage tracks what % of the `initialRealTokenReserves` has been purchased.

### Bonding (Migration) Threshold

When `virtualSolReserves >= ~85 SOL`, the token "bonds" and migrates to Raydium:

```typescript theme={null}
bondedCriteria = 86000000000n; // ~86 SOL in lamports

async isBonded(pool: PumpfunPool): Promise<boolean> {
  if (pool.bonded) return true;
  if (pool.reserve0 >= this.bondedCriteria) return true;
  return false;
}
```

Since virtual SOL starts at 30 SOL, approximately **55-56 SOL** of real purchases triggers migration.

### Price Impact Formula

For a given SOL input, the price impact is:

```
priceImpact = sol_in / (virtualSolReserves + sol_in)
```

<Warning>
  **Example**: If virtual SOL reserves = 30 SOL and you buy with 3 SOL, your price impact is \~9.1%. Early buys have massive impact because of the relatively low virtual reserve.
</Warning>

### Numerical Example

At launch:

* Virtual SOL: 30,000,000,000 lamports (30 SOL)
* Virtual Tokens: 1,073,000,000,000,000 (1.073B with 6 decimals)
* Exchange rate: 1,073B / 30 = **35,766,666,666 tokens per SOL**
* Token price: 30 / 1,073B = **0.000000028 SOL per token**

After 10 SOL buy:

* Tokens received: (10 × 1,073B) / (30 + 10) = **268,250,000,000 tokens** (\~268M)
* New Virtual SOL: 40 SOL
* New Virtual Tokens: 804,750,000,000,000 (804.75B)
* New exchange rate: 804.75B / 40 = **20,118,750,000 tokens per SOL**
* Price increased by \~44%

***

## Meteora DBC: Dynamic Bonding Curve

Meteora's Dynamic Bonding Curve (DBC) uses a **sqrt price model** with concentrated liquidity, similar to Uniswap V3 but optimized for launchpads.

### Core Concept: Sqrt Price

Instead of storing price directly, Meteora DBC stores the **square root of price** as a Q64.64 fixed-point number:

```typescript theme={null}
sqrtPrice = sqrt(price) * 2^64
```

To get the actual price:

```typescript theme={null}
getPrice(pool: MeteoraDBCPool): number {
  const sqrtPrice = pool.extra?.sqrtPriceX64 ?? 0n;
  if (sqrtPrice === 0n) return 0;
  
  // Convert from Q64.64 fixed point
  return getPriceFromSqrtX(sqrtPrice, 64);
}

// Where getPriceFromSqrtX does:
function getPriceFromSqrtX(sqrtPrice: bigint, resolution: number): number {
  const price = (sqrtPrice * sqrtPrice) / (1n << BigInt(resolution * 2));
  return Number(price) / (2 ** resolution);
}
```

### The Curve Structure

Meteora DBC defines a **curve** as an array of price/liquidity points:

```typescript theme={null}
type Curve = Array<{
  sqrtPrice: bigint;   // Price at this point
  liquidity: bigint;   // Liquidity available
}>;
```

This creates a **piecewise linear** bonding curve where:

* Each segment has different liquidity concentration
* Price moves faster in segments with lower liquidity
* Price moves slower in segments with higher liquidity

### Quote Reserve Calculation

The virtual quote (SOL) reserve is calculated by integrating along the curve:

```typescript theme={null}
calculateQuoteVirtualReserve(pool: MeteoraDBCPool): bigint {
  const curve = pool.extra.curve;
  const nextSqrtPrice = pool.extra.sqrtPriceX64;
  const sqrtStartPrice = pool.extra.sqrtPriceStart;
  
  let totalAmount = 0n;
  
  for (let i = 0; i < curve.length; i++) {
    const currentPoint = curve[i];
    const lowerSqrtPrice = i === 0 
      ? sqrtStartPrice 
      : curve[i - 1].sqrtPrice;
    
    if (nextSqrtPrice > lowerSqrtPrice) {
      const upperSqrtPrice = nextSqrtPrice < currentPoint.sqrtPrice 
        ? nextSqrtPrice 
        : currentPoint.sqrtPrice;
      
      // Calculate delta amount for this segment
      const maxAmountIn = getDeltaAmountQuoteUnsigned(
        lowerSqrtPrice,
        upperSqrtPrice,
        currentPoint.liquidity
      );
      
      totalAmount += maxAmountIn;
    }
  }
  
  return totalAmount;
}
```

### Delta Amount Formula

For each curve segment:

```typescript theme={null}
getDeltaAmountQuoteUnsigned(
  lowerSqrtPrice: bigint,
  upperSqrtPrice: bigint,
  liquidity: bigint
): bigint {
  // Δquote = L * (√P_upper - √P_lower) / 2^128
  const deltaSqrtPrice = upperSqrtPrice - lowerSqrtPrice;
  const prod = liquidity * deltaSqrtPrice;
  return prod >> BigInt(RESOLUTION * 2); // RESOLUTION = 64
}
```

### Bonding Percentage

Meteora DBC calculates bonding progress as:

```typescript theme={null}
bondingPercentage = (quoteReserve / migrationQuoteThreshold) * 100
```

When `bondingPercentage >= 100%`, the token migrates to Meteora DAMM.

### Migration Thresholds

| Parameter                 | Description                                                     |
| ------------------------- | --------------------------------------------------------------- |
| `migrationQuoteThreshold` | SOL amount needed to trigger migration                          |
| `sqrtPriceStart`          | Initial sqrt price                                              |
| `curve`                   | Array of (sqrtPrice, liquidity) points defining the curve shape |

***

## Comparison: Pumpfun vs Meteora DBC

| Aspect                     | Pumpfun                   | Meteora DBC                               |
| -------------------------- | ------------------------- | ----------------------------------------- |
| **Curve Type**             | Constant Product (x\*y=k) | Sqrt Price with Concentrated Liquidity    |
| **Price Formula**          | `SOL / Token`             | `sqrtPrice² / 2^128`                      |
| **Liquidity Distribution** | Uniform across all prices | Concentrated in curve segments            |
| **Price Impact**           | Higher for same volume    | Variable based on liquidity concentration |
| **Bonding Trigger**        | 86 SOL raised             | Custom `migrationQuoteThreshold`          |
| **Migration Target**       | Raydium                   | Meteora DAMM                              |
| **Complexity**             | Simple                    | More complex, more flexible               |

***

## Practical Applications

### 1. Predicting Bonding Time

For Pumpfun:

```typescript theme={null}
// Bonding happens when virtualSolReserves reaches ~86 SOL
// Since it starts at 30 SOL, you need ~56 SOL of real purchases
const INITIAL_VIRTUAL_SOL = 30_000_000_000n; // 30 SOL
const BONDED_CRITERIA = 86_000_000_000n;     // 86 SOL

// Current progress (using virtual reserves)
const currentVirtualSol = pool.reserve0;
const progress = Number(currentVirtualSol - INITIAL_VIRTUAL_SOL) * 100 
                 / Number(BONDED_CRITERIA - INITIAL_VIRTUAL_SOL);

// Real SOL needed to bond
const solNeeded = BONDED_CRITERIA - currentVirtualSol;
```

For Meteora DBC:

```typescript theme={null}
// Current progress
const quoteReserve = calculateQuoteVirtualReserve(pool);
const progress = (quoteReserve * 100n) / migrationQuoteThreshold;

// SOL needed to bond
const solNeeded = migrationQuoteThreshold - quoteReserve;
```

### 2. Price Impact Estimation

For a buy of `X` SOL on Pumpfun:

```typescript theme={null}
// Current exchange rate (tokens per SOL)
const currentRate = virtualTokenReserves / virtualSolReserves;

// After your buy
const newSolReserves = virtualSolReserves + X;
const tokensReceived = (X * virtualTokenReserves) / newSolReserves;

// Your effective rate (tokens per SOL)
const effectiveRate = tokensReceived / X;

// Price impact (how much worse your rate is vs spot)
const priceImpact = (currentRate - effectiveRate) / currentRate;
// Or equivalently: X / (virtualSolReserves + X)
```

### 3. Slippage Calculation

```typescript theme={null}
// Expected tokens at current spot rate (no slippage)
const expectedTokens = (solIn * virtualTokenReserves) / virtualSolReserves;

// Actual tokens (accounting for price impact)
const actualTokens = (solIn * virtualTokenReserves) / (virtualSolReserves + solIn);

// Slippage percentage
const slippage = (expectedTokens - actualTokens) / expectedTokens * 100;
// This equals: solIn / (virtualSolReserves + solIn) * 100
```

### 4. Calculating Token Price in USD

```typescript theme={null}
// Get SOL price from oracle
const solPriceUSD = 150; // example: $150 per SOL

// Token price in SOL
const tokenPriceInSOL = virtualSolReserves / virtualTokenReserves;

// Token price in USD
const tokenPriceUSD = tokenPriceInSOL * solPriceUSD;
```

***

## API Access

Query bonding curve data through Mobula's API:

```bash theme={null}
# Get token details for a Pumpfun token (Fartcoin)
curl -X GET "https://demo-api.mobula.io/api/2/token/details?blockchain=solana&address=9BB6NFEcjBCtnNLFko2FqVQBq8HHM13kCyYcdQbgpump" \
  -H "Authorization: YOUR_API_KEY"

# Get token details for Wojak
curl -X GET "https://demo-api.mobula.io/api/2/token/details?blockchain=solana&address=8J69rbLTzWWgUJziFY8jeu5tDwEPBwUz4pKBMr5rpump" \
  -H "Authorization: YOUR_API_KEY"
```

The response includes:

* `bonded` - Whether the token has migrated to Raydium/Meteora
* `bondingPercentage` - Progress toward migration (0-100)
* `bondingCurveAddress` - Address of the bonding curve contract
* `preBondingFactory` - Original launchpad (e.g., Pumpfun, Meteora DBC)
* `liquidityUSD` - Current liquidity in the curve

<Info>
  For real-time bonding curve updates, use the [WSS Market Details](/indexing-stream/stream/websocket/wss-market-details) WebSocket stream.
</Info>
