Reference document, written for a non-engineer reader who can follow a formula. Source of truth: core/src/lib.rs (the code is authoritative, this document explains it) and core/src/tests.rs (what is proven). Date: 2026-10-09. Status: program not deployed.
Two sentences carry the product. They live in config/brand.ts and must not be reworded:
The pump pays you, even if you never sell. And once acquired, nothing can take it back.
This document explains exactly what these two sentences mean, and nothing more.
Vocabulary: throughout this document, "token" means the smallest unit of the token (with 6 decimals, 1 displayed token = 1,000,000 units). "Lamport" is the smallest unit of SOL (1 SOL = 1,000,000,000 lamports).
1. What the ratchet does in 5 lines
- Each launch has a curve that sells tokens. The program counts how many tokens have left the curve: that is
sold. It also remembers the highest levelsoldhas ever reached: that ishigh_water. - When a buy pushes
soldabovehigh_water, a share of that buy's fee (30% of the fee on the new ground) is credited to the holders who held tokens before that buy. - This credit is recorded in a per-token counter,
acc_per_token, which only ever goes up. Nobody, and no instruction, can make it go down. - A sell lowers
sold, but touches neitherhigh_water, noracc_per_token, nor anything already credited to anyone. - The credited lamports sit in a reserve that only the holder can empty, to their own wallet, at any time, with no fee, forever.
2. The state
Per launch (Launch account)
| Field | Type | What it is |
|---|---|---|
curve_supply | 64-bit integer | Total number of tokens the curve can sell before graduation. |
sold | 64-bit integer | Tokens currently out of the curve. Goes up on a buy, down on a sell. |
high_water | 64-bit integer | The highest sold ever reached. Never goes down. |
acc_per_token | 128-bit integer, fixed point | Lamports credited per token held, multiplied by 10^12 (SCALE). Never goes down. |
carry | 128-bit integer | The remainder of the division of the last credit, carried over to the next credit. Never thrown away. |
reserve_in | 64-bit integer | Total lamports that have ever entered the ratchet reserve. |
reserve_claimed | 64-bit integer | Total lamports that have ever been claimed out of the reserve. |
clicks | 64-bit integer | Number of new highs (display only). |
frozen_at_graduation | boolean | True after graduation. No more credit after that. Claims stay open. |
pool | address | The Raydium CP-Swap pool opened by migrate (§9). All zero before that. |
Ratchet balance of the reserve = reserve_in − reserve_claimed. On top of this, the reserve account (an address belonging to the program) also holds a fixed rent floor: at create_launch the program tops the reserve account (and the curve's SOL account) up to the rent-exempt minimum of an empty Solana account (890,880 lamports today), paid by the launch creator. That floor is never counted in reserve_in and is not claimable by anyone. So the SOL the reserve account must contain is: rent floor + reserve_in − reserve_claimed.
Per holder (Holder account, one per launch/wallet pair)
| Field | What it is |
|---|---|
balance_tracked | Tokens bought on the curve and not sold back. During the curve the tokens are held in escrow in the program's vault, so this number is the balance. |
debt | The value of acc_per_token at this holder's last settlement. |
credited | Lamports acquired and not yet claimed. Only settlement increases it; only a claim resets it to zero. Selling does not touch it. |
claimed_total | Total claimed over the holder's lifetime (display). |
withdrawn | True once the tokens have been withdrawn from escrow after graduation. |
The constants (fixed in the program, no instruction changes them)
| Constant | Value | Meaning |
|---|---|---|
TRADE_FEE_BPS | 100 | Trading fee: 1.00% of the SOL amount of every buy and every sell. This is the standard market fee; the ratchet redistributes a share of it, it does not add to it. |
RATCHET_BPS | 3,000 | Share of the fee on new ground that goes to the ratchet: 30%. |
CREATOR_FEE_BPS | 5,000 | Share of the remainder that goes to the creator: 50%. The platform receives the rest. |
SCALE | 10^12 | Precision of acc_per_token. |
3. The accumulation formula (what a buy does)
A buy of n tokens with a total fee fee (in lamports) does the following, in this order:
circulating_before = sold (the tokens already held by others)
new_sold = sold + n
if new_sold > high_water : (there is new ground)
new_ground = new_sold − high_water
if circulating_before > 0 :
fee_on_new_ground = fee × new_ground / n (pro rata of the buy)
ratchet_share = fee_on_new_ground × 3,000 / 10,000 (30%)
numerator = ratchet_share × 10^12 + carry
acc_per_token = acc_per_token + (numerator ÷ circulating_before) (integer division)
carry = numerator modulo circulating_before (the remainder, kept)
reserve_in = reserve_in + ratchet_share
high_water = new_sold
clicks = clicks + 1
sold = new_sold
remainder = fee − ratchet_share
creator = remainder × 5,000 / 10,000
platform = remainder − creator
Three points to remember:
- Only new ground counts. If
new_solddoes not exceedhigh_water,ratchet_share = 0and the whole fee goes to creator/platform. - The credit goes to the tokens that were there before. The divisor is
circulating_before, notnew_sold. Thentokens that have just been bought receive nothing from their own buy. - Nothing is lost in the division. The remainder goes into
carryand will be added to the numerator of the next high.
One exception on the creator and platform shares, in the on-chain program: a creator or platform share is paid only if the receiving wallet ends up at or above the Solana rent-exempt minimum. If a share would leave that wallet below it (for example, a wallet emptied to 0 lamports receiving a small share), that share is kept by the trader: on a buy it is not charged, on a sell it is paid to the seller. This exists so that a fee wallet can never block a trade. The ratchet share is not affected.
Worked example
Before the buy: sold = 1,500,000, high_water = 2,000,000, acc_per_token = 0, carry = 0. (Someone has sold since the last high: sold has gone back down below high_water.)
A buyer buys n = 1,000,000 tokens for 2,000,000,000 lamports (2 SOL). Fee: 1% = fee = 20,000,000 lamports.
new_sold = 1,500,000 + 1,000,000 = 2,500,000 > 2,000,000 : new ground
new_ground = 2,500,000 − 2,000,000 = 500,000 (only half of the buy)
fee_on_new_ground = 20,000,000 × 500,000 / 1,000,000 = 10,000,000 lamports
ratchet_share = 10,000,000 × 3,000 / 10,000 = 3,000,000 lamports → reserve
numerator = 3,000,000 × 10^12 + 0 = 3 × 10^18
acc_per_token = 0 + 3 × 10^18 ÷ 1,500,000 = 2,000,000,000,000 (i.e. 2 lamports per token)
carry = 3 × 10^18 mod 1,500,000 = 0
high_water = 2,500,000 ; sold = 2,500,000 ; clicks + 1
remainder = 20,000,000 − 3,000,000 = 17,000,000
creator = 8,500,000 ; platform = 8,500,000
The 1,500,000 tokens that were held before this buy are now credited with 2 lamports each. The buyer's 1,000,000 tokens: nothing, for this buy.
The same example with a remainder (carry)
If circulating_before had been 1,400,000 instead of 1,500,000:
3 × 10^18 ÷ 1,400,000 = 2,142,857,142,857 remainder 200,000
acc_per_token += 2,142,857,142,857 (≈ 2.142857 lamports per token)
carry = 200,000 (in units of 10^-12 lamport: 0.0000002 lamport in total)
This remainder of 200,000 will be added to the numerator of the next high. It is not thrown away. It represents less than one lamport in total, but the rule is: nothing is thrown away.
4. The settlement formula (settle)
Settlement turns the rise of acc_per_token into concrete lamports for a holder. It is a single internal function, called first by every instruction (buy, sell, claim, graduation/withdrawal). There is no path that changes a holder's balance without settling it first.
delta = acc_per_token − debt (cannot be negative: acc never goes down)
pending = balance_tracked × delta ÷ 10^12 (integer division)
credited = credited + pending
debt = acc_per_token
Calling settle twice in a row gives 0 the second time: delta = 0. It is idempotent.
Worked example
Take the example from §3: acc_per_token went from 0 to 2,000,000,000,000.
A holder holds balance_tracked = 300,000 tokens, last settled when acc_per_token was 0 (debt = 0).
delta = 2,000,000,000,000 − 0 = 2,000,000,000,000
pending = 300,000 × 2,000,000,000,000 ÷ 10^12 = 600,000 lamports
credited = 0 + 600,000
debt = 2,000,000,000,000
This holder has 600,000 lamports acquired. They can claim them now or in three years; it is the same number.
Example of rounding down
With the carry variant from §3 (delta = 2,142,857,142,857) and a holder of 7 tokens:
pending = 7 × 2,142,857,142,857 ÷ 10^12 = 14,999,999,999,999 ÷ 10^12 = 14 lamports (not 15)
Rounding is always down for the holder. The fraction of a lamport stays in the reserve. It is claimable by nobody: not by the holder, not by the creator, not by the platform. See SECURITY.md, section "Arithmetic".
5. The monotonicity invariant and why it holds
The claim: acc_per_token never goes down, high_water never goes down, credited only goes down when the holder claims it themselves.
Why this is true, instruction by instruction:
| Instruction | high_water | acc_per_token | credited (of a holder) |
|---|---|---|---|
| buy | goes up if new ground, otherwise unchanged | goes up if new ground and circulating > 0, otherwise unchanged | goes up (settlement), never goes down |
| sell | unchanged | unchanged | goes up (settlement), never goes down |
| claim | unchanged | unchanged | goes up (settlement) then set to zero and paid to the holder |
graduation (migrate) | unchanged | unchanged | unchanged |
| post-graduation withdrawal | unchanged | unchanged | goes up (settlement), never goes down |
In the code, the only line that writes acc_per_token is an addition. The only line that writes high_water is high_water = new_sold inside an if new_sold > high_water. The only line that writes credited downward is credited = 0 in the claim, after paying exactly that amount to the holder. There is no administration instruction: nothing can decrement these fields, reset them to zero, or freeze them other than graduation.
What is proven by the tests (core/src/tests.rs): the invariant is checked after every operation over 10,000 random adversarial sequences (prop_monotone_10k, up to 60 operations each, including full sells, round trips, buys exactly at the high, buys one token above the high, bundles of 30 buys, claims, graduation, exhaustion of the curve) and over four sequences of 5,000 operations (adversarial_long_sequences).
Full-sell test (sell_everything_keeps_credit_and_claim_still_works): a holder accumulates credit, sells 100% of their position, then everyone sells 99% of the rest. Their credited has not moved by a single lamport. They claim: they receive exactly that amount. They claim a second time: 0, with no error.
This is the exact meaning of "once acquired, nothing can take it back".
6. Why wash trading brings nothing
The ratchet does not look at volume. It only looks at whether sold goes above its all-time maximum. Buying then selling back brings sold back to the same point: the second buy crosses no new ground.
The test wash_trading_1000_round_trips_earns_nothing_beyond_new_ground:
- Two holders A and B each hold 10,000 tokens.
high_water = 20,000. - A wash trader makes 1,000 round trips: buys 5,000 tokens, sells 5,000 tokens back, with a fee of 50,000 lamports on every buy and every sell.
- Total fees paid by the wash trader: 2,000 × 50,000 = 100,000,000 lamports.
- What entered the ratchet reserve: 15,000 lamports, all of it on the first trip (5,000 tokens of new ground × 100% of the buy × 30% of 50,000). The other 999 trips: new ground = 0, credit = 0,
acc_per_tokenunchanged.
In other words: 0.015% of the wash-trading fees fed the ratchet, and only because the first buy was a real new high. The wash trader paid 100 million lamports in fees to credit 15,000 lamports to the other holders, and nothing to themselves (their tokens were not there before their own buy).
Wash trading does not "pump" the ratchet. On a buy that crosses no new ground, and on every sell, the whole fee goes to the creator and the platform: the wash trader only pays them fees. In the test above, out of 100,000,000 lamports of fees, only 15,000 (the new ground of the first round trip) went to the ratchet, and all the rest went to the creator and the platform.
7. Same slot, bundles
On Solana several transactions can be executed in the same slot, or even grouped together. This changes nothing: the program executes the buys one after the other and each buy sees the state left by the previous one.
Test bundle_of_30_buys_crosses_ground_once: high_water = 100,000, sold has gone back down to 40,000. A bundle of 30 buys of 4,000 tokens (120,000 in total) brings sold up to 160,000.
- The first 15 buys (40,000 → 100,000) cross no new ground: 0 credit.
- The next 15 (100,000 → 160,000) cross 60,000 tokens of new ground, only once, in 15 pieces of 4,000.
- Sum of new ground = 60,000 =
160,000 − 100,000. Not 120,000. Not twice 60,000. - With 1,000 lamports of fee per token: reserve = 60,000 × 1,000 × 30% = 18,000,000 lamports.
Test bundle_vs_single_buy_same_ground_same_reserve: 30 small buys covering the same ground as a single large buy put the same lamports into the reserve, up to rounding (at most 1 lamport of difference per buy).
A buyer who splits their buy credits neither more nor less. A buyer who places themselves just before a large buy in the same slot is treated exactly like someone who had held their tokens from the start: the test sniper_earns_exactly_holding_period checks that a "sniper" who enters just before a high and exits just after is credited the same amount as a long-term holder, for that event, neither more nor less. The ratchet pays for holding at the moment of the high, nothing else.
8. First buyer
On the very first buy, circulating_before = 0: nobody held anything before. The program credits nobody and performs no division (no division by zero). The whole fee goes to creator/platform. high_water takes the value of this buy.
Test first_buyer_credits_nobody_no_div_by_zero: reserve = 0, acc_per_token = 0, high_water = n, creator + platform = total fee.
The first buyer is not credited for their own buy. They will be credited starting from the second buy that goes beyond theirs, like everyone else.
9. Graduation and lazy settlement
Graduation is the migrate instruction. Anyone can call it, with no arguments, once the curve is fully sold (sold >= curve_supply, otherwise CurveNotComplete). In one atomic instruction it:
- sets
frozen_at_graduation = true; - moves the 206.9M tokens never sold (
TOTAL_SUPPLY − sold) and the curve's SOL, minusMIGRATION_OVERHEAD(0.25 SOL, which pays Raydium's 0.15 SOL create-pool fee and the rent of the pool's accounts), into a new Raydium CP-Swap pool (program and 0.25% fee tier fixed in the program); - burns every LP token it receives: nobody can withdraw that pool's liquidity;
- closes the temporary accounts (their rent goes back to whoever paid it) and sends what is left of the 0.25 SOL plus the curve account's remaining lamports to the launch creator. The curve account ends at 0 lamports. The pool's address is recorded in
Launch.pool.
The pool opens at the last curve price, to within about 0.3% (the effect of holding back 0.25 SOL). Until migrate succeeds, the curve stays open for sells: there is no state where the SOL is stuck and the exit is closed. If the call into Raydium fails, the whole instruction is reverted and nothing has changed.
From then on:
- no more buys or sells on the curve (error
Frozen); acc_per_token,high_water,carryandreserve_innever change again;- claims and token withdrawal remain available, with no time limit.
The program does not "settle" every holder at graduation. It does not need to. Since acc_per_token is constant after the freeze, settling a holder will give exactly the same delta, and therefore exactly the same lamports, whether it is done in the second of graduation or months later. This is what is called lazy settlement: it happens when the holder shows up.
Test graduation_lazy_settle_is_exact: 50 holders, 2,000 random operations, graduation. Each holder's settlement is computed at the moment of graduation (the "eager" version) and compared with the settlement done later on the live state (the "lazy" version). The 50 values are identical to the lamport.
Test graduation_freezes_exactly_and_claims_forever: after graduation, buy and sell fail, a second graduation fails, acc_per_token and reserve_in have not moved, claims work, token withdrawal works, and when everyone has claimed at most 2 lamports of dust remain in the reserve (in the accounting; on-chain, the reserve account also still holds its rent floor from §2, which belongs to nobody's credit).
On-chain test graduation_boundary_and_claim_forever (the built program, next to the real Raydium CP-Swap mainnet program): migrate called by an arbitrary wallet, the pool holds the curve's SOL minus the overhead and the 206.9M tokens, the LP is burned, the curve account is empty, the caller pays only the transaction fee, then withdrawn tokens are sold into the Raydium pool. Test migrate_guards: migrate too early or with another fee tier fails, and a sell is still possible on a full curve as long as migrate has not happened.
Sentence from brand.ts: "The ratchet runs during the curve. After graduation it stops, and what you acquired stays yours."
10. Claiming
The claim (claim):
- settles the holder (§4);
- pays
creditedlamports from the reserve to the holder's wallet, and to that wallet only; - resets
creditedto 0, incrementsclaimed_totalandreserve_claimed.
Zero fee taken by the program (the Solana network charges its own transaction fees; the program adds nothing). No access control: any holder, at any time, before or after graduation. No pause: there is no pause instruction in the program. Claiming while credited = 0 returns 0 and causes no error.
The program does not know the time. There is no deadline, no expiry, no "claim before". This cannot change: there is no time field in the state.
11. Token escrow during the curve and withdraw_frozen
During the curve, bought tokens are not sent to the buyer's wallet. They stay in a vault belonging to the program, and the Holder account records balance_tracked. This number is what settlement uses.
Why: if tokens circulated freely during the curve, the program would have to follow every transfer (via a "transfer hook") to know who holds what, and any tracking error would distort the credits. With escrow, the tracked balance is the real balance, by construction. No hook, no drift.
Consequence: during the curve, the tokens are not visible in the wallet, and cannot be transferred out of the program. They can be sold on the curve (sell), and that is all.
After migrate, the holder calls withdraw_frozen:
- settles the holder (the credit is kept);
- transfers
balance_trackedtokens from the vault to the holder's token account; - sets
balance_tracked = 0andwithdrawn = true.
They can then trade their tokens on the Raydium pool. Their credit remains claimable after the withdrawal (test settle_first_graduate_withdraw and withdraw_requires_graduation_and_keeps_credit). Calling withdraw_frozen before graduation fails (NotGraduated), and so does calling it before the pool exists (NotMigrated): no token leaves escrow before migrate, so nobody can open a competing pool at another price before it.
After the withdrawal, the program no longer follows these tokens, and there is nothing left to follow: the ratchet has stopped.
12. The fee split in bps
Three numbers, displayed on each token's page, fixed at launch, identical for all launches of this version of the program:
| Displayed | Value | On what |
|---|---|---|
| Trading fee | 100 bps (1.00%) | The SOL amount of every buy and every sell. |
| Ratchet share | 3,000 bps (30%) | Of the fee on the new ground of a buy. |
| Creator share | 5,000 bps (50%) | Of the remainder of the fee after the ratchet share. The platform gets the rest. |
What this means in practice, relative to the amount of a buy:
| Situation | Ratchet | Creator | Platform |
|---|---|---|---|
| The buy is 100% new ground | 30 bps | 35 bps | 35 bps |
| The buy is 50% new ground (example from §3) | 15 bps | 42.5 bps | 42.5 bps |
| No new ground, or any sell | 0 bps | 50 bps | 50 bps |
The ratchet does not add to the 1% fee. It is a share of it. On a buy with no new ground, the fee is the same and goes entirely to creator/platform.
(As stated in §3: if a creator or platform share would leave the receiving wallet below the Solana rent-exempt minimum, that share is not paid to it and stays with the trader. The ratchet column is never affected.)
13. What the program does NOT know
This must be said as clearly as the rest.
- The price. There is no price in the program. No oracle, no price feed, no average. The "high" is the maximum of
sold, an integer the program owns itself. A new high ofsoldis not a new high of the price in SOL, let alone in dollars. - Time. There is no clock in the state. The program does not know how long you have held, nor what time it is. That is why claims never expire, and also why there is no bonus for holding longer.
- Who holds after graduation. Once the tokens are withdrawn from escrow, they circulate freely and the program no longer sees them. It does not try to see them: the ratchet has stopped.
- Who you are. No list, no identity check, no wallet privilege. The launch creator has no power over the ratchet; they receive their share of the fee, and that is all.
- What the token is worth. The program redistributes a share of a fee in lamports. It does not know, and cannot know, whether the token itself is worth anything. See
docs/RISKS.md.