Разработка платформы в стиле pump.fun

Проектируем и разрабатываем блокчейн-решения полного цикла: от архитектуры смарт-контрактов до запуска DeFi-протоколов, NFT-маркетплейсов и криптобирж. Аудит безопасности, токеномика, интеграция с существующей инфраструктурой.
Показано 1 из 1Все 1306 услуг
Разработка платформы в стиле pump.fun
Сложный
от 2 недель до 3 месяцев
Часто задаваемые вопросы

Направления блокчейн-разработки

Этапы блокчейн-разработки

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1288
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1198
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    902
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1123
  • image_logo-advance_0.webp
    Разработка логотипа компании B2B Advance
    589
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    860

Разработка платформы в стиле pump.fun

pump.fun решила конкретную инфраструктурную проблему: запуск токена на Solana занимал часы и требовал технических знаний. Платформа сделала это доступным за 30 секунд. Механика простая — bonding curve до достижения определённой рыночной капитализации, затем автоматическая миграция ликвидности в Raydium. Ежедневно через платформу проходят десятки миллионов долларов. Технически это интересная система с несколькими нетривиальными компонентами.

Bonding Curve: ядро механики

Bonding curve — математическая функция, определяющая цену токена в зависимости от текущего supply. Нет orderbook, нет LP, нет внешней цены — контракт сам определяет обменный курс.

Линейная кривая:

Price = initial_price + slope * supply

Простая, предсказуемая, но рост цены пропорционален объёму покупок — whale может быстро вытолкнуть цену.

Экспоненциальная кривая:

Price = initial_price * e^(k * supply)

Более резкий рост при высоком supply. Ранние покупатели получают значительно большее преимущество.

pump.fun использует polynomial bonding curve — реализация с virtual reserves, имитирующая поведение Uniswap AMM без реального liquidity:

virtual_sol_reserves = 30 SOL
virtual_token_reserves = 1_073_000_000 tokens
real_sol_reserves = 0 (накапливается от продаж)
real_token_reserves = 793_100_000 tokens (продаются через кривую)

Цена определяется через формулу constant product: k = virtual_sol * virtual_token_supply. При покупке dx SOL:

new_virtual_sol = virtual_sol + dx
new_virtual_token = k / new_virtual_sol
tokens_received = virtual_token - new_virtual_token

Это точная копия механики Uniswap V2, но с виртуальными резервами вместо реальных LP токенов.

Реализация на EVM

contract BondingCurve {
    uint256 public constant VIRTUAL_SOL_RESERVES = 30 ether;  // в ETH/SOL
    uint256 public constant VIRTUAL_TOKEN_RESERVES = 1_073_000_000e18;
    uint256 public constant TOTAL_SUPPLY = 1_000_000_000e18;
    uint256 public constant MIGRATION_THRESHOLD = 69_000 * 1e18; // $69k в ETH

    uint256 public realEthReserves;      // накопленный ETH
    uint256 public tokensSold;           // продано через кривую

    // Сколько токенов получишь за X ETH
    function getTokensOut(uint256 ethIn) public view returns (uint256) {
        uint256 virtualEth = VIRTUAL_SOL_RESERVES + realEthReserves;
        uint256 virtualTokens = VIRTUAL_TOKEN_RESERVES - tokensSold;
        uint256 k = virtualEth * virtualTokens;

        uint256 newVirtualEth = virtualEth + ethIn;
        uint256 newVirtualTokens = k / newVirtualEth;

        return virtualTokens - newVirtualTokens;
    }

    // Сколько ETH получишь за X токенов
    function getEthOut(uint256 tokensIn) public view returns (uint256) {
        uint256 virtualEth = VIRTUAL_SOL_RESERVES + realEthReserves;
        uint256 virtualTokens = VIRTUAL_TOKEN_RESERVES - tokensSold;
        uint256 k = virtualEth * virtualTokens;

        uint256 newVirtualTokens = virtualTokens + tokensIn;
        uint256 newVirtualEth = k / newVirtualTokens;

        return virtualEth - newVirtualEth;
    }

    function buy(uint256 minTokensOut) external payable nonReentrant {
        require(msg.value > 0, "No ETH sent");
        require(!migrated, "Token migrated to DEX");

        uint256 fee = (msg.value * FEE_BPS) / 10000;  // 1%
        uint256 ethIn = msg.value - fee;

        uint256 tokensOut = getTokensOut(ethIn);
        require(tokensOut >= minTokensOut, "Slippage exceeded");

        realEthReserves += ethIn;
        tokensSold += tokensOut;

        IERC20(token).safeTransfer(msg.sender, tokensOut);
        payable(feeRecipient).transfer(fee);

        emit Trade(msg.sender, ethIn, tokensOut, true);

        // Проверяем порог миграции
        if (realEthReserves >= MIGRATION_THRESHOLD) {
            _migrateToDEX();
        }
    }

    function sell(uint256 tokensIn, uint256 minEthOut) external nonReentrant {
        require(!migrated, "Token migrated to DEX");
        require(tokensIn > 0, "Zero tokens");

        uint256 ethOut = getEthOut(tokensIn);
        uint256 fee = (ethOut * FEE_BPS) / 10000;
        uint256 ethToUser = ethOut - fee;

        require(ethToUser >= minEthOut, "Slippage exceeded");

        IERC20(token).safeTransferFrom(msg.sender, address(this), tokensIn);
        tokensSold -= tokensIn;
        realEthReserves -= ethOut;

        payable(msg.sender).transfer(ethToUser);
        payable(feeRecipient).transfer(fee);

        emit Trade(msg.sender, tokensIn, ethToUser, false);
    }
}

Автоматическая миграция в DEX

При достижении threshold (у pump.fun — $69k market cap) контракт автоматически:

  1. Останавливает торговлю через bonding curve
  2. Создаёт пул на Uniswap V2 (или V3)
  3. Добавляет накопленный ETH + оставшиеся токены как ликвидность
  4. Сжигает или локает LP токены навсегда
function _migrateToDEX() internal {
    migrated = true;

    uint256 ethForLiquidity = realEthReserves;
    uint256 tokensForLiquidity = TOTAL_SUPPLY - tokensSold; // нераспроданный supply

    // Создаём пул и добавляем ликвидность
    address pair = IUniswapV2Factory(UNISWAP_FACTORY).createPair(
        token,
        WETH
    );

    // Approve и добавление ликвидности
    IERC20(token).approve(UNISWAP_ROUTER, tokensForLiquidity);

    (, , uint256 lpTokens) = IUniswapV2Router(UNISWAP_ROUTER).addLiquidityETH{
        value: ethForLiquidity
    }(
        token,
        tokensForLiquidity,
        tokensForLiquidity,  // minTokens = 100% (нет слиппажа при создании пула)
        ethForLiquidity,     // minETH = 100%
        address(this),
        block.timestamp + 300
    );

    // Сжигаем LP токены — ликвидность перманентна
    IERC20(pair).transfer(address(0xdead), lpTokens);

    emit Migrated(pair, ethForLiquidity, tokensForLiquidity);
}

Locked vs burned LP: pump.fun сжигает LP токены (отправляет на dead address). Альтернатива — локать через Unicrypt/Team.Finance. Сжигание радикальнее, но необратимо — если в контракте баг, исправить нельзя.

Фабрика токенов: запуск за один вызов

Каждый пользователь запускает новый токен. Нужна фабрика, которая деплоит токен + bonding curve контракт за одну транзакцию:

contract TokenFactory {
    event TokenCreated(
        address indexed token,
        address indexed curve,
        address indexed creator,
        string name,
        string symbol,
        string uri,
        uint256 timestamp
    );

    address[] public allTokens;
    mapping(address => TokenInfo) public tokenInfo;

    function createToken(
        string calldata name,
        string calldata symbol,
        string calldata uri,
        uint256 initialBuyEth
    ) external payable returns (address token, address curve) {
        // Деплой минимального ERC-20
        token = address(new MinimalERC20(name, symbol, TOTAL_SUPPLY));
        curve = address(new BondingCurve(token, msg.sender));

        // Передаём все токены в кривую
        MinimalERC20(token).transfer(curve, TOTAL_SUPPLY);

        // Первая покупка если был ETH
        if (initialBuyEth > 0) {
            uint256 creationFee = CREATION_FEE;
            require(msg.value >= creationFee + initialBuyEth, "Insufficient ETH");
            BondingCurve(payable(curve)).buy{value: initialBuyEth}(0);
        }

        allTokens.push(token);
        tokenInfo[token] = TokenInfo({
            curve: curve,
            creator: msg.sender,
            name: name,
            symbol: symbol,
            uri: uri,
            createdAt: block.timestamp
        });

        emit TokenCreated(token, curve, msg.sender, name, symbol, uri, block.timestamp);
    }
}

CREATE2 для предсказуемых адресов — полезно для frontend: можно рассчитать адрес токена до деплоя и показывать пользователю заранее.

Anti-rug механизмы

Основные риски: создатель dump'ает (купил 80% supply через кривую при низкой цене, продаёт после hype). pump.fun частично решает это архитектурой — после миграции LP залочен и создатель не может вытащить ликвидность.

Максимальная аллокация на адрес — при работе через кривую один адрес не может купить более X% supply за раз:

uint256 public constant MAX_BUY_PERCENT = 10; // максимум 10% за транзакцию

function buy(uint256 minTokensOut) external payable {
    uint256 tokensOut = getTokensOut(msg.value);
    uint256 maxTokens = (TOTAL_SUPPLY * MAX_BUY_PERCENT) / 100;
    require(tokensOut <= maxTokens, "Buy too large");
    // ...
}

Cooldown между покупками — защита от rapid accumulation ботами.

Индексирование и discovery

С тысячами новых токенов в день нужен real-time индекс:

The Graph subgraph для индексирования событий TokenCreated, Trade, Migrated. GraphQL API для frontend.

Trending алгоритм (упрощённо):

score = (volume_1h * 3) + (volume_24h * 1) + (buyers_1h * 50) - (sellers_1h * 30)

Больший вес у недавнего объёма и количества уникальных покупателей (а не объёма от одного whale).

WebSocket для live trades — frontend подписывается на события конкретного токена и отображает trades в реальном времени.

Экономика платформы

pump.fun зарабатывает:

  • 1% fee от каждой trade через bonding curve
  • 0.5% от объёма после миграции в Raydium
  • Платная верификация создателей (опционально)

При объёме $1M/день это $10,000/день только от trading fee. Для EVM реализации на Base/Arbitrum — модель аналогична, но gas cost выше чем на Solana, что важно для маленьких сделок.

Технический стек

Контракты: Solidity + Foundry (тестирование с fuzz для invariants: totalEth = sum(all buys) - sum(all sells))

Индексирование: The Graph или собственный indexer (Node.js + ethers.js + PostgreSQL)

Frontend: React + wagmi + viem, real-time через WebSocket к собственному indexer

Чарты: TradingView Lightweight Charts поверх indexed trade data

Хранение метаданных: IPFS (изображение, описание токена)

Этапы разработки

Фаза Содержание Срок
Bonding curve math Расчёт параметров кривой, тесты инвариантов 1–2 нед
Core contracts Factory, BondingCurve, миграция 3–4 нед
Security audit Особое внимание на манипуляцию кривой, reentrancy 2–3 нед
Indexer Subgraph или кастомный indexer 2–3 нед
Frontend Trading interface, discovery, charts 4–6 нед
Testnet Полный цикл создание → торговля → миграция 2–3 нед
Mainnet Деплой на target chain 1 нед

Критические тесты: fuzz invariants (totalETHin - totalETHout = realEthReserves), migration math (цена в DEX пуле сразу после миграции должна совпадать с ценой на bonding curve в момент миграции), extreme slippage scenarios.