Розроблення платформи запуску мемкоінів
Pump.fun обробив більше $1B транзакцій за перший рік роботи. Ключовий інсайт команди: барьєр для запуску токена був занадто високим (деплой контракту, створення LP, листинг), а механізм накачування через bonding curve — передбачуваним та зрозумілим користувачам. Результат — машина для запуску токенів, яка генерує мільйони в protocol revenue щомісячно.
Платформа подібного роду технічно нетривіальна: bonding curve зі специфічною математикою, автоматичний перехід на DEX при досягненні порога ліквідності, anti-rug механізми, та усе це повинно працювати за секунди при високій конкуренції.
Bonding Curve: математика та реалізація
Constantна product curve (спрощена Pump.fun)
Pump.fun використовує віртуальний AMM з константним добутком. При запуску токен не має реальної ліквідності — віртуальні резерви задають початкову ціну.
contract BondingCurve {
uint256 public constant VIRTUAL_SOL_RESERVE = 30_000_000_000; // 30 SOL віртуальних
uint256 public constant VIRTUAL_TOKEN_RESERVE = 1_073_000_000 * 10**6; // 1.073B токенів
uint256 public constant TOTAL_SUPPLY = 1_000_000_000 * 10**6;
uint256 public constant GRADUATION_THRESHOLD = 85_000_000_000; // 85 SOL зібрано
uint256 public realSolReserve; // фактично внесений SOL
uint256 public realTokenReserve; // токени в кривій
// k = (virtual_sol + real_sol) * (virtual_token + real_token) = const
function buy(uint256 solIn) external payable returns (uint256 tokensOut) {
require(msg.value == solIn, "Value mismatch");
require(!graduated, "Already on DEX");
uint256 virtualSol = VIRTUAL_SOL_RESERVE + realSolReserve;
uint256 virtualToken = VIRTUAL_TOKEN_RESERVE - (TOTAL_SUPPLY - realTokenReserve);
// Constant product: k = virtualSol * virtualToken
// Після покупки: (virtualSol + solIn) * (virtualToken - tokensOut) = k
// tokensOut = virtualToken - k / (virtualSol + solIn)
uint256 k = virtualSol * virtualToken;
tokensOut = virtualToken - (k / (virtualSol + solIn));
require(tokensOut <= realTokenReserve, "Not enough tokens");
realSolReserve += solIn;
realTokenReserve -= tokensOut;
token.transfer(msg.sender, tokensOut);
// Перевіряємо graduation
if (realSolReserve >= GRADUATION_THRESHOLD) {
_graduate();
}
emit TokensPurchased(msg.sender, solIn, tokensOut, currentPrice());
}
function currentPrice() public view returns (uint256) {
uint256 virtualSol = VIRTUAL_SOL_RESERVE + realSolReserve;
uint256 virtualToken = VIRTUAL_TOKEN_RESERVE - (TOTAL_SUPPLY - realTokenReserve);
// ціна в SOL за токен (lamports)
return (virtualSol * 10**6) / virtualToken;
}
}
Віртуальні резерви — ключовий елемент. Без них початкова ціна при нульовій ліквідності була б 0. Віртуальні резерви створюють штучну «глибину» кривої, формуючи стартову ціну та контролюючи price impact перших покупок.
Graduation: перехід на Raydium/Uniswap
Коли платформа збирає достатньо SOL/ETH — токен «gradates»: контракт автоматично створює LP пул на DEX та додає ліквідність.
function _graduate() internal {
graduated = true;
uint256 solForLiquidity = realSolReserve; // весь зібраний SOL
uint256 tokensForLiquidity = realTokenReserve; // залишкові токени
// Створюємо LP на Uniswap V2 (або Raydium на Solana)
IUniswapV2Router router = IUniswapV2Router(ROUTER_ADDRESS);
token.approve(address(router), tokensForLiquidity);
(uint amountToken, uint amountETH, uint liquidity) = router.addLiquidityETH{
value: solForLiquidity
}(
address(token),
tokensForLiquidity,
tokensForLiquidity * 99 / 100, // 1% slippage
solForLiquidity * 99 / 100,
address(0), // LP токени на address(0) — burn ліквідності
block.timestamp + 300
);
// Спалюємо LP токени — ліквідність permanent, не можна rug pull
emit Graduated(address(token), amountToken, amountETH, liquidity);
}
Спалення LP токенів при graduation — критичний anti-rug механізм. Створювач не може вивести ліквідність та втекти. Це — головне преімущество довіри Pump.fun над самостійним запуском.
Solana: чому більшість memecoin платформ там
Pump.fun на Solana не випадково:
- Транзакція: ~$0.0001 vs $0.5-5 на Ethereum mainnet
- Finality: ~400ms vs 12+ секунд
- При високочастотних launch подіях (сотні токенів на годину) — це вирішальне UX преімущество
Solana Anchor framework для контрактів:
use anchor_lang::prelude::*;
use anchor_spl::token::{self, Mint, Token, TokenAccount};
#[program]
pub mod pump_clone {
use super::*;
pub fn create_token(
ctx: Context<CreateToken>,
name: String,
symbol: String,
uri: String,
total_supply: u64,
) -> Result<()> {
// Мінтимо всі токени в bonding curve vault
token::mint_to(
CpiContext::new_with_signer(
ctx.accounts.token_program.to_account_info(),
token::MintTo {
mint: ctx.accounts.mint.to_account_info(),
to: ctx.accounts.bonding_curve_vault.to_account_info(),
authority: ctx.accounts.mint_authority.to_account_info(),
},
&[&[b"mint_authority", &[ctx.bumps.mint_authority]]],
),
total_supply,
)?;
// Інітіалізуємо bonding curve account
let curve = &mut ctx.accounts.bonding_curve;
curve.total_supply = total_supply;
curve.virtual_sol_reserves = 30_000_000_000; // 30 SOL
curve.virtual_token_reserves = total_supply;
curve.real_sol_reserves = 0;
curve.real_token_reserves = total_supply;
curve.graduated = false;
curve.creator = ctx.accounts.creator.key();
emit!(TokenCreated {
mint: ctx.accounts.mint.key(),
creator: ctx.accounts.creator.key(),
name,
symbol,
uri,
});
Ok(())
}
pub fn buy(ctx: Context<Buy>, sol_amount: u64, min_tokens: u64) -> Result<()> {
let curve = &mut ctx.accounts.bonding_curve;
require!(!curve.graduated, ErrorCode::AlreadyGraduated);
let tokens_out = curve.calculate_buy(sol_amount)?;
require!(tokens_out >= min_tokens, ErrorCode::SlippageExceeded);
// Передаємо SOL від покупця до vault
anchor_lang::system_program::transfer(
CpiContext::new(
ctx.accounts.system_program.to_account_info(),
anchor_lang::system_program::Transfer {
from: ctx.accounts.buyer.to_account_info(),
to: ctx.accounts.sol_vault.to_account_info(),
},
),
sol_amount,
)?;
// Передаємо токени з vault до покупця
token::transfer(
CpiContext::new_with_signer(/* ... */),
tokens_out,
)?;
curve.real_sol_reserves += sol_amount;
curve.real_token_reserves -= tokens_out;
// Перевіряємо graduation
if curve.real_sol_reserves >= GRADUATION_SOL_THRESHOLD {
ctx.accounts.bonding_curve.graduated = true;
// Вызов Raydium CPI для створення LP...
}
Ok(())
}
}
Anti-rug та fair launch механізми
Creator lock
// Створювач не може продати в перші X блоків/хвилин
mapping(address => uint256) public creatorLockExpiry;
function createToken(...) external {
// ...
creatorLockExpiry[newToken] = block.timestamp + 24 hours;
}
// Override transfer для createra
function _beforeTokenTransfer(address from, address to, uint256 amount) internal override {
if (from == tokenCreator[address(this)]) {
require(block.timestamp >= creatorLockExpiry[address(this)], "Creator locked");
}
}
Max buy per wallet
Обмеження знижує premine-сценарії коли створювач скупує велику частину supply до публікації:
uint256 public constant MAX_BUY_PERCENT = 200; // 2% total supply
uint256 public constant MAX_BUY_AMOUNT = TOTAL_SUPPLY * MAX_BUY_PERCENT / 10000;
mapping(address => uint256) public totalBought;
function buy(uint256 solIn) external {
// ...
require(totalBought[msg.sender] + tokensOut <= MAX_BUY_AMOUNT, "Max buy exceeded");
totalBought[msg.sender] += tokensOut;
}
Revenue модель платформи
Платформа заробляє на кожній транзакції в bonding curve. Pump.fun бере 1% від кожної покупки/продажи. При $1M дневного обсягу — $10k дневного revenue тільки від trading fee. Плюс graduation fee при листингу на DEX.
uint256 public constant PLATFORM_FEE_BPS = 100; // 1%
address public immutable feeRecipient;
function buy(uint256 solIn) external payable {
uint256 platformFee = (solIn * PLATFORM_FEE_BPS) / 10000;
uint256 effectiveSolIn = solIn - platformFee;
// platformFee відправляється на feeRecipient
payable(feeRecipient).transfer(platformFee);
// Остаток іде в bonding curve
_processBuy(effectiveSolIn);
}
Frontend: real-time UX
Користувачі очікують миттєвий фідбек: chart обновляється після кожного swap, activity feed показує буквально останні 10 транзакцій.
WebSocket для real-time. Subscribe на on-chain события через Helius (Solana) або Alchemy (EVM). На кожному `TokensPurchased события — оновити chart, додати в activity feed.
// Real-time price updates via WebSocket
const ws = new WebSocket('wss://mainnet.helius-rpc.com/?api-key=...')
ws.send(JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'logsSubscribe',
params: [
{ mentions: [PROGRAM_ID] },
{ commitment: 'confirmed' }
]
}))
ws.onmessage = (event) => {
const { result } = JSON.parse(event.data)
if (result?.value?.logs) {
const parsed = parsePurchaseEvent(result.value.logs)
if (parsed) updateChart(parsed)
}
}
OHLCV chart. Для кожного токена будуємо OHLCV із transaction history. Aggre по 1-хвилинним свічах. TradingView Lightweight Charts — стандарт для crypto проектів.
Модерація та compliance
Token metadata verification. IPFS зберігання метаданих (ім'я, символ, зображення). Платформа не повинна хостити illegals content — потрібна система reportu та можливість приховати токен з UI (не on-chain, тільки frontend).
Spam prevention. Creation fee (невелика кількість SOL) знижує spam launches. Pump.fun бере ~0.02 SOL за створення.
Процес розроблення
Смарт-контракти (4-6 тижнів). Bonding curve контракт → graduation механізм → fee collection → Anchor/Foundry тести з граничними випадками (покупка останнього токена, graduation edge cases, reentrancy).
Індексер (2-3 тижні). Off-chain сервіс, що парсить on-chain события та будує базу даних токенів, цін, транзакцій. PostgreSQL + Redis для кеша. Це потрібно для швидкого API — on-chain query занадто повільний.
API та frontend (3-4 тижні). REST API для списків токенів, WebSocket для real-time updates, React frontend з TradingView charts.
Запуск та моніторинг. Сповіщення на аномальну активність (один адрес купив 10%+ supply), моніторинг gas/compute на Solana, circuit breaker якщо graduation механізм давить на Raydium API.
Повна платформа — 3-4 місяці. MVP без graduation та спрощеним UI — 6-8 тижнів.







