The Dynamic Bonding Curve is a customizable bonding curve that allows you to configure up to 16 curve segments to control the curve’s shape and price action. Each curve segment follows a constant product formula:

x×y=kx \times y = k

Mathematical Foundation

A simple constant product formula can be expressed as:

x×y=Virtual Base Reserve×Virtual Curve Reservex \times y = \text{Virtual Base Reserve} \times \text{Virtual Curve Reserve}

This can also be represented as:

x×y=Liquidity2x \times y = \text{Liquidity}^2

Where:

Liquidity=Virtual Base Reserve×Virtual Curve Reserve\text{Liquidity} = \sqrt{\,\text{Virtual Base Reserve} \times \text{Virtual Curve Reserve}\,}

With a constraint on migration_quote_threshold, this can be presented as a function of liquidity, minimum price, and maximum price. We denote:

  • l = liquidity
  • pa = minimum price
  • pb = maximum price

Therefore:

Bonding Curve Constant Product=f(l,pa,pb)\text{Bonding Curve Constant Product} = f(l, p_a, p_b)

Example Configuration

Consider a pool with the following configuration:

sqrt_start_price = 1
curve = [
  (sqrt_price = 2, liquidity = 100),
  (sqrt_price = 4, liquidity = 500)
]

The bonding curve will function across 2 price ranges:

  • Range 1: (l = 100, pa = 1, pb = 2)
  • Range 2: (l = 500, pa = 2, pb = 4)
These are just example values and are not real values in the actual curve. You will have to calculate the actual sqrt_price and liquidity values which will be much bigger.

Core Formulas

Below are the core formulas used in the dynamic bonding curve program. We use the following notation:

  • Let LiL_i = liquidity in ii index
  • Let PiP_i = price at ii index
  • Pi1P_{i-1} = price at the lower boundary of ii index

1. Bonding Curve Amount

The total amount of base mint tokens in the bonding curve is given by:

Bonding Curve Amount=iLi(1Pi11Pi)\text{Bonding Curve Amount} = \sum_{i} L_i \left( \frac{1}{P_{i-1}} - \frac{1}{P_i} \right)

2. Migration Quote Threshold

The migration quote threshold required for the pool to migrate is calculated as:

Migration Quote Threshold=iLi(PiPi1)\text{Migration Quote Threshold} = \sum_{i} L_i (P_i - P_{i-1})

3. Migration Price Calculation

To determine the migration price squared (pmax2p_\text{max}^2) during migration, use:

pmax2=Migration Quote Threshold×(1Migration Fee Percentage)Migration Amountp_\text{max}^2 = \frac{\text{Migration Quote Threshold} \times (1 - \text{Migration Fee Percentage})}{\text{Migration Amount}}

Where:

  • Migration Fee Percentage is the fee (as a decimal, e.g., 0.01 for 1%)
  • Migration Amount is the total amount of base mint tokens being migrated

These formulas allow you to compute swap amounts, migration thresholds, and price limits for any custom liquidity distribution along the bonding curve.

Fee Formulas

The total swap fee (fsf_s) will have two components:

  1. A base fee (fbf_b)
  2. A variable fee (fvf_v)

The total swap fee is calculated as:

fs=fb+fvf_s = f_b + f_v

Pool Fee Interface

poolFees: {
    baseFee: {
        cliffFeeNumerator: BN // Initial fee numerator (base fee)
        firstFactor: number // feeScheduler: numberOfPeriod, rateLimiter: feeIncrementBps
        secondFactor: BN // feeScheduler: periodFrequency, rateLimiter: maxLimiterDuration
        thirdFactor: BN // feeScheduler: reductionFactor, rateLimiter: referenceAmount
        baseFeeMode: number // 0: FeeSchedulerLinear, 1: FeeSchedulerExponential, 2: RateLimiter
    }
    dynamicFee: {
        // Optional dynamic fee
        binStep: number // u16 value representing the bin step in bps
        binStepU128: BN // u128 value for a more accurate bin step
        filterPeriod: number // Minimum time that must pass between fee updates
        decayPeriod: number // Period after the volatility starts decaying (must be > filterPeriod)
        reductionFactor: number // Controls how quickly volatility decys over time
        variableFeeControl: number // Multiplier that determines how much volatility affects fees
        maxVolatilityAccumulator: number // Caps the maximum volatility that can be accumulated
    } | null
}

Using the relevant parameters, you can calculate the base fee and variable fee for any given swap.

Migration Fee

We introduced a new migration fee feature that allows users to collect a percentage of the quote_min from the migration_quote_threshold amount.

migrationFee: {
    // Optional migration fee (set as 0 for feePercentage and 0 for creatorFeePercentage for no migration fee)
    feePercentage: number // The percentage of fee taken from migration quote threshold (0-50)
    creatorFeePercentage: number // The fee share percentage for the creator from the migration fee (0-100)
}

ONLY if you are using the buildCurveWithMarketCap function from the DBC Typescript SDK, you will need to calculate the actual initial_market_cap value that you want based on the desired initial market cap.

Formula

let D = desiredMarketCap and M = migrationMarketCap and f = migrationFee and I = initialMarketCap

requiredRatio = sqrt(D / M)
percentageSupplyOnMigration = (requiredRatio * (1 - f) * 100) / (1 + requiredRatio * (1 - f))
x = percentageSupplyOnMigration / ((100 - V - L) - percentageSupplyOnMigration)
I = M * x²

Example

let D = 10000 / SOL_PRICE
let M = 80000 / SOL_PRICE
let f = 0.5
let V = 0
let L = 1 / 1000000000 // leftover needs to be indicated to cover precision loss

let requiredRatio = Math.sqrt(D / M)
let percentageSupplyOnMigration =
    (requiredRatio * (1 - f) * 100) / (1 + requiredRatio * (1 - f))
let x =
    percentageSupplyOnMigration /
    (100 - V - L - percentageSupplyOnMigration)
let I = M * x * x

const curveConfig = buildCurveWithMarketCap({
    totalTokenSupply: 1000000000,
    initialMarketCap: I,
    migrationMarketCap: M,
    migrationOption: MigrationOption.MET_DAMM_V2,
    tokenBaseDecimal: TokenDecimal.SIX,
    tokenQuoteDecimal: TokenDecimal.NINE,
    lockedVestingParam: {
        totalLockedVestingAmount: 0,
        numberOfVestingPeriod: 0,
        cliffUnlockAmount: 0,
        totalVestingDuration: 0,
        cliffDurationFromMigrationTime: 0,
    },
    baseFeeParams: {
        baseFeeMode: BaseFeeMode.FeeSchedulerLinear,
        feeSchedulerParam: {
            startingFeeBps: 100,
            endingFeeBps: 100,
            numberOfPeriod: 0,
            totalDuration: 0,
        },
    },
    dynamicFeeEnabled: false,
    activationType: ActivationType.Slot,
    collectFeeMode: CollectFeeMode.QuoteToken,
    migrationFeeOption: MigrationFeeOption.FixedBps100,
    tokenType: TokenType.SPL,
    partnerLpPercentage: 0,
    creatorLpPercentage: 0,
    partnerLockedLpPercentage: 100,
    creatorLockedLpPercentage: 0,
    creatorTradingFeePercentage: 0,
    leftover: 1,
    tokenUpdateAuthority: 0,
    migrationFee: {
        feePercentage: 50,
        creatorFeePercentage: 0,
    },
})
A leftover value is needed to cover precision loss when you indicate a migration fee.