01 — Overview
The contracts, and how a pool is oriented
Each chain runs one hook contract, and it serves every launch on that chain. Each launch has its own Uniswap v4 pool, and its own vault for that launch’s ETH and tokens. The hook keeps each launch’s accounting under that pool’s id.
In every pool, native ETH is currency0 and the launch token is currency1. The orientation block below the contract list shows what that means for tick direction.
The hook is an OpenZeppelin uniswap-hooks BaseHook. It takes the beforeInitialize permission at pool creation. On each swap it takes beforeSwap and afterSwap. Both may return a delta, through beforeSwapReturnDelta and afterSwapReturnDelta. It takes no liquidity or donate permissions. An approved factory calls registerPool(key, config, launch, platformPool) once per launch. That call deploys the pool’s FloorPoolVault and writes its Config. Nothing can rewrite the platformVault, the creator, any skim rate, the creator’s rates or the holder tax. No setter exists for any of them. Every per-pool read and write goes through execute(poolId, calldata). The hook delegates it to SingletonFloorEngine or SingletonFloorViews. One call to poolState(poolId) returns the stored state as one struct. The hook is deployed directly, with no proxy or beacon, so its code cannot be upgraded. It has no admin and no withdraw function. The vaults it deploys are beacon proxies (row 02).
bindPool once per pool, by its sale,
DYNAMIC_FEE_FLAG, currency0 == 0
registerPool deploys it as a BeaconProxy at a CREATE3 address salted by the pool id. The same call initialises it with its hook, pool id and assets. Skim, fees and closed positions go straight into it, and settlement pays out of it. Only its own hook can ask it to pay. A payment can never draw on another launch’s vault. The vault has no owner and no sweep. Its code cannot change. Every vault on the chain reads one FloorPoolVaultBeacon, the hook’s immutable vaultBeacon. That beacon has no owner and no upgrade function, and its implementation is fixed when it is deployed.
poolState(poolId).custodyVault
hook.vaultBeacon()
A pure library. Its helpers are sqrtPriceX96FromRatio, floorTick and askTick, with the rounding pair _ceilToSpacing / _floorToSpacing. It defines the constant TICKS_PER_DOUBLING = 6932. The table in 02 gives each helper’s rounding and guards.
orientation note lives here
TOTAL_SUPPLY = 1_000_000_000e18 at 18 decimals, minted once, straight to the sale. The token has no mint function and no transfer tax. It is deployed behind an upgradeable proxy whose admin is the deployment’s upgrade owner. It has three optional extras. bindRewards() links it to the chain’s FloorHolderRewards. The deployer calls it once, on a launch with a holder tax. After that, transfer and transferFrom notify the rewards contract. burn(amount) destroys the caller’s own tokens. bindLaunch(), called once by the deployer, names the one sale that may move the token while it is locked. For anyone else, transfer, transferFrom and burn then revert with Locked. The lock lasts until that sale calls unlock() at graduation. While the token is locked, sellBack(amount) is the exit. It moves the caller’s own balance to the sale and tells the sale to pay. There is no pull form, so nothing can move a balance its holder did not authorise.
The factory mints 100% of supply to the sale before the sale exists. buy() takes the quote asset and hands the buyer their tokens in the same call, so there is no claim step. Until graduation, FloorToken.sellBack() returns the seller’s cost basis less the sale’s LODE Platform fee. Each buy pays that fee too, on top of the sale price, and the sale holds it apart from the raise. Before any seeding moves a token, graduate() releases the token’s sale lock. It initializes the pool, binds it on the hook, seeds the floor, POL and staircase, and calls ratchet(). The sale has no deadline. It graduates when it sells out. Each sale is a BeaconProxy, and every sale on the chain reads one UpgradeableBeacon. The deployment’s upgrade owner can point that beacon at new code.
founder allocation 0 on every launch
A pure library that holds no state and reads no oracle. The launchpad calls it at deploy time. It exposes preset(Mode) and hookConfig(Mode, liftMaxBps, platformVault, creator). It also exposes tranchePriceFor(mcapUsd, ethUsd, totalSupply). The enum has three modes: Meme, Bluechip and Custom.
One contract keeps a per-share accumulator for every launch on the chain. Each token calls onTransfer before every balance change. The contract holds no money. Each launch’s holder tax waits in that launch’s own vault. claim(token) has the engine pay what the caller’s balance earned, capped by what that pool accrued. claimMany and claimAll do the same for several launches in one transaction. Protocol addresses are excluded when a launch registers. The contract sits behind a TransparentUpgradeableProxy. Its ProxyAdmin is owned by the deployment’s upgrade owner, who can replace the implementation.
ProxyAdmin → the upgrade owner
see 12
lock(token, beneficiary, amount, cliff, duration) records an immutable schedule. claim(id) pays only the beneficiary. A lock cannot be revoked or released early.
Orientation (read before touching any sign)
currency0 = native ETH (address(0)), currency1 = LODE pool price = token1 / token0 = TOKEN per ETH P_eth = 1 / poolPrice higher tick == more TOKEN per ETH == CHEAPER token "floor up" == floorTick DOWN bid (all ETH) sits ABOVE the current tick ask (all TOK) sits BELOW the current tick hard ordering: askTick < currentTick < floorTick
Pool state that matters · poolState(poolId)
02 — Floor math
Floor = backing ÷ circulating supply
The floor comes from the pool’s backing divided by the tokens that could be sold into it. Backing, Q, is the pool’s ETH: what sits idle in its vault plus what is inside the bid. S counts only tokens that could actually be sold into the bid. The hook solves for the highest price at which Q buys every one of those tokens. It publishes the floor one narrow band, about 1.2%, below that price.
In pool state, Q is vaultEth + bidEthDeployed. S leaves out the vault’s inventory, the staircase’s unsold tokens and the tokens the protocol-owned position holds at the floor price.
// backing per circulating token F = Q / S_circ // the same ratio, two readings floor / price = backing / mcap // selling q ETH into the bid removes q/F tokens F' = (Q − q) / (S − q/F) = (Q − q) / (S·(Q − q)/Q) = Q / S = F // invariant under own fills // bid capacity in tokens: the whole circulating supply Q / F = S_circ // where step n of the staircase starts selling Step(n) = open × 2^n
F is the price at the bid band’s dear edge. The published floor, floorTick, is one band cheaper. The band is BID_BAND_TICKS = 120 ticks, rounded up to the spacing: about 1.2% in price (see 04 and 05). The floor rises only from skim, ask proceeds, staircase proceeds and seed-fee sweeps. A fill of the bid itself leaves it unchanged.
Every launch sells its reserve on a staircase: fixed token-only steps, each one doubling of the price. A preset’s steps run from the graduation market cap to about $1B, and $LODE’s from its open to about $2.6B. A Custom launch takes one step for each doubling from its graduation market cap to about $1B, at most 16, each holding the same tokens. At each ratchet the money the steps took is split between the floor and the protocol-owned position (see 04 and 11, and 15 for measured figures).
The hook takes its fee in ETH only. A fee worth V taken as ETH gives F = (Q+V)/S. Taken as tokens and retired, it gives F = Q/(S − V/P). The second is larger only when Q + V > S·P, which means backing above market cap. That does not hold while the pool trades.
// what the bid must cover sellable(F) = totalSupply − inventory − steps − T_pol(F) // T_pol(F): tokens the protocol-owned position holds at the // floor price. A concentrated position's composition is a // pure function of price, so this is exact, not a bound. polTokensAtTick(t) = getAmount1Delta(sa, min(sp, sb), seedLiq, false) // the dear edge is the highest F with F · sellable(F) <= Q // F on both sides: a fixed point, bisected in tick space _solveFloorTick(q): hi = ceil(MAX_TICK), lo = ceil(MIN_TICK) if sellable(lo) < MIN_SELLABLE return floorTick − W // the dear edge, unchanged if cost(hi) > q return hi while hi − lo > tickSpacing: mid = ceilToSpacing(lo + (hi − lo)/2) cost(mid) <= q ? hi = mid : lo = mid return hi cost(t) = _costAtTick(sellable(t), t) = tokens · 2^192 / sqrtP(t)^2 // what is published is the band's cheap edge, W = ceilToSpacing(BID_BAND_TICKS) _publish(solved) = ceilToSpacing(solved + W)
| FloorMath helper | Does | Rounding / guard |
|---|---|---|
| TICKS_PER_DOUBLING | 6932 = ln(2)/ln(1.0001); ticks spanned by a 2× move in ETH per token | subtract from floorTick to get a 2× ask |
| sqrtPriceX96FromRatio(ethWei, tokenWei) | sqrt(tokenWei · 2^96 / ethWei) << 48, staying inside uint256 | tokenWei == 0 reverts ZeroDenominator; ethWei == 0 returns MAX_SQRT_PRICE − 1; clamped to [MIN_SQRT_PRICE, MAX_SQRT_PRICE − 1] |
| floorTick(quoteWei, circ, spacing) | tick of Q/S, rounded conservatively | _ceilToSpacing: rounds the tick up = cheaper token = understated floor. Under-stating is safe (the bid absorbs more than full supply); over-stating would break redemption |
| askTick(cost, tokens, multipleBps, floorTick, minSpread, spacing) | min(byCostBasis, floorTick − minSpread) in tick terms, i.e. the higher ask | empty inventory or zero cost returns the floor-derived ask; constraint 2 dominates as the floor ratchets past old lots |
| _ceilToSpacing / _floorToSpacing | round to the next / previous multiple of tickSpacing | clamped one spacing inside MAX_TICK / MIN_TICK |
03 — Fee and skim schedule
How a swap is charged: the LP fee and the skim
A trader pays five things on a swap: the 0.25% LP fee, the floor skim, the creator fee, the holder tax and the LODE Platform fee. This section covers the first two, and 06 lists them all. The skim is taken from the ETH side of the trade and goes to the launch’s vault, less the $LODE cut. Its rate ramps with the price’s distance from the floor. A buy’s skim falls to zero at the floor and a sell’s rises to 1.5× its far rate on a preset and on $LODE. A Custom launch picks its own multiple, 1× to 5×.
The pool is created with DYNAMIC_FEE_FLAG. On every swap the hook overrides the fee with LP_FEE | OVERRIDE_FEE_FLAG. Each pool has four skim rates: far from the floor and at it, on each side. They are written when the pool is registered, and nothing can change them after that. The ramp’s width is the same for every launch, and it is measured to the bid band’s dear edge. The LODE Platform fee is taken in the same step as the skim, at the pool’s own flat rate: 0.25% today, never above 0.5%, and 0 allowed (see 08).
LP_FEE
2500
hundredths of a bip = 0.25%, flat
skimBuyFarBps → skimBuyAtFloorBps
≤ 1000 → 0
bps of the ETH leg, per pool (modes: 150 / 200 far; 0 at the floor, so buys ramp to 0% skim)
skimSellFarBps → skimSellAtFloorBps
≤ 1000 → ≤ 1500
bps, per pool (presets: 200 far, 1.5× at the floor; Custom picks 1× to 5×, and a sell at the floor never pays more than 15%)
SKIM_RAMP_TICKS
16094
≈ 5× in price; ramp width above the band’s dear edge
_skimBps(zeroForOne): distance = (floorTick − bidWidth) − currentTick // to the DEAR edge; ≤ 0 inside the band closeness = distance <= 0 ? 10_000 : distance >= RAMP_TICKS ? 0 : 10_000 − distance · 10_000 / RAMP_TICKS buy (zeroForOne): buyFar − (buyFar − buyAtFloor) · closeness / 10_000 // or + if buyAtFloor > buyFar sell (!zeroForOne): sellFar + (sellAtFloor − sellFar) · closeness / 10_000 // flat if sellFar ≥ sellAtFloor fee = ethLeg · bps / 10_000 // floor skim → vault (less the $LODE cut) cfee = ethLeg · creatorBps(dir) / 10_000 // creator fee → creator (see 09) tfee = ethLeg · teamFeeBps / 10_000 // LODE Platform fee, the pool's own rate → teamFeesOwed (see 08) poolManager.take(currency0, custodyVault, fee + cfee + tfee) vaultEth += _intake(fee); unpaidSkim += kept; creatorFeesOwed += cfee; teamFeesOwed += tfee
cumulativeVolumeEth adds the ETH leg of every swap, skimmed or not. A 0%-skim buy at the floor still counts. The hook’s own nudges are swaps with sender == address(this). They pay the LP fee, but no skim, and add no volume. The nudges are the re-anchor inside a sell and the ratchet’s dust crossing (see 05). custodyVault is the launch’s own FloorPoolVault. The hook takes every fee straight into it and holds none itself.
// ETH is the SPECIFIED currency exactly when
_ethIsSpecified(p) = p.zeroForOne == (p.amountSpecified < 0)
One boolean decides which callback skims. When ETH is the specified currency, the fee is returned through BeforeSwapDelta. In the other two cases, afterSwap takes it from the unspecified leg and returns it as the hook delta.
| Case | zeroForOne | amountSpecified | ETH leg | Skimmed in |
|---|---|---|---|---|
| Buy, exact in | true | < 0 | specified (ETH in) | beforeSwap · BeforeSwapDelta(+fee, 0) |
| Sell, exact out | false | > 0 | specified (ETH out) | beforeSwap · BeforeSwapDelta(+fee, 0) |
| Buy, exact out | true | > 0 | unspecified (ETH in) = delta.amount0() | afterSwap · hookDelta = fee |
| Sell, exact in | false | < 0 | unspecified (ETH out) = delta.amount0() | afterSwap · hookDelta = fee |
04 — Positions
The four positions the hook owns in each pool
The hook holds four kinds of liquidity position in every launch’s pool. The bid holds the vault’s ETH and buys tokens at the floor. The protocol-owned position and the staircase sell tokens as the price rises. The ask re-sells the tokens the vault bought, at twice their cost or more.
Every modifyLiquidity call runs inside unlockCallback, with an action code for the ratchet, the seed or the staircase. The pool id rides at the end of the callback data. That lets one hook own positions in every launch’s pool without two launches sharing a position. Each position has its own salt.
The range is [floorTick − W, floorTick], with W = _ceilToSpacing(BID_BAND_TICKS = 120). That is 120 at spacing 60, about 1.2% in price. floorTick marks the band’s cheap edge: the lowest price a sell into the bid can receive. The dear edge, bidLower = floorTick − W, is where the backing solves and where a sell fills first. Read it with bidRawQuotePerToken. A partial fill leaves the market inside the band. The re-place then keeps only the part still above the market, so the band narrows from the dear side: lower = max(floorTick − W, _ceilToSpacing(current + 1)). The cheap edge does not move, so sells do not walk the band down one spacing at a time. The band’s token capacity is Q / geomean(edges) > sellable, so no sequence of sells carries the price through it. It falls back to one spacing above market only when the whole band is behind the market. That happens once the sellable float is absorbed, or for a pool that arrived in a gap. _liqForAmount0(sa, sb, vaultEth) sizes it, and it is skipped below MIN_BID_ETH = 0.001 ether. bidWidth records the placed width. A bid placed before the band existed has a width of 0, read as one spacing.
teardown: spent = bidEthDeployed − ethBack
inventoryTokens += tokBack
inventoryCostEth += spent
seedLiquidity(tickLower, tickUpper, tokenAmount) is payable and permissionless. The first call fixes the range, and a later call with another range reverts SeedRangeFixed. Ticks must be spacing-aligned. FloorLaunch sets lower = _ceilToSpacing(TickMath.MIN_TICK), which is v4’s minUsableTick (−887220 at spacing 60). It sets upper = _floorToSpacing(open), so upper ≤ current and the position is 100% tokens. That gives buy-side depth at every price above the open. The tail has constant liquidity: it thins as price rises but never runs out. The ETH a buy leaves in it is reversible, because it pays sellers on the way down. That ETH is not backing. No code path removes the position. Each ratchet raises its lowest-price edge to the bid band’s dear edge (raisePol), so nothing of the protocol’s ever sells inside the band. Each ratchet, _sweepSeedFees also does a zero-delta modifyLiquidity. ETH fees go to vaultEth, and token fees go to inventory at zero basis.
fees swept to seedFeesSweptEth / Tokens
The range is [at − RECYCLING_WIDTH_TICKS, at]. The top, at, starts as FloorMath.askTick(inventoryCostEth, inventoryTokens, ASK_MULTIPLE_BPS, floorTick, MIN_ASK_SPREAD_TICKS, tickSpacing). Then at = min(at, _floorToSpacing(current)), so an ask the market has already passed moves up to market instead of sitting idle. The ask is deployed only if current >= upper. With MIN_ASK_SPREAD_TICKS = TICKS_PER_DOUBLING, the ask never sits within 2× of the floor. The vault buys at or below the floor, so the band normally runs 2× → 8× of the floor. The multiple is fixed and does not move with cumulative volume. If at − RECYCLING_WIDTH_TICKS would pass MIN_TICK, the inventory stays idle and the band is not narrowed. At teardown, tokBack >= deployed is fee income, joining inventory at zero basis. Otherwise the sold share retires basis pro rata. Either way, inventory ends at before − deployed + returned.
RECYCLING_WIDTH_TICKS 13_862 (4×)
→ 13_920 at spacing 60
askWidth records the placed width
On Cook, Bluechip and Moonshot, 69% of supply sits in the steps. Graduation places them from the graduation market cap up to about a $1B market cap, and 1% of supply as an open tail above them. On Moonshot each step holds the same number of tokens. On Cook and Bluechip each step up holds 1.04× the tokens of the one below it. The steps never move. Because every doubling sells about the same number of tokens for twice the money, the money the steps take grows with the market cap. At each ratchet the hook takes out what the steps sold and splits it by two numbers: the floor over the price, with a target of 20%, and the protocol-owned position’s money over the market cap, with a target of 15%. Each gets a share in proportion to how far it is short of its target. When both are met, all of it goes to the floor. The protocol-owned position’s share is placed as bids from 90% of the price up to the price, and it follows the price up at later ratchets. It is never swept to the floor. The $LODE cut applies to what reaches the vault. The tokens the vault buys at the floor join the step just above the price, at no less than twice what it paid. Their money goes through the same split when they sell. A Custom launch’s steps hold its supply less its sale, its protocol-owned position and the 1% open tail. They run from its graduation market cap toward about a $1B market cap, one step for each doubling, at most 16, and each step holds the same number of tokens. With its default 30 / 10 / 60 split, a Custom launch softens a 3% sell about as the presets do from a graduation market cap of about $200k, and less below it (see 16). $LODE runs its own staircase. 93% of its supply sits in steps from its open to about a $2.6B market cap, as many doublings as fit. The protocol owns the bottom 13% and the team owns the 80% above it. Each step up holds 0.95× the tokens of the one below it, and 1% of supply is the open tail. One team step’s unsold tokens can be withdrawn every 30 days from day 30, lowest step first. Its protocol-owned position’s target is 20% of the market cap, and its bids sit from 70% of the price up to the price. The genesis sets the top in SOL before the raise opens, and the step count is fixed when the raise closes. With ETH at $2,400 and a steady climb, Cook’s vault holds $30.3k at a $1M market cap, $308k at $10M, $3.57M at $100M and $41.0M at $1B (see 16).
69% staircase · 1% open tail
floor ÷ price target 20%
POL money ÷ mcap target 15%
Custom: round(log2($1B ÷ cap)) equal steps, 1–16
$LODE: 5% sale · 1% POL
13% protocol steps · 80% team steps
1% open tail · 0% vesting
POL money ÷ mcap target 20% · bids from 70%
Liquidity helpers (overflow-safe)
_liqForAmount0(sa, sb, amount0): l = mulDiv(amount0, mulDiv(sa, sb, Q96), sb − sa) return l > type(uint128).max ? 0 : uint128(l) _liqForAmount1(sa, sb, amount1): l = mulDiv(amount1, Q96, sb − sa) return l > type(uint128).max ? 0 : uint128(l) // 0 means "not deployed"; the ETH / tokens stay idle in the pool's // vault instead of reverting the whole ratchet on an extreme range.
Views · execute(poolId, selector), decoded twice
05 — ratchet()
How a ratchet raises the floor
Anyone can ratchet a pool. A ratchet takes the pool’s positions out, pays the caller a small bounty from new skim, and solves the floor again. It then publishes the new floor and places the positions back. The published floor can only move to a higher price. Between ratchets, a sell that fills the bid re-places the bid inside the same swap.
The call is execute(poolId, ratchet()), one pool at a time. It reverts NotBound until that pool’s bindPool. Otherwise it unlocks the PoolManager with ACTION_RATCHET and runs _ratchet(msg.sender). The bid is a band whose cheap edge is the published floor, so no gap opens between the bid and the floor. Between ratchets, the only thing that buys is the re-anchor inside a sell (below).
_ratchet(beneficiary): // no-op guard against rounding drains (no lift, so no "gap" clause) if !needsRatchet && unpaidSkim == 0 && vaultEth < MIN_BID_ETH: bidCanRise = bidLiquidity > 0 && floorTick − W < bidLower && ceilToSpacing(cur + 1) < bidLower if !bidCanRise: return needsRatchet = false; floor0 = floorTick _redeemLiftClaims() // the in-swap re-place's ERC-6909 claims come home _sweepSeedFees(key) // zero-delta modifyLiquidity on SEED_SALT // the staircase: what the steps sold is split before the solve _teardownBid(key) // tokens → inventory at cost _teardownAsk(key) // ETH → vault; fee income vs sold accounting // everything that leaves before the bid is placed leaves BEFORE the solve bounty = min(unpaidSkim · BOUNTY_BPS / 10_000, MAX_BOUNTY, vaultEth) unpaidSkim = 0; pay beneficiary (failure re-credits vaultEth) reserve = min(vaultEth, MIN_BID_ETH) // the nudge's dust, held out of Q for i in 0..2: // solve, then the POL follows the floor if vaultEth <= reserve || circulatingSupply() == 0: break candidate = _publish(_solveFloorTick(vaultEth − reserve)) // dear edge + W if candidate < floorTick: floorTick = candidate // ratchet guard else if i != 0: break if !_raisePol(): break _nudge(key, reserve) // up to the dear edge; free across an empty gap stand = ceilToSpacing(cur + 1 + W) // the closing clamp if floorTick < stand: floorTick = min(stand, floor0) // withholds a rise, never lowers // the vault's tokens join the step above the price, at ≥ 2× cost at = _deployAsk(key); _deployBid(key) emit Ratcheted(floorTick, at, vaultEth, inventoryTokens, bounty)
Each teardown and redeploy loses a wei or two to v4’s rounding, which runs against the liquidity provider. The no-op guard at the top stops a spammer turning idle ratchets into a slow drain. For the same reason, the bounty is paid from unpaidSkim only. The bounty and the nudge’s reserve both leave before the solve. So the bid always holds at least the Q its floor was solved on. If they left after, the bid could land up to MAX_BOUNTY short of the floor it was solved for. The closing clamp holds the published floor where the bid can stand: one spacing above where the market ended, plus W. So a third party parked in the gap delays the rise, rather than leaving a bid under the floor. The clamp never lowers the standing floor.
In-swap re-anchor · replaceBidInSwap, inside a sell that filled the bid
afterSwap, on a sell: (bidEth, bidTok) = _bidLive(sqrtP) // exact mid-fill composition if bidTok > 0: self.call(replaceBidInSwap) // an empty revert fails the swap closed replaceBidInSwap(): // hook only, inside the NET window fold earlier claims into the net // every wei of vaultEth: in custody or a credit here _teardownBid(key) // tokens absorbed → inventory at cost; ETH left → vault _nudge(key, vaultEth) // RE-ANCHOR: back up to the dear edge, across the emptied band _deployBid(key) // the whole band again; cheap edge = floorTick, unchanged needsRatchet = true net quote debit → settled from custody; net credit → ERC-6909 claims (liftClaims) // no floor re-solve, no bounty; costs 0 wei in every honest state
A sell that crosses into the band leaves tokens in the bid. A two-sided v4 position would resell them at the floor, skim-free, to the next buyer. So the hook takes the filled bid out inside the same sell, and places it again with the ETH it has left. Without the re-anchor, each re-place would give up the ticks between the market and the next spacing boundary. A few small sells would then close the band from the dear side: at spacing 60 with a 120-tick band, two are enough. The nudge crosses the bid’s own just-emptied band, so it spends nothing. Anything a third party parked there was filled by the seller at those same ticks a moment earlier. liftClaims holds the ERC-6909 claims this netting produces.
The band · _nudge, _deployBid
W = ceilToSpacing(BID_BAND_TICKS) // 120 → 120 at spacing 60 dearEdge = floorTick − W // where the backing solves; a sell fills here first _nudge(key, budget): // buy up to the dear edge, spending at most budget if budget == 0 || price already at or above dearEdge: return _buyUpTo(key, budget, dearEdge) // bought tokens → inventory at cost _deployBid(key): if vaultEth < MIN_BID_ETH: return upper = floorTick // the cheap edge: the published floor lower = max(upper − W, ceilToSpacing(current + 1)) // a partial fill narrows from the dear side if lower >= upper: upper = lower + spacing // last resort: one spacing above market bidLiquidity = liqForAmount0(lower, upper, vaultEth) bidEthDeployed = owed; bidLower = lower; bidWidth = upper − lower
The POL’s edge, the nudge’s limit and the skim ramp all measure to the dear edge. So nothing of the protocol’s sits inside the band, and the market rests just above it.
06 — Every fee
Every fee a trade can pay, and where each one goes
A trade on a LODE launch pays up to six fees. Each launch keeps the rates it was given, and nothing can change them afterwards. This section lists them all, and the sections after it explain each one.
| Fee | Charged on | Rate | Goes to |
|---|---|---|---|
| LP fee | every pool swap | 0.25% | the pool’s in-range liquidity (03) |
| Floor skim | every pool swap | up to 10%; near the bid a buy falls to 0% and a sell rises to 1.5× | the launch’s vault, which is the bid (03) |
| LODE Platform fee | each sale buy and sell, every pool swap | sale 1% (at most 1%), pool 0.25% (at most 0.5%) | LODE’s team vault (08) |
| Creator fee | every pool swap | 0–5% a side, flat | the fee recipients by share, less the referral share (09) |
| Holder tax | every pool swap | 0–10% a side, flat | the launch’s holders (12) |
| Carpenter Platform fee | every swap of a Solana LODE pool | 0.05% (at most 0.1%), quote side | Carpenter, the Solana AMM |
Two more amounts come out of these fees rather than on top of them. The $LODE cut is 2.5% of every inflow to a launch’s vault, taken from the skim and the raise (07). The referral share is 10% of the creator fee, taken from the creator’s side (10). Neither changes what the trader pays.
| Action | What it pays |
|---|---|
| Deploy a launch | gas only |
| Buy in the sale | the sale’s LODE Platform fee, on top of the price; no pool fee |
| Selling before graduation | the cost basis back, less the sale’s LODE Platform fee; the buy’s fee is kept |
| Swap after graduation, EVM | LP fee, floor skim, creator fee, holder tax and the pool’s LODE Platform fee |
| Swap after graduation, Solana | the same five, plus the Carpenter Platform fee |
| Claim fees or rewards | gas only |
07 — The $LODE cut
Where the 2.5% $LODE cut goes
Every launch pays the platform 2.5% of what flows into its vault. On a ETH launch on Ethereum, LODE’s own chain, a keeper sweeps that cut into the $LODE token’s pool. On every other launch, its chain’s platform treasury holds it in the launch’s own quote asset.
LODE is the launchpad and a token. Every launch is a pool on its chain’s single hook. When a pool registers, the hook gives it a destination for the cut, from the destinations its deployer set once. On an EVM chain that call is configurePlatform(treasury, genesisFactory, teamTreasury). The team treasury is where the LODE Platform fee is swept; it is never the platform treasury and it takes no cut. The Ethereum contracts that send a ETH launch’s cut to $LODE are ruled and not yet deployed.
Each chain’s treasury takes the cut in the pool’s own quote and holds it per asset (on EVM, balanceOf[quote], with ETH at address(0)). Governance can withdraw whatever the treasury holds. Nothing is bridged, and none of the treasury’s holdings reach the $LODE pool.
$LODE is an Ethereum launch, and its pool runs the same hook on its own terms. The rates set for it are a 2.5% floor skim and a 0.5% creator fee each side, and no holder rewards. After its raise its pool pays the LODE Platform fee like every other pool (0.25% today), and the timed raise itself pays none. Its sale is the only raise on LODE that runs on a clock, and it has no target, cap or minimum. While the clock runs, anyone can bid SOL. When it stops, the tokens on offer split pro rata by contribution at one clearing price: total raised ÷ tokens offered. Each bidder claims their share once the pool is seeded. The pool pays no cut to itself, so all of what it raises becomes backing.
uint256 public constant PLATFORM_BPS = 250; address platformVault; // per pool, written once at registerPool (see 07, 08, 09) bytes32 platformPoolId; // LODE's pool, when platformVault is the hook itself uint256 platformPaidEth; // lifetime forwarded (launched pools) uint256 platformReceivedEth; // lifetime received (LODE's own pool) function _intake(uint256 amount) internal returns (uint256 kept) { if (platformVault == address(0) || amount == 0) return amount; uint256 cut = (amount * PLATFORM_BPS) / 10_000; if (cut == 0) return amount; platformPaidEth += cut; if (platformVault == address(this)) { // a native pool on a set with a LODE pool; no EVM chain has one PoolState storage target = pools[platformPoolId]; if (target.quoteToken != quoteToken) revert BadQuoteToken(); FloorPoolVault(custodyVault).payQuote(target.custodyVault, cut); target.vaultEth += cut; target.platformReceivedEth += cut; target.needsRatchet = true; } else { // the treasury: any stock pool, or an ETH pool with no LODE pool here FloorPoolVault(custodyVault).forwardQuote(platformVault, cut, false); } emit PlatformCut(poolId, cut); return amount - cut; }
Every inflow passes through _intake before the vault books it:
The bid’s own ETH returning in _teardownBid is the vault’s money coming home, so it never passes through _intake. The code above is the EVM hook. No EVM chain has a $LODE pool, so there the launch’s vault pays the treasury’s intake. Only a registered pool’s own vault may call it, and it credits balanceOf[quote]. Every vault payment holds a transient reentrancy lock.
On Ethereum nothing moves to $LODE during a trade. The program books a ETH launch’s cut on the launch’s own pool. A permissionless keeper sweeps booked cuts into $LODE’s pool, and until $LODE graduates they stay where they were booked.
| Same $297k launch | LODE’s own pool | A launched pool |
|---|---|---|
| Day-one bid as % of open | 99% | 96% |
| Vault after the $576k pump | $759k | $740k |
| Vault after everyone dumps | $44k | $43k |
| Bid after the dump | $0.001828 | $0.001753 |
| Forwarded to LODE on the raise alone | — | $7,425 |
| Mode | Floor skim, far | All in, at the bid · buy / sell | All in, far from it |
|---|---|---|---|
| Cook | 2% / 2% | 1.247% / 4.240% | 3.243% |
| Bluechip | 2% / 2% | 1.497% / 4.489% | 3.492% |
| Moonshot | 2% / 2% | 0.998% / 3.991% | 2.993% |
| $LODE | 2.5% / 2.5% | 0.998% / 4.739% | 3.492% |
The skim column is the floor skim alone. The two all in columns are what the trader pays, which is why Bluechip’s 2% skim reads 3.492%. Skim, creator fee, holder tax and the LODE Platform fee (today’s 0.25% pool rate) are four percentages of the same ETH leg, so they are summed. The pool’s 0.25% LP fee is then charged on what is left, so the two compose multiplicatively. Buys slide to 0% skim at the bid. Sells climb to 1.5× their far rate on Cook, Bluechip, Moonshot and $LODE. A Custom launch picks its own multiple, 1× to 5×. So the at-the-bid pair is asymmetric in every mode. Each pool pays the LODE Platform fee its launch was created with. At the 0.5% cap every all-in figure is about 0.25 points higher, and at 0 about 0.25 points lower.
Every preset’s far skim is 2%, so the presets differ only by their creator fee. Far from the bid, $LODE costs the same as Bluechip and more than Cook or Moonshot. On a buy at the bid it costs the same as Moonshot, and on a sell into the bid it costs more than every preset. Moonshot is the cheapest preset at both ends. 2.5 of $LODE’s 3.25 points are floor skim, booked under the token.
$LODE’s floor grows with the platform’s ETH volume on its chain: F_LODE = (Q_LODE + Σ 0.025 · inflows_i) / S_LODE, summed over every ETH pool i whose cut lands there. Nothing can withdraw it from there.
Source: the reference launch in 15 (raise ≈ $297k), ETH = $2,400, before the LODE Platform fee.
08 — The LODE Platform fee
LODE’s own fee on sales and swaps
LODE charges a fee on each sale buy, each sale sell and every pool swap. The trader pays it on top of the price. It never enters the raise or the vault, so it never moves the floor.
There are two rates, one for the sale and one for the pool. A governance key sets the current value of each, from 0 up to its cap. A launch copies both values when it is created and keeps them for life.
| Rate | Default | Cap |
|---|---|---|
| Sale: each buy and each sell | 1% | 1% |
| Pool: every swap after graduation | 0.25% | 0.5% |
At the default sale rate, a $1,000 buy costs $1,010. Selling those tokens returns $990, because the sell pays the fee too and the buy’s fee is kept.
09 — The creator fee
A flat fee of up to 5% a side, shared among up to five recipients
Whoever launches a token can charge a flat fee on every buy and every sell, up to 5% a side. The fee goes to one to five recipients set at launch, each with a share, and the shares add up to 100%. The launchpad defaults to the launcher’s own wallet at 100%. After launch, nobody can change the rates, the recipients or their shares, including the creator and LODE.
The factory writes the recipient list and both rates into the launch’s pool once, when it registers the pool. The hook has no setter for any of them.
uint256 public constant MAX_CREATOR_BPS = 500; // 5% each way, hard cap uint256 creatorSlotCount; // 1–5 recipients, written once at registration uint256 creatorPendingMask; // bit i set while slot i is a handle not yet claimed uint256 creatorBuyBps; uint256 creatorSellBps; uint256 creatorFeesOwed; // accrued, unpaid, every slot together uint256 creatorFeesPaid; // lifetime paid out, every slot together Payee[5] creatorSlots; // each slot: wallet, share in bps, paid so far registerPool(key, config, launch, referrer2, referrer3, creatorSlots) initialize(c, launch) // BadRange if a rate > cap, or a rate with no recipient // _beforeSwap / _afterSwap, per swap (currency0 = ETH, zeroForOne = buy): fee = ethLeg · skimBps(dir) / 10_000 // to the vault, after the $LODE cut cfee = ethLeg · creatorBps(dir) / 10_000 // to the fee recipients, no $LODE cut tfee = ethLeg · teamFeeBps / 10_000 // to the team at the pool's own rate, owed on the pool, no $LODE cut poolManager.take(ETH, custodyVault, fee + cfee + tfee) vaultEth += _intake(fee); creatorFeesOwed += cfee; teamFeesOwed += tfee return delta(fee + cfee + tfee) function claimCreatorFees(uint8 slot) external returns (uint256 paid) { Payee storage p = creatorSlots[slot]; // RecipientPendingClaim while the slot waits on its handle uint256 lifetime = creatorFeesPaid + creatorFeesOwed; paid = min(lifetime · p.bps / 10_000 − p.paid, creatorFeesOwed); creatorFeesOwed −= paid; creatorFeesPaid += paid; p.paid += paid; bool ok = _payQuote(p.wallet, paid); // out of the pool's vault, only ever to that slot's wallet if (!ok) revert CreatorTransferFailed(); }
The hook takes the creator fee in the same take as the skim and returns both in the same hook delta. A swap therefore pays five things: the LP fee (0.25%), the floor skim (0–15%, ramped, to the vault), the creator fee (flat, ≤ 5%), the holder tax (flat, ≤ 10%) and the LODE Platform fee (0.25% by default, ≤ 0.5%).
The creator fee is not a vault inflow. It never passes through _intake, so $LODE takes no cut of it. It is never counted in vaultEth, unpaidSkim or the bounty base, so it never moves the floor. The launch’s FloorPoolVault therefore holds idle vault ETH plus every fee it owes: to the fee recipients, the holders, the referrers and the team. Its ETH balance covers them all after every completed operation.
Each slot earns its share of everything the pool has ever booked for the creator, rounded down. A claim pays the slot what it has earned less what it was already paid. The rounding leaves at most a few wei per pool in the vault.
A slot is claimed with execute(poolId, claimCreatorFees(slot)) on the hook. Anyone may send that call, and the ETH goes only to that slot’s wallet.
| Per swap, ETH leg | Buy | Sell | Goes to |
|---|---|---|---|
| LP fee | 0.25% | 0.25% | pool liquidity (the hook’s own positions) |
| Floor skim | 1% → 0% at floor | 1% → 1.5% at floor | vault, less 2.5% to LODE |
| Creator fee | 0–5% flat | 0–5% flat | fee recipients by share, no cut |
| Holder tax | 0–10% flat | 0–10% flat | FloorHolderRewards, no cut |
| LODE Platform fee | 0.25% flat | 0.25% flat | team, owed on the pool, no cut; fixed per pool, ≤ 0.5% |
10 — Referrals
The referral share, split across up to three referrers
A launch can name the wallet that referred its creator. That referrer earns 10% of the launch’s creator fee, and the fee recipients share the other 90%. The trader pays nothing extra.
A launch may also name the wallet that referred the referrer, and the wallet above that one. Each referrer keeps 90% of what reaches it and passes 10% up to the next.
| Referrers named | Tier 1 | Tier 2 | Tier 3 |
|---|---|---|---|
| One | 100% | — | — |
| Two | 90% | 10% | — |
| Three | 90% | 9% | 1% |
The shares are of the referral share, not of the trade. On a launch with three referrers, a $100 creator fee sends $90 to the fee recipients, $9 to tier 1, $0.90 to tier 2 and $0.10 to tier 3.
11 — Launch modes
Meme, Bluechip, Custom: three bundles of fixed settings
A mode is a preset bundle of launch settings. It fixes the market cap at which the token graduates, the skim far from the floor, the creator fee and the holder tax, which the presets leave at zero. Meme and Bluechip are fixed. Only Custom can be edited.
The modes live in src/FloorModes.sol. The launchpad does not let anyone edit Meme or Bluechip, because a preset is useful only if everyone recognises it. It converts the cap to a tranche price with the ETH price at deploy time. Nothing on-chain reads an oracle.
The enum has three members, with the ordinals Meme 0, Bluechip 1, Custom 2. FloorFactory casts the ordinal to uint8, and FloorRegistry stores it permanently. A registry written under one numbering cannot be re-read under another. A set of contracts therefore moves to a new enum by being redeployed, never by an upgrade in place.
| Mode | Graduation mcap | Sale raises (30%) | Skim far, buy / sell | Creator fee |
|---|---|---|---|---|
| Meme | $30k | $9k | 1.5% / 1.5% | 0.5% / 0.5% |
| Bluechip | $60k | $18k | 2% / 2% | 1% / 1% |
| Custom | launcher’s | 30% of it | ≤ 10% / 10% | ≤ 5% / 5% |
library FloorModes {
enum Mode { Meme, Bluechip, Custom }
struct Preset { uint256 graduationMcapUsd; uint256 creatorBps; uint256 skimBuyFarBps; uint256 skimSellFarBps; }
function preset(Mode) internal pure returns (Preset memory);
function hookConfig(Mode, uint256 liftMaxBps, address platformVault, address creator)
internal pure returns (FloorHookStorage.Config memory); // liftMaxBps: still passed and range-checked, read by no engine path
function tranchePriceFor(uint256 mcapUsd, uint256 ethUsd, uint256 totalSupply)
internal pure returns (uint256); // mcapUsd·1e36 / (ethUsd·totalSupply)
}
The near-floor ramp has the same shape in every mode. Buys slide to 0% at the floor. Sells climb to 1.5× the far rate on a preset. On Custom the launcher picks the multiple, 1× to 5×. Only the skim ramps, and no rate can change after launch (see 03). Custom is the empty preset, so the hook’s own caps are its only limits. The hook caps the far skim at 10% (MAX_SKIM_FAR_BPS) and the creator fee at 5% (MAX_CREATOR_BPS). It caps the holder tax at 10% (MAX_HOLDER_BPS).
The launchpad’s presets
The launchpad offers three fixed presets, Cook, Bluechip and Moonshot, beside Custom. Each sells 20% of supply in the sale, so it raises 20% of its graduation market cap. Each keeps 10% as the protocol-owned position and sells 69% on the staircase, with 1% as an open tail (see 04).
Measured · $LODE cut on, ETH at $2,400
| Launch, then a buy of 2× the raise, then every holder dumps | Meme | Bluechip |
|---|---|---|
| Vault at graduation | $10.7k | $53.6k |
| Market cap / vault after the pump | $118k / $27.7k | $598k / $139k |
| Market cap / vault after the dump | $67k / $1.7k | $336k / $8.3k |
| Bid after the dump vs open | 3.5× | 3.4× |
| Creator fees earned on the path | $529 | $1,326 |
| Forwarded to LODE on the path | $788 | $3,957 |
Source: each preset at its rates before 2026-09-25 (Bluechip then graduated at $100k), on a 55/15/30 split with a 2× → 8× ask in place of the staircase, launched with the $LODE cut on, ETH = $2,400.
12 — Holder rewards
How the holder tax is shared with holders
A launch can charge an optional holder tax on every trade, fixed at launch like the creator fee. The tax is owed to the token’s holders, and each holder claims their pro-rata share whenever they choose. Balances never change on their own.
Rebasing balances would change the pool’s token balance underneath the PoolManager, which would corrupt the bid, the staircase and the floor math. Instead, one contract per chain keeps a per-share accumulator for each launch, and the token reports every transfer to it. Claims are continuous rather than in rounds: a claim pays what is owed at that moment.
// hook (Config): holderRewards, holderBuyBps, holderSellBps uint256 public constant MAX_HOLDER_BPS = 1000; // 10% each way, hard cap function _takeFees(key, ethLeg, zeroForOne) internal returns (uint256 total) { fee = ethLeg · skimBps / 10_000 // vault, after the $LODE cut cfee = ethLeg · creatorBps / 10_000 // fee recipients, accrued (10% owed to a referrer) hfee = ethLeg · holderBps / 10_000 // holders, booked now, paid on claim tfee = ethLeg · teamFeeBps / 10_000 // LODE Platform fee at the pool's own rate, owed to the team (teamFeesOwed) poolManager.take(ETH, custodyVault, fee + cfee + hfee + tfee) …; holderOwedEth += hfee; IFloorHolderRewards(holderRewards).accrue(poolId, hfee); } // FloorHolderRewards — one per chain, behind a proxy; books only, holds no money rewardPerShareE36[token] += amount · 1e36 / eligibleSupply // on every accrue (1e36, not 1e18 — see the note) onTransfer(from, to, amount): // called by the token, pre-transfer settle(from): owed += shares·rps/1e36 − debt; shares −= amount; debt = shares·rps/1e36 settle(to): same, shares += amount claimable(token, who) = owed[who] + shares[who]·rps/1e36 − debt[who] claim(token): settle(msg.sender); paid = owed; owed = 0; hook.execute(poolId, releaseHolderRewards(msg.sender, paid))
Never earns · fixed when the launch registers
Only an approved factory can register a launch, and the book checks it against the pool’s own state on the hook. An accrue made while nobody holds yet is parked in unallocated and folded into the next one. The hook books the tax on a buy in beforeSwap, before the buyer’s tokens arrive, so a buyer never pays themselves. A wallet whose balance predates binding, such as the deployer’s supply, is mirrored on its first outgoing transfer.
The book holds no money. Each launch’s holder tax waits in that launch’s own FloorPoolVault, counted as holderOwedEth. The engine’s releaseHolderRewards pays each claim. Only the pool’s own book can reach it, through hook.execute, and it refuses to pay more than that pool has accrued. A contract that holds tokens and never claims keeps its share, and nobody else can take it. On Ethereum the same tally is floor_holders, a Token-2022 transfer hook on new launches with a holder tax. It counts only the wallets that have started earning.
The accumulator is rewardPerShareE36, scaled by 1e36 so that a pool can carry a quote of any decimals. At a 1e18 scale, _deposit would floor total · ACC / eligibleSupply. Any deposit under eligibleSupply / 1e18 raw units would then credit nobody and be stranded for good. On an ETH quote with 30% sold, that threshold is 3e8 wei, which is invisible. On a 6-decimal quote the same 3e8 raw units is 300, and a holder tax on a small swap is well under it. With eligibleSupply ≤ 1e27 < 1e36, the remainder per deposit is under one raw unit. The multiplications go through FullMath.mulDiv and round down. There is no per-launch contract: every launch’s book is a slot in the chain’s single FloorHolderRewards (see 01, row 07).
Over five buy-sell rounds with a 2% / 2% holder tax and a 1% / 1% creator fee, $1,415 was deposited for holders. The first five wallets claimed $766, and the rest stayed claimable.
Source: the five-round figures from a single-launch version of the hook, with a book of its own. The accumulator’s figures from HolderRewards.sol:42-43 at ratchet-floor df191ce.
13 — Lock & vest, burn
Locking, vesting and burning tokens
Any holder can lock tokens on a vesting schedule for a beneficiary, or burn tokens they hold. One contract, FloorVesting.sol, serves every token on the platform. Burning is a function on the token itself, FloorToken.burn.
struct Lock { token; beneficiary; total; claimed; start; cliff; end; }
lock(token, beneficiary, amount, cliffSeconds, durationSeconds) → id
// cliff ≤ duration; tokens pulled now; schedule immutable
vested(id) = t < cliff ? 0 : t ≥ end ? total : total · (t − start) / (end − start)
claimable(id) = vested(id) − claimed
claim(id) // anyone may call; pays only the beneficiary
Once a lock is made, nobody can revoke it, unlock it early or change who receives it. The contract has no owner.
function burn(uint256 amount) external {
_notify(msg.sender, address(0), amount); // stops earning
_burn(msg.sender, amount); // totalSupply falls
totalBurned += amount;
}
The hook reads totalSupply() live in circulatingSupply(). A burn therefore shrinks sellable supply against the same ETH, and the floor rises on the next ratchet for everyone else. Only a holder can burn what they hold. The vault never burns its own inventory: it keeps what it buys.
14 — FloorLaunch
How the sale, selling and graduation work
Each launch sells its tokens through a sale contract before its pool opens. The sale holds the quote asset until it sells out and graduates, and until then any buyer can sell at their cost basis, less the sale’s LODE Platform fee. Buyers receive their tokens inside the buy, so there is no claim step.
The sale’s config is immutable. The factory mints the whole supply to the sale when it creates the launch. The sale’s LODE Platform fee is copied into its config at creation and kept for life: 1% today, never above 1%, and 0 allowed. Each buy pays it on top of the sale price, and the sale holds it apart from the raise.
On Ethereum, creating a launch takes two transactions that the creator approves once. The first sets up an address lookup table for that launch, and the second creates the launch through it. Solana’s transaction size limit needs the split, and the table’s rent can be reclaimed afterwards.
struct Config {
uint256 saleTokens; // sold in tranches
uint256 polTokens; // protocol-owned, token-only, open → ∞ (the tail)
uint256 vaultTokens; // the staircase's tokens
uint256 p0; // ETH wei per whole token, first tranche
uint256 p1; // last tranche; pool opens at p1
uint8 tranches;
uint256 floorShareBps; // share of the raise → seedFloor()
}
// constructor: saleTokens + polTokens + vaultTokens == totalSupply
// p1 >= p0, p0 != 0, tranches != 0, floorShareBps <= 10_000
tranchePrice(i) = p0 + (p1 − p0) · i / (tranches − 1)
openTick() = getTickAtSqrtPrice(sqrtPriceX96FromRatio(p1, 1e18))
canGraduate() = funded && !graduated && sold >= saleTokens
_buy(gross) = walk(gross · 10_000 / (10_000 + teamFeeBps)); fee = spent · teamFeeBps / 10_000 // the fee rides on top; contributed and raised count spent only
_sell(tokens) = contributed · tokens / allocation // your own average price; raised falls by this
sellBack pays = _sell(tokens) − _sell(tokens) · teamFeeBps / 10_000 // less the sale's LODE Platform fee (1%) → teamOwed
custodyAtBuy = token.launch() == address(this) // probed at initialize: true on every factory sale
// the exit: token.sellBack(tokens) -> onSellBack -> _sell; FloorLaunch.sell() reverts UseSellBack
// no claim step: buy() already transferred the tokens; claim() reverts Nothing
Reference launch config
The factory mints the whole supply straight to the sale’s predicted address before the sale exists, and binds the token to it. The sale therefore starts funded and delivers at the buy. Founder allocation is 0% on every launch: the factory mints the whole supply to the sale.
It reverts SaleOver after graduation or once sold out, and Nothing if zero tokens result. It records allocation and contributed for the sale price only. The fee is booked to teamOwed, apart from raised. Then the sale transfers the tokens to the buyer before refunding the change. All sale state is settled first. Solmate’s transfer has no receiver callback, so the buy hands control to nobody. claim() reverts Nothing rather than paying a second time out of the ask ladder.
floorEth = raised · floorShareBps / 10_000, and the rest pairs into POL. Before anything is seeded, the sale hands teamOwed to its pool’s owed line (bookTeamFees). The LODE Platform fees are therefore never backing and never pay the $LODE cut. Any balance the POL position could not use goes to seedFloor. Unsold sale tokens join vaultTokens on the staircase. It emits Graduated with the raise, the floor and POL ETH, the staircase’s tokens and the open tick.
The seller calls FloorToken.sellBack(tokens). It moves the seller’s own balance to the sale, then tells the sale to pay through the same _sell. The payout is contributed × tokens / allocation, your own average price, less the sale’s LODE Platform fee. The buy’s fee is not returned. The tranche capacity is released, and raised falls by the whole average-price amount. FloorLaunch.sell() reverts UseSellBack, because the tokens are in the seller’s wallet and paying out without taking them back would be an unconditional drain.
no approval
Sale
30%
300_000_000e18, 10 flat tranches at 225 gwei (reference config)
POL
10%
100_000_000e18, tokens only, open → ∞ (the tail; overlaps the steps)
Staircase
60%
600_000_000e18, equal steps from the open, one per doubling, and a 1% open tail
Founder
0
floorShareBps 10_000; no minimum raise, no deadline
Day-one ratio, with floor share f: floor / price = f · (sold / circulating) · (avg / p1). A flat sale (avg == p1) that sends everything to the floor opens at 100% of the bid-covered supply. The measured 78% backing-to-market-cap headline counts POL tokens in circulating supply.
The counts above are the reference config’s. Cook, Bluechip and Moonshot split supply 20% sale, 10% POL, 69% staircase and 1% open tail (see 04 and 11).
Source: the reference launch config at 225 gwei.
15 — The team buy
A team buy paid out to up to five team payees
A launcher may buy up to 5% of supply in the sale with their own money. What the team buy pays out goes to one to five team payees, each with a share, and the shares add up to 100%.
At least 80% of the team buy goes on team steps, which lock for at least 90 days. The rest is the wallet part, which vests on cliffs. The launchpad defaults to the launcher’s own wallet at 100%.
Every payee is paid its share of three things: the team’s 80% of what the team steps sell for, the team steps’ unsold tokens after the lock, and the vested wallet part.
Each payee earns its share of everything the team has been owed, rounded down. A claim pays one payee what it has earned less what it was already paid. The rounding leaves at most a few raw units in the vault.
16 — Measured results
A reference launch under stress, with ETH at $2,400
These tables follow one reference launch. It raised about $297k and split its supply 55/15/30 between the sale, the POL and a genesis ask from 2× to 8×. Its dollar figures are priced at ETH = $2,400. The tables show a pump and then a full dump, a dump on day one, and 30 days of balanced trading. The last table follows Cook, Bluechip and Moonshot on the staircase instead, from graduation to a $100M market cap.
Pump, then everyone dumps
| Moment | Price | Market cap (price × 1B) | Vault ETH | Supply held by vault | Live bid |
|---|---|---|---|---|---|
| Graduation (raise $297k) | $0.000540 | $540k | $297k | 30% (POL + ladder) | $0.000537 · 99% of open |
| After a $576k pump (ladder sells 248M for $458k) | $0.003139 | $3.14M | $759k | 5% | $0.000911 |
| After everyone dumps | $0.001836 | $1.84M | $44k | 91% | $0.001828 |
Market cap is price × total supply, as every tracker quotes it. The vault never burns, so tokens it buys back still count, and the cap cannot fall below bid × supply. After the dump the price sits on the bid and the cap is $1.84M. The vault holds 91% of the supply as inventory it will re-list at ≥ 2× cost. Sellers were paid $714k in row three. The vault is the money sellers can take out, so it fills on the pump and empties on the dump.
In this run the bid never falls, and it ends at 3.4× the launch price. The near-floor sell skim retires tokens more cheaply than the bid pays for them. On the live hook, the figure that never falls is the published floor, floorTick. The bid, bidRawQuotePerToken, is the band’s dear edge. It steps down as a part-filled band narrows, until the next ratchet re-solves it.
Day-one dump
| 70/30 split, wide POL | 100% to bid, token-only POL | |
|---|---|---|
| Day-one bid as % of opening price | 76% | 99% |
| Bid ETH used if everyone dumps | $214k of $216k | $249k of $297k |
| Buyers' recovery, total day-one dump | 68¢ / $ | 89¢ / $ (96¢ at 3% skim) |
| Where the missing cents went | $68k stranded as ETH in POL + skim | skim only, all back in the vault |
30 days of balanced flow · ratchet() once a day
| Daily volume | Volume, day 30 | Vault, day 30 | Live bid, day 30 | Effective take |
|---|---|---|---|---|
| $100k | $2.99M | $436k | $0.000739 | 4.7% |
| $1M | $29.9M | $1.75M | $0.002991 | 4.8% |
| $10M | $299M | $15.3M | $0.026723 | 5.0% |
Each day is a set of round trips (buy, then sell everything back), so volume counts both sides. Effective take is vault growth ÷ volume. Far from the floor it is 1.25%: the 1% skim plus the 0.25% LP sweep, with no creator fee or holder tax in this run. On the floor, sells pay up to 10% and buys 0%.
The staircase presets · one steady climb to about a $1B market cap
| Preset · market cap | Bought since graduation | Vault | Floor ÷ price | POL money · share of market cap | 1% sell moves the price | 3% sell moves the price |
|---|---|---|---|---|---|---|
| Moonshot · $1.01M | $80.9k | $34.1k | 7.4% | $49.7k · 4.9% | 2.7% | 7.7% |
| Moonshot · $10.0M | $712k | $322k | 5.0% | $375k · 3.7% | 3.4% | 8.8% |
| Moonshot · $101M | $7.02M | $3.36M | 4.1% | $3.49M · 3.5% | 3.4% | 8.7% |
| Moonshot · $802M | $55.5M | $27.4M | 3.5% | $27.0M · 3.4% | 3.4% | 8.8% |
| Cook · $1.00M | $71.6k | $30.3k | 8.5% | $49.3k · 4.9% | 3.3% | 8.6% |
| Cook · $10.1M | $700k | $308k | 5.6% | $381k · 3.8% | 3.5% | 9.0% |
| Cook · $101M | $7.55M | $3.57M | 4.9% | $3.80M · 3.8% | 3.2% | 8.2% |
| Cook · $1.01B | $83.3M | $41.0M | 4.4% | $40.4M · 4.0% | 2.8% | 7.5% |
| Bluechip · $1.00M | $78.1k | $35.5k | 11.7% | $60.4k · 6.0% | 4.5% | 8.9% |
| Bluechip · $10.1M | $764k | $330k | 6.4% | $429k · 4.2% | 3.9% | 9.2% |
| Bluechip · $101M | $7.98M | $3.74M | 5.2% | $4.04M · 4.0% | 3.0% | 7.8% |
| Bluechip · $1.00B | $88.2M | $43.4M | 4.8% | $42.6M · 4.2% | 2.7% | 7.4% |
This table is measured on the live hook with 69% of supply in steps, a 1% open tail and a 15% POL target. Each preset starts from its graduation market cap: $25k for Moonshot, $50k for Cook and $100k for Bluechip. Moonshot’s steps end at about $819M, and Cook’s and Bluechip’s at about $1.64B. Every 5 minutes a buyer spends 0.1% of the market cap, and a ratchet follows. At each row the clock moves 30 minutes and one ratchet runs. Then a single sell of 1% or 3% of the market cap is measured on its own. Bought since graduation leaves out the raise. POL money is what the protocol-owned position and its bids under the price hold. A faster climb leaves those bids further under the price, so the same sells move it more. Past Moonshot’s last step only the open tail is left, and at a $1.17B market cap a 3% sell moves its price 26.6%.
Custom on the staircase · a 3% or 4% sell, to about a $1B market cap
| Launch · graduation cap | Split: sale / POL / steps | 3% sell moves the price | 4% sell moves the price | Sell that empties the cushion · share of market cap |
|---|---|---|---|---|
| Custom · $1M cap | 30 / 10 / 60 | 5.6–8.6% | 7.3–10.6% | 4.5–6.1% |
| Custom · $200k cap | 30 / 10 / 60 | 6.6–8.5% | 8.5–9.8% to $10M · 57–90% from $100M | 3.7–4.3% |
| Custom · $30k cap | 30 / 10 / 60 | 8.9–13.3% · 29.9% at $100M · 80.1% at $813M | 44–97% | 3.0–3.1% |
| Custom · $200k cap | 45 / 10 / 45 | 7.9–10.2% to $10M · 51–84% from $100M | 10.2% at $1M · 68–97% from $10M | 2.8–3.1% |
| Moonshot · $25k | 20 / 10 / 69 | 7.7–9.6% | 10.1% at $1M · 73–96% from $10M | 3.5–3.7% |
| Cook · $50k | 20 / 10 / 69 | 7.5–9.0% | 32% at $1M · 69–72% at $10M and $100M · 9.7–10.1% from $300M | 3.6–4.2% |
| Bluechip · $100k | 20 / 10 / 69 | 7.3–9.2% | 10.9% at $1M · 36% at $10M · 9.4–12.0% from $100M | 3.9–4.5% |
This table is measured on the live hook with every launch’s steps to about a $1B market cap and a 15% POL target. The Custom launches use their default fees: a 1% skim and a 1% creator fee each way, and 1.5× at the floor. Each launch climbs as in the table above. Each range runs from a $1M market cap to the launch’s last step, or from $10M on the $1M-cap launch. The last column is the smallest sell that moves the price more than 20%, read from a $10M market cap.
A Custom launch puts 59% of its supply on equal steps, where a preset puts 69%. Each doubling therefore feeds less money to the bids under the price. With the default 30 / 10 / 60 split, a Custom launch softens a 3% sell about as the presets do from a graduation market cap of about $200k. Below that cap, or with a bigger sale share, the cushion is thinner and a 3% sell can move the price much more. A sell larger than the cushion falls to the floor. Above the last step only the thin open tail is left, so sells move the price more there.
Source: reference launch, 55/15/30 split at 225 gwei, raise ≈ $297k, ETH = $2,400. Staircase and Custom tables: the live hook, each launch at its own fees with the LODE Platform fee and the $LODE cut, ETH = $2,400.
Verify