The two-position launch

Since the 2026-09-12 amendment there is no bonding curve. The entire supply goes into locked Uniswap v4 liquidity, from the creation transaction itself. In the code since 2026-09-28: LiquidityLock.launchMarket does all of it inside the market's creation transaction, and the tests pin the opening price the Lens reads, 3,401,582,525 wei per token.

Why the curve went away

The old curve was a constant product over virtual reserves:

x = VIRTUAL_ETH   + netReserve     (3.75 ETH + what came in)
y = TOKEN_RESERVE - tokensSold     (1.1 B − what went out)

That is exactly what a concentrated liquidity position is: v3/v4's virtual reserves are that offset. The correspondence is not an approximation, it is the same equation written differently.

What removing it buys: no migration — the protocol's riskiest moment — no graduation fee to extract, one fee path instead of two, and markets routable by aggregators from their first block.

The two bands

graph LR A["FDV 3.409 ETH

tick 195000

opening"] -->|band 1 · 700M tokens · 7.535 ETH| B["FDV 34.091 ETH

tick 171960

10x"] B -->|band 2 · 300M tokens · unbounded| C["tick −887220

price ceiling"]
Band 1 Band 2
Tokens 700,000,000 300,000,000
Ticks [171960, 195000] [−887220, 171960]
Depth 7.535 ETH to traverse 14.5 ETH at 2× · 45.7 ETH at 20× · 144.6 ETH at 200×

tickSpacing 60, and no LP fee.

These are the default launch settings. Since 2026-10-05 the supply, the tokens in band 1 (band 2 takes the rest), the launch tick, the bottom ticks of both bands, the tick spacing and the LP fee form one setting of StockFun's owner, setLaunchConfig on the factory, which applies to the markets created afterwards. It refuses a shape no pool could hold: an empty band, ticks off the spacing or out of order, a tick spacing or an LP fee out of range, bands whose liquidity one tick cannot carry. Each pool keeps the shape, the LP fee and the tick spacing it was created with: the lock records its ticks, and the Lens gives each market's LP fee and tick spacing.

The delicate part: the opening price

Both positions hold tokens only at launch. That is what lets the protocol advance no ETH: every ETH the pool will ever hold comes from buyers.

For a position to be token-only, the current price must be at or above the top of its range. Hence:

sqrtStartX96 = TickMath.getSqrtPriceAtTick(BAND1_UPPER);  // not sqrt(raw FDV)

The exact tick of the launch FDV is 194,977.95, and the nearest usable tick above it is 195,000. Deriving sqrtStart from the raw FDV would put the price inside band 1, and LiquidityLock's NotSingleSided check would reject the deposit.

Quantisation leaves an effective FDV of 3.4016 ETH instead of 3.409, a −0.22 % drift.

What it looks like in practice

Successive 2 ETH buys from launch, with the default settings:

Spent FDV Supply held
2 ETH ~$27,600 36.1 %
4 ETH ~$50,400 53.3 %
10 ETH ~$164,000 74.8 %
50 ETH ~$2.78 M 93.9 %

The first ticket takes 36.1 % of supply — against 36.99 % on the old curve. The launch behaves as before, to within a point, which was the criterion the parameters were chosen against.

A band's structural ceiling

The ETH a band can absorb, if 100 % of supply sat in it, is exactly the geometric mean of its two FDVs:

$$ E{\max} = \sqrt{\text{FDV}{\text{start}} \times \text{FDV}_{\text{end}}}

$$

That is what constrains the parameters: you cannot freely pick the launch price, the band top and the depth — the token count closes the system.

The end mode

Like the tokens, the lock cannot be upgraded: its code is what keeps the liquidity in the pools. Since 2026-10-02 it has one exit, the end mode, for the case where the project shuts down.

  1. The announcement. StockFun's owner calls end(), and the lock records, publicly, the date 30 days later. From then on no new market can launch, nor can the $STOCKFUN position be created, so no market gets less than the full notice. Trading and fee collection go on
  2. The notice. For 30 days every pool keeps trading. The owner can cancel at any time with cancelEnd(), and launches resume
  3. The recovery. Once the 30 days have run, the owner can take every position of a pool out — both bands of a market, the single $STOCKFUN position — and send its ETH and tokens, uncollected donations included, to any address (recoverLiquidity). A recovered pool collects nothing more and no longer counts as locked; a later cancellation leaves it empty

The 30 days are the holders' notice. They are a constant of the lock, END_DELAY, not a setting: the one fixed delay of the protocol.

Outside the end mode, nothing reaches the positions. Since 2026-10-05 the lock keeps a share of a fee collection whose recipient refused it, for that recipient, until anyone pays it (payOwed); and StockFun's owner can move out what was sent to the lock by mistake (rescue, rescueClaims, rescueNft): any token, ETH beyond the shares it keeps, v4 claims, an NFT. The lock has no generic call: through the PoolManager, one could reach the end mode's recovery without its 30 days.