the math behind pumpfun amm

April 3, 2025

Introduction

Pumpfun amm recently launched (at the time of writing) and it is pumpfuns take on an automated market maker. As a developer of a solana pumpfun bot, one of the key challenges of building transactions is figuring out how the prices are calculated. This post will explain how to calculate the price of a pumpfun amm token so you can use it in your transactions.

Maths

All of the tokens/amounts are expressed in lamports (in case of solana) or decimals (in case of other tokens).

If you are not familiar with the concept of lamports, it is the smallest unit of solana. 1 sol = 1_000_000_000 lamports. If you are buying tokens with solana, then your quote amount in lamports is the amount of solana you are sending to the pool.

⚠️ Note: When I'm using sol, I actually mean wrapped sol (wsol) which is what the new pumpfun amm uses. So you will need to wrap your solana before sending it to the pool.

Pumpfun AMM Token Price Calculation

Definitions

1️⃣ Let lpFeeBps be the liquidity provider fee in basis points.
2️⃣ Let protocolFeeBps be the protocol fee in basis points.
3️⃣ Let QuoteAmountIn be the amount of quote tokens being swapped. If you are buying with sol, this would for example be the amount of sol you are sending in lamports.
4️⃣ Let PoolBaseTokenReserves be the reserves of the base token in the pool.
5️⃣ Let PoolQuoteTokenReserves be the reserves of the quote token in the pool.

How to find lpFeeBps and protocolFeeBps

Those are fixed values for most of the time, at time of writing the fees are as following, and will likely stay like this. Make sure to check it out once a while if you will be hardcoding them. To find it, go to solscan and find a PumpFun Buy IX. Example TX Check out the following image to see where to find them: Solscan PumpFun Buy IX Example

Calculations

  1. Total Fee Basis Points:

    totalFeeBps = lpFeeBps + protocolFeeBps

    This step calculates the total fee (in basis points) by summing the liquidity provider fee and the protocol fee. Basis points are used to represent percentages, where 1 basis point equals 0.01%.

  2. Denominator for Effective Quote Calculation:

    denominator = 10000 + totalFeeBps

    The denominator is calculated by adding the total fee (in basis points) to 10,000 (the base value representing 100%). This value will be used to adjust the quote amount to account for fees.

  3. Effective Quote Amount:

    effectiveQuote = (QuoteAmountIn * 10000) / denominator

    The effective quote amount is the adjusted amount of quote tokens after accounting for the fees. This is done by scaling the input quote amount by 10,000 and dividing it by the denominator calculated in the previous step.

  4. Base Tokens Received:

    numerator = PoolBaseTokenReserves * effectiveQuote
    denominatorEffective = PoolQuoteTokenReserves + effectiveQuote

    The numerator represents the product of the base token reserves and the effective quote amount. The denominatorEffective is the sum of the quote token reserves and the effective quote amount. These values are used to calculate the amount of base tokens received.

    baseAmountOut = numerator / denominatorEffective

    The final amount of base tokens received (baseAmountOut) is calculated by dividing the numerator by the denominatorEffective. This represents the number of base tokens you will receive for the given input quote tokens.

Implementation

javascript 🦕

this javascript implementation is from the pumpfun amm sdk on npm : source code

// 1) Calculate total fee basis points and denominator
const totalFeeBps = lpFeeBps.add(protocolFeeBps);
const denominator = new BN(10_000).add(totalFeeBps);

// 2) Calculate effective quote amount
const effectiveQuote = quote.mul(new BN(10_000)).div(denominator);

// 3) Calculate the base tokens received using effectiveQuote
//    base_amount_out = floor(base_reserve * effectiveQuote / (quote_reserve + effectiveQuote))
const numerator = baseReserve.mul(effectiveQuote);
const denominatorEffective = quoteReserve.add(effectiveQuote);

if (denominatorEffective.isZero()) {
    throw new Error("Pool would be depleted; denominator is zero.");
}

const baseAmountOut = numerator.div(denominatorEffective);

// 4) Calculate maxQuote with slippage
//    If slippage=1 => factor = (1 + 1/100) = 1.01
const precision = new BN(1_000_000_000); // For slippage calculations
const slippageFactorFloat = (1 + slippage / 100) * 1_000_000_000;
const slippageFactor = new BN(Math.floor(slippageFactorFloat));

// maxQuote = quote * slippageFactor / 1e9
const maxQuote = quote.mul(slippageFactor).div(precision);

golang 🦫

this golang implementation was done by me. which is a port of the javascript/typescript code above. I have an ammEvent struct which has the following fields, I extract this data from the transaction logs: This just the buy event which is found in the logs.

type AMMBuyEvent struct {
    Identifier                           [8]byte
    Timestamp                            int64
    Base_amount_out                      uint64
    Max_quote_amount_in                  uint64
    User_base_token_reserves             uint64
    User_quote_token_reserves            uint64
    Pool_base_token_reserves             uint64
    Pool_quote_token_reserves            uint64
    Quote_amount_in                      uint64
    Lp_fee_basis_points                  uint64
    Lp_fee                               uint64
    Protocol_fee_basis_points            uint64
    Protocol_fee                         uint64
    Quote_amount_in_with_lp_fee          uint64
    User_quote_amount_in                 uint64
    Pool                                 solana.PublicKey
    User                                 solana.PublicKey
    User_base_token_account              solana.PublicKey
    User_quote_token_account             solana.PublicKey
    Protocol_fee_recipient               solana.PublicKey
    Protocol_fee_recipient_token_account solana.PublicKey
}

And this is the golang code to calculate the base amount out:

// Calculate total fee basis points and denominator 
lpFeeBps := big.NewInt(int64(ammEvent.Lp_fee_basis_points)) 
protocolFeeBps := big.NewInt(int64(ammEvent.Protocol_fee_basis_points))
totalFeeBps := new(big.Int).Add(lpFeeBps, protocolFeeBps)
denominator := new(big.Int).Add(big.NewInt(10000), totalFeeBps)

// Calculate effective quote amount
effectiveQuote := new(big.Int).Mul(big.NewInt(int64(QuoteAmountIn)), big.NewInt(10000))
effectiveQuote = effectiveQuote.Div(effectiveQuote, denominator)

// Calculate the base tokens received using effectiveQuote
numerator := new(big.Int).Mul(big.NewInt(int64(ammEvent.Pool_base_token_reserves)), effectiveQuote)
denominatorEffective := new(big.Int).Add(big.NewInt(int64(ammEvent.Pool_quote_token_reserves)), effectiveQuote)

if denominatorEffective.Cmp(big.NewInt(0)) == 0 {
    return nil, errors.New("Pool would be depleted; denominator is zero.")
}

baseAmountOut := new(big.Int).Div(numerator, denominatorEffective).Uint64()

Conclusion

This is certainly not the only calculation you will need to do when building a pumpfun bot. But I just wrote this as lots of people were asking how to calculate the price of a pumpfun amm token.