Development of Bonding Curve (bonding curve) for Token Launch
Pump.fun made bonding curve a mass-market product: anyone can launch a token without seed liquidity, without CEX listing, without insider allocation. Price increases along a deterministic curve as purchases grow — and decreases with sales. This isn't magic, it's mathematics of AMM without a counterparty pool.
But behind the simple interface lies a non-trivial choice: curve shape, parameters, graduation mechanics (transition to DEX), protection against sniper bots. Wrong decisions here = token dies in the first hours.
Curve Forms and Their Behavior
Linear bonding curve
P(x) = a * x + b
Price increases linearly with supply. Simple, predictable. Problem: at low a, early buyers get minimal advantage; at high a, late entrants overpay disproportionately.
Exponential / Power curve
P(x) = a * x^n
When n > 1 — growth accelerates. Strongly rewards early participants. Pump.fun uses a variant of this curve.
Bancor formula (constant reserve ratio)
P = Balance / (Supply * CRR)
Where CRR (Constant Reserve Ratio) is the reserve fraction. At CRR = 0.5, price grows as x^2. Bancor popularized this math; Uniswap v3 uses similar ideas in concentrated liquidity.
Sigmoid curve
Slow growth at the beginning, fast in the middle, slowdown approaching maximum. Mimics S-curve adoption. More complex to implement, but more "organic" pricing for utility tokens.
Implementation: Key Contract Decisions
Invariant vs. Computation per Transaction
Two approaches:
Analytical — formula is precisely defined, price is calculated mathematically for any x. Requires precise big number arithmetic without precision loss.
Discrete — price updates in steps. Simpler, less gas-intensive, but less precise.
For production, analytical is preferred using fixed-point libraries (PRBMath, ABDKMath):
import { PRBMathUD60x18 } from "@prb/math/UD60x18.sol";
contract BondingCurve {
using PRBMathUD60x18 for uint256;
uint256 public constant INITIAL_PRICE = 0.000001 ether; // in wei
uint256 public constant K = 1e15; // curve steepness coefficient
uint256 public totalSupply;
uint256 public reserveBalance;
// Price of current token at supply = x
function currentPrice() public view returns (uint256) {
// P(x) = INITIAL_PRICE + K * x^2
return INITIAL_PRICE + K.mul(totalSupply.powu(2));
}
// Cost to buy amount tokens (curve integral)
function getBuyPrice(uint256 amount) public view returns (uint256) {
// Integral P(x)dx from totalSupply to totalSupply + amount
uint256 newSupply = totalSupply + amount;
// ∫(INITIAL_PRICE + K*x^2)dx = INITIAL_PRICE*x + K*x^3/3
return _integral(newSupply) - _integral(totalSupply);
}
function _integral(uint256 x) internal pure returns (uint256) {
return INITIAL_PRICE * x + K.mul(x.powu(3)) / 3;
}
function buy(uint256 minTokens) external payable {
uint256 tokensToMint = _calculatePurchaseReturn(msg.value);
require(tokensToMint >= minTokens, "Slippage exceeded");
reserveBalance += msg.value;
totalSupply += tokensToMint;
token.mint(msg.sender, tokensToMint);
emit Buy(msg.sender, msg.value, tokensToMint);
}
function sell(uint256 tokenAmount, uint256 minEth) external {
uint256 ethToReturn = _calculateSaleReturn(tokenAmount);
require(ethToReturn >= minEth, "Slippage exceeded");
token.burnFrom(msg.sender, tokenAmount);
totalSupply -= tokenAmount;
reserveBalance -= ethToReturn;
payable(msg.sender).transfer(ethToReturn);
emit Sell(msg.sender, tokenAmount, ethToReturn);
}
}
Slippage protection
minTokens / minEth parameters are mandatory. Without them, the transaction is vulnerable to sandwich attack: a bot sees a large buy in mempool, buys before it (raises price), sells after (captures the difference).
Fee structure
Bonding curve earns through fees on buy/sell:
uint256 public buyFeeBps = 100; // 1%
uint256 public sellFeeBps = 100; // 1%
function buy(uint256 minTokens) external payable {
uint256 fee = msg.value * buyFeeBps / 10000;
uint256 netValue = msg.value - fee;
protocolFees += fee;
// ... calculate tokenAmount based on netValue
}
Pump.fun takes 1% on each trade + 0.5 SOL at graduation. This generates significant protocol revenue.
Graduation: Transition to DEX
Graduation is the moment when a token reaches target market cap and moves from bonding curve to Uniswap/Raydium. This is critical: the curve stops working, liquidity migrates to the pool.
uint256 public constant GRADUATION_THRESHOLD = 69000 ether; // market cap in wei
uint256 public constant GRADUATION_LIQUIDITY = 12000 ether; // reserve for DEX pool
function _checkGraduation() internal {
uint256 marketCap = totalSupply * currentPrice();
if (marketCap >= GRADUATION_THRESHOLD && !graduated) {
graduated = true;
_graduate();
}
}
function _graduate() internal {
// 1. Create Uniswap v2 pair
address pair = IUniswapV2Factory(UNISWAP_FACTORY).createPair(
address(token), WETH
);
// 2. Add liquidity from reserve
uint256 ethForLiquidity = GRADUATION_LIQUIDITY;
uint256 tokensForLiquidity = _calculateTokensForLiquidity(ethForLiquidity);
token.mint(address(this), tokensForLiquidity);
IUniswapV2Router(UNISWAP_ROUTER).addLiquidityETH{value: ethForLiquidity}(
address(token),
tokensForLiquidity,
0, 0, // min amounts (can be stricter)
DEAD_ADDRESS, // Burn LP tokens — liquidity permanent
block.timestamp + 300
);
emit Graduated(pair, ethForLiquidity, tokensForLiquidity);
}
Important: LP tokens are sent to 0xdead (burn). This guarantees that liquidity cannot be withdrawn. Without this — rug pull is possible at graduation.
Protection Against Snipers
Sniper bots monitor mempool or events and buy at launch with maximum gas. They capture a large share of early supply.
Several protection mechanics:
Cooldown between purchases — minimum interval between transactions from one address:
mapping(address => uint256) public lastBuyBlock;
modifier antiBotCooldown() {
require(block.number > lastBuyBlock[msg.sender] + 2, "Cooldown");
lastBuyBlock[msg.sender] = block.number;
_;
}
Max buy per transaction — limit on one transaction in the first N blocks.
Launch delay with commit-reveal — contract address not known until launch moment (deployed via CREATE2 with salt, known only at launch time).
Curve Parameters: Practical Guidelines
| Parameter | Value for meme token | Value for utility token |
|---|---|---|
| Initial price | 0.000001 ETH | 0.001 ETH |
| Graduation market cap | $50K–$100K | $500K–$2M |
| Buy fee | 1–2% | 0.3–1% |
| Sell fee | 1–2% | 0.3–1% |
| Curve shape | Exponential (n=2) | Linear or sigmoid |
| Max buy (launch) | 0.5–1 ETH | 5–10 ETH |
Bonding curve — it's not just a smart contract, it's a price discovery mechanism without an order book. A properly configured curve creates organic price growth, fair rewards for early participants, and smooth transition to classic AMM.







