pump.fun — the original
Solana, so the runtime is nothing like ours. The economics are, and they are the thing to learn from. Numbers below are from pump.fun's own docs and the published program maths.
Architecture
One program, one PDA per token. There is no factory deploying contracts, because Solana does not work that way — the "per-token contract" is an account.
| account | |
|---|---|
Global (PDA ["global"]) | Every launch's starting parameters. One account, protocol-wide |
BondingCurve (PDA ["bonding-curve", mint]) | Per token: the four reserves and a complete flag |
associated_bonding_curve | The token account the curve actually holds supply in |
| Pump Fees program | Fee rates, queried by the curve. Separate program, so rates move without touching curve logic |
| PumpSwap | The AMM tokens graduate into. Owned by the protocol |
Instructions: create / create_v2 (SPL vs Token-2022), buy, sell. Program
6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P.
The lesson for us: their per-launch state is one cheap account, not a deployment. Our EVM
equivalent is a clone or a single contract holding a mapping — not a full stack per token.
See notes/DECISIONS.md and the EIP-3860 trap.
The curve
Constant product on virtual reserves, same family as ours.
k = virtualTokenReserves * virtualSolReserves
tokensOut = (netSolIn * virtualTokenReserves) / (virtualSolReserves + netSolIn)
solOut = (tokensIn * virtualSolReserves) / (virtualTokenReserves + tokensIn)
Four reserves are tracked: virtual{Token,Sol}Reserves for pricing, real{Token,Sol}Reserves for
what actually exists. Fees come off the input on a buy and the output on a sell — outside the
invariant, exactly as RHUB does it.
Launch parameters:
| total supply | 1,000,000,000 |
initialVirtualTokenReserves | 1,073,000,000 |
initialVirtualSolReserves | 30 SOL |
initialRealTokenReserves | 793,100,000 — the curve allocation |
| reserved for the pool | 206,900,000 |
They are on the same forced relation we are — verified
Graduation is realTokenReserves == 0, i.e. the curve sells its whole allocation. Solving that:
raise at sell-out 85.005 SOL
curve share c 0.7931
implied virtual reserve T(1-c)/(2c-1) = 30.003 SOL <- their actual 30
curve close price 0.000000410880 SOL
pool open price 0.000000410852 SOL
pump.fun obeys V = T(1-c)/(2c-1) to four significant figures. Same equation as
../launchpad, same equation in ../888/notes/CURVE-MATH.md. They did not pick a different
mechanism; they picked a different c.
Consequences of c = 0.7931:
| pump.fun | RHUB | |
|---|---|---|
| price rise across the curve | 14.7x | 2.25x |
| first 10% of the money takes | 29.9% of curve supply | 14.3% |
| graduation FDV | 410.9 SOL | 172,500 ARB |
That 30% is the number ../launchpad/STATE.md says RHUB deliberately rejected. It is a product
decision wearing a parameter's clothes.
Fees
| rate | split | |
|---|---|---|
| Bonding curve | 1.25% | creator 0.300% / protocol 0.95% / LP 0% |
| Graduation | 0.015 SOL | protocol |
| PumpSwap canonical pool | tiered by market cap, 1.25% → 0.30% | at the bottom tier: creator 0.300 / protocol 0.930 / LP 0.020 |
| PumpSwap non-canonical pool | 0.30% | creator 0% / protocol 0.05% / LP 0.25% |
The tiering is worth noting: creator fee falls as market cap rises (0.300% → 0.050%), and LP fee rises. Early creators are paid to get a coin moving; mature coins pay their liquidity instead.
What is actually worth copying
- Fees outside the invariant. We already do this.
- One cheap per-launch state object, not a deployed stack.
- Fee rates in a separate, replaceable component. That is
FeeVault.strategy's cousin. - Graduation triggered by supply sold out, not by a market-cap oracle. No off-chain input.
What is not
c = 0.79. It is the extractive end of the family and we have already argued against it.- Protocol-owned graduated pool with no locked LP. pons locks; we lock (RHUB's curve holds the
position and cannot withdraw principal —
liquidityDeltahardcoded to zero).