Розробка бондинг-кривої (bonding curve) для запуску токена
Pump.fun зробив bonding curve масовим продуктом: будь-хто може запустити токен без seed liquidity, без листингу на CEX, без алокацій інсайдерам. Ціна зростає за детермінованою кривою разом із покупками — і падає разом із продажами. Це не магія, це математика AMM без пулу контрагентів.
Але за простотою інтерфейсу приховується нетривіальний вибір: форма кривої, параметри, механіка градієнта (перехід на DEX), захист від снайпер-ботів. Неправильні рішення тут = токен вмирає в перші години.
Форми кривих та їх поведінка
Лінійна bonding curve
P(x) = a * x + b
Ціна зростає лінійно з supply. Просто, передбачувано. Проблема: при низькому a ранні покупці отримують мінімальну перевагу; при високому — пізні входящі переплачують непропорційно.
Експоненціальна / степенева крива
P(x) = a * x^n
При n > 1 — зростання прискорюється. Сильно вознаграджує ранніх учасників. Pump.fun використовує варіант цієї кривої.
Формула Bancor (константне співвідношення резерву)
P = Balance / (Supply * CRR)
де CRR (Constant Reserve Ratio) — частка резерву. При CRR = 0.5 ціна зростає як x^2. Bancor зробив цю математику популярною; Uniswap v3 використовує подібні ідеї в зосередженій ліквідності.
Сигмоїдна крива
Повільне зростання на початку, швидке в середині, сповільнення до максимуму. Імітує S-криву адаптації. Складніше у реалізації, але більш "органічне" ціноутворення для utility токенів.
Реалізація: ключові рішення контракту
Інваріант vs. обчислення при кожній транзакції
Два підходи:
Аналітичний — формула задана точно, ціна обчислюється математично для будь-якого x. Вимагає точної арифметики великих чисел без втрати точності.
Дискретний — ціна оновлюється поступеньками. Простіше, менш gas-інтенсивно, але менш точно.
Для виробництва бажаний аналітичний підхід із використанням бібліотек fixed-point (PRBMath, ABDKMath):
import { PRBMathUD60x18 } from "@prb/math/UD60x18.sol";
contract BondingCurve {
using PRBMathUD60x18 for uint256;
uint256 public constant INITIAL_PRICE = 0.000001 ether; // у wei
uint256 public constant K = 1e15; // коефіцієнт крутизни кривої
uint256 public totalSupply;
uint256 public reserveBalance;
// Ціна поточного токена при supply = x
function currentPrice() public view returns (uint256) {
// P(x) = INITIAL_PRICE + K * x^2
return INITIAL_PRICE + K.mul(totalSupply.powu(2));
}
// Вартість покупки токенів amount (інтеграл кривої)
function getBuyPrice(uint256 amount) public view returns (uint256) {
// Інтеграл P(x)dx від totalSupply до 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)
Параметри minTokens / minEth обов'язкові. Без них транзакція вразлива до sandwich-атаки: бот бачить велику покупку у mempool, купує перед нею (підвищує ціну), продає після (отримує різницю).
Структура комісій
Bonding curve заробляє через комісії при 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;
// ... розрахунок tokenAmount на основі netValue
}
Pump.fun бере 1% з кожної транзакції + 0.5 SOL при градієнті. Це генерує значний протокольний дохід.
Градієнт: перехід на DEX
Градієнт — момент, коли токен досягає цільової ринкової капіталізації та переходить з bonding curve на Uniswap/Raydium. Це критичний момент: крива припиняє роботу, ліквідність мігрує в пул.
uint256 public constant GRADUATION_THRESHOLD = 69000 ether; // ринкова капітал у wei
uint256 public constant GRADUATION_LIQUIDITY = 12000 ether; // резерв для пулу DEX
function _checkGraduation() internal {
uint256 marketCap = totalSupply * currentPrice();
if (marketCap >= GRADUATION_THRESHOLD && !graduated) {
graduated = true;
_graduate();
}
}
function _graduate() internal {
// 1. Створюємо пару Uniswap v2
address pair = IUniswapV2Factory(UNISWAP_FACTORY).createPair(
address(token), WETH
);
// 2. Додаємо ліквідність із резерву
uint256 ethForLiquidity = GRADUATION_LIQUIDITY;
uint256 tokensForLiquidity = _calculateTokensForLiquidity(ethForLiquidity);
token.mint(address(this), tokensForLiquidity);
IUniswapV2Router(UNISWAP_ROUTER).addLiquidityETH{value: ethForLiquidity}(
address(token),
tokensForLiquidity,
0, 0, // мінімальні суми (можна зробити строгіше)
DEAD_ADDRESS, // Спалюємо LP токени — ліквідність вічна
block.timestamp + 300
);
emit Graduated(pair, ethForLiquidity, tokensForLiquidity);
}
Важливо: LP токени відправляються на 0xdead (спалювання). Це гарантує, що ліквідність не може бути виведена. Без цього — rug pull можливий у момент градієнту.
Захист від снайперів
Снайпер-боти моніторять mempool або события та купують у момент запуску з максимальним gas. Вони захоплюють велику частку раннього supply.
Кілька механік захисту:
Затримка між покупками — мінімальний інтервал між транзакціями однієї адреси:
mapping(address => uint256) public lastBuyBlock;
modifier antiBotCooldown() {
require(block.number > lastBuyBlock[msg.sender] + 2, "Cooldown");
lastBuyBlock[msg.sender] = block.number;
_;
}
Максимальна покупка на транзакцію — лімітація однієї транзакції в перші N блоків.
Затримка запуску з commit-reveal — адреса контракту невідома до моменту запуску (розгортається через CREATE2 з солтом, відомим тільки у момент запуску).
Параметри кривої: практичні орієнтири
| Параметр | Значення для мем-токена | Значення для utility-токена |
|---|---|---|
| Початкова ціна | 0.000001 ETH | 0.001 ETH |
| Ринкова капіталізація градієнту | $50K–$100K | $500K–$2M |
| Комісія покупки | 1–2% | 0.3–1% |
| Комісія продажу | 1–2% | 0.3–1% |
| Форма кривої | Експоненціальна (n=2) | Лінійна або сигмоїдна |
| Максимальна покупка (запуск) | 0.5–1 ETH | 5–10 ETH |
Bonding curve — це не просто смарт-контракт, це механізм виявлення ціни без order book. Правильно налаштована крива створює органічне зростання ціни, справедливе вознаграджування ранніх учасників та плавний перехід на класичний AMM.







