Pump.fun-style token launch platform development

We design and develop full-cycle blockchain solutions: from smart contract architecture to launching DeFi protocols, NFT marketplaces and crypto exchanges. Security audits, tokenomics, integration with existing infrastructure.
Showing 1 of 1 servicesAll 1306 services
Pump.fun-style token launch platform development
Complex
from 2 weeks to 3 months
FAQ
Blockchain Development Services
Blockchain Development Stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1238
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1167
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    867
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1080
  • image_logo-advance_0.png
    B2B Advance company logo design
    563
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    829

Development of Pump.fun-Style Platform

pump.fun solved a specific infrastructure problem: launching a token on Solana took hours and required technical knowledge. The platform made it accessible in 30 seconds. The mechanics are straightforward — bonding curve until reaching a certain market cap, then automatic liquidity migration to Raydium. Tens of millions of dollars flow through the platform daily. Technically, this is an interesting system with several non-trivial components.

Bonding Curve: Core Mechanics

Bonding curve is a mathematical function that determines token price based on current supply. No orderbook, no LP, no external price — the contract itself determines the exchange rate.

Linear curve:

Price = initial_price + slope * supply

Simple, predictable, but price growth proportional to buy volume — a whale can quickly push the price.

Exponential curve:

Price = initial_price * e^(k * supply)

Sharper growth at high supply. Early buyers get significantly more advantage.

pump.fun uses polynomial bonding curve — implementation with virtual reserves, mimicking Uniswap AMM behavior without real liquidity:

virtual_sol_reserves = 30 SOL
virtual_token_reserves = 1_073_000_000 tokens
real_sol_reserves = 0 (accumulates from sales)
real_token_reserves = 793_100_000 tokens (sold via curve)

Price is determined via constant product formula: k = virtual_sol * virtual_token_supply. When buying dx SOL:

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

This is exactly Uniswap V2 mechanics, but with virtual reserves instead of real LP tokens.

Implementation on EVM

contract BondingCurve {
    uint256 public constant VIRTUAL_SOL_RESERVES = 30 ether;  // in 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 in ETH

    uint256 public realEthReserves;      // accumulated ETH
    uint256 public tokensSold;           // sold via curve

    // How many tokens you get for 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;
    }

    // How many ETH you get for X tokens
    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);

        // Check migration threshold
        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);
    }
}

Automatic DEX Migration

When threshold is reached (pump.fun — $69k market cap), the contract automatically:

  1. Stops trading via bonding curve
  2. Creates a pool on Uniswap V2 (or V3)
  3. Adds accumulated ETH + remaining tokens as liquidity
  4. Burns or locks LP tokens forever
function _migrateToDEX() internal {
    migrated = true;

    uint256 ethForLiquidity = realEthReserves;
    uint256 tokensForLiquidity = TOTAL_SUPPLY - tokensSold; // unsold supply

    // Create pair and add liquidity
    address pair = IUniswapV2Factory(UNISWAP_FACTORY).createPair(
        token,
        WETH
    );

    // Approve and add liquidity
    IERC20(token).approve(UNISWAP_ROUTER, tokensForLiquidity);

    (, , uint256 lpTokens) = IUniswapV2Router(UNISWAP_ROUTER).addLiquidityETH{
        value: ethForLiquidity
    }(
        token,
        tokensForLiquidity,
        tokensForLiquidity,  // minTokens = 100% (no slippage at pool creation)
        ethForLiquidity,     // minETH = 100%
        address(this),
        block.timestamp + 300
    );

    // Burn LP tokens — liquidity is permanent
    IERC20(pair).transfer(address(0xdead), lpTokens);

    emit Migrated(pair, ethForLiquidity, tokensForLiquidity);
}

Locked vs burned LP: pump.fun burns LP tokens (sends to dead address). Alternative — lock via Unicrypt/Team.Finance. Burning is more radical, but irreversible — if there's a contract bug, can't fix it.

Token Factory: Launch in One Call

Each user launches a new token. Need a factory that deploys token + bonding curve contract in one transaction:

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) {
        // Deploy minimal ERC-20
        token = address(new MinimalERC20(name, symbol, TOTAL_SUPPLY));
        curve = address(new BondingCurve(token, msg.sender));

        // Transfer all tokens to curve
        MinimalERC20(token).transfer(curve, TOTAL_SUPPLY);

        // Initial buy if ETH provided
        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 for predictable addresses — useful for frontend: can calculate token address before deployment and show user in advance.

Anti-rug Mechanisms

Main risks: creator dumps (bought 80% supply via curve at low price, sells after hype). pump.fun partially solves this architecturally — after migration, LP is locked and creator cannot withdraw liquidity.

Maximum allocation per address — while using the curve, one address cannot buy more than X% of supply at once:

uint256 public constant MAX_BUY_PERCENT = 10; // max 10% per transaction

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 between purchases — protection against rapid accumulation by bots.

Indexing and Discovery

With thousands of new tokens daily, need real-time index:

The Graph subgraph for indexing TokenCreated, Trade, Migrated events. GraphQL API for frontend.

Trending algorithm (simplified):

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

Higher weight on recent volume and unique buyer count (not volume from single whale).

WebSocket for live trades — frontend subscribes to events of specific token and displays trades in real time.

Platform Economics

pump.fun earns from:

  • 1% fee from each trade via bonding curve
  • 0.5% of volume after migration to Raydium
  • Optional creator verification payment

At $1M/day volume this is $10,000/day from trading fee alone. For EVM implementation on Base/Arbitrum — model is similar, but gas cost higher than Solana, important for small trades.

Technical Stack

Contracts: Solidity + Foundry (testing with fuzz for invariants: totalEth = sum(all buys) - sum(all sells))

Indexing: The Graph or custom indexer (Node.js + ethers.js + PostgreSQL)

Frontend: React + wagmi + viem, real-time via WebSocket to custom indexer

Charts: TradingView Lightweight Charts over indexed trade data

Metadata storage: IPFS (token image, description)

Development Phases

Phase Content Time
Bonding curve math Curve parameters, invariant tests 1–2 weeks
Core contracts Factory, BondingCurve, migration 3–4 weeks
Security audit Focus on curve manipulation, reentrancy 2–3 weeks
Indexer Subgraph or custom indexer 2–3 weeks
Frontend Trading interface, discovery, charts 4–6 weeks
Testnet Full cycle create → trade → migrate 2–3 weeks
Mainnet Deploy to target chain 1 week

Critical tests: fuzz invariants (totalETHin - totalETHout = realEthReserves), migration math (DEX pool price immediately after migration should match bonding curve price at migration moment), extreme slippage scenarios.