MLXDocs
Protocol

The price curve

Markdown

The network's position counts the dollars that entered it, in {{unitUsd}} units. MLX per unit starts at {{genesisRate}} and halves at every doubling ({{doublingUsd}}), so the network price starts at {{genesisPrice}} and doubles each time. The protocol buys and sells MLX along this curve.

All of it is in lib/chain/curve.ts. The ledger's swap and buy_node handlers in lib/chain/ledger.ts apply it, and lib/chain/walletpay.ts plans a seat paid from the wallet.

Supply

The supply is fixed at 10,000,000,000 MLX (TOTAL_SUPPLY), divisible to 6 decimals (DECIMALS). On the ledger, amounts are integers in base units, written as strings. All MLX was created at genesis in the five protocol accounts shown in the overview. The curve creates no MLX. Spot buys are filled from treasury.mlx.

Position

The position u is stats.units on the ledger: how many $100 units have entered the network.

EventPosition
A seat is boughtmoves forward by 50% of the seat's units (all of them before 29 Oct 2026, seatCurveUnits)
A seat is granted (Builder program)doesn't move
A spot buy of D dollarsmoves forward by D / unit
A spot salemoves back by the units that would have minted that MLX, never below 0
A seat paid partly with MLXmoves back by the sale, then forward by the seat

The current position, price and halving progress are in /api/curve:

GEThttps://mlx.app/api/curve

Rate and price

D_k = length of doubling k             (DOUBLINGS, doublingLength)
b_k = D_0 + … + D_(k−1)                where doubling k starts (halvingAt)
k   = the doubling u is in             (epochOf)

rate(u)  = G · 2^−(k + (u − b_k) / D_k)    MLX per unit at position u
priceAt(u) = unit / rate(u)                dollars per MLX

unit = $100                      (UNIT_USD)
G = 10,000 MLX per unit       (GENESIS_RATE)

Doublings lengthen (curve v2, 29 Oct 2026): 200,000 ($20 million), then 300,000 ($30 million), then 400,000 ($40 million), then 500,000 ($50 million) for every doubling after. The rate halves once per doubling, smoothly, not in steps, and the price is continuous at every boundary. The network price starts at $0.01 and doubles every doubling. The first doubling is the same as before v2, and the network had not left it, so earlier transactions replay unchanged.

The integral

A span of units [u, u + m) is worth the exact integral of the rate over it (grant):

within doubling k:
grant(u, m) = (G · 2^−k · D_k / ln 2) · (2^(−(u − b_k) / D_k) − 2^(−(u + m − b_k) / D_k))

A span that crosses a boundary is summed doubling by doubling.

The integral is additive, so grant(u, a) + grant(u + a, b) = grant(u, a + b): buying in one piece or many gets the same MLX. One pass along the whole curve is worth at most G · H / ln 2 MLX (CURVE_TOTAL, also curveTotal in /api/curve). Because sales move the position back, a stretch of the curve can be paid again after a sale.

Dedicated seats bought before SEAT_REWARD_END_AT were paid grant(u, units) up front. Seats bought since are paid nothing up front. They still move the position, and so the price. See Dedicated seats.

Spot buys and sells

The protocol is the counterparty. It fills every spot order on the curve, from treasury.mlx (the swap transaction).

Buy with D dollars of USDC (or legacy USDT) at position u:

m   = D / unit
MLX = grant(u, m) / (1 + buyPremium)          (buyQuote)
u  → u + m

Sell X MLX at position u:

K   = G · 2^−k · D_k / ln 2                  within doubling k
a   = b_k − D_k · log2(2^(−(u − b_k) / D_k) + X / K)   the position where the curve would have paid exactly X
                                              (a sale that reaches b_k continues into doubling k − 1; never below 0)
USDC = unit · (u − a) · (1 − sellDiscount)    (sellQuote)
u  → a

Past position 0 the curve has nothing left to unwind, so a sale is paid only for the units that are there.

The defaults are a buy premium of 3% and a sell discount of 20% (BUY_PREMIUM, SELL_DISCOUNT). The live values can differ: they are set by the operator and published in /api/stats as market. Read them there, never from this page.

The ledger refuses a fill when:

  • the amount is under its minimum (SPOT_MIN_UNITS in lib/chain/spot.ts);
  • the treasury doesn't hold enough MLX for a buy, or enough USDC for a sale;
  • the output is below the minOut the wallet signed (its slippage guard);
  • a sale asks for more than the wallet's unlocked MLX. Locked MLX can't be sold.

Outputs are rounded down to whole base units. Spot-bought MLX is never locked.

To get the exact quote the ledger would fill right now, with its minOut:

GEThttps://mlx.app/api/market/quote
ParameterTypeNotes
sidebuy or sellrequired
amountinteger stringwhat goes in, in base units: USDC (or USDT) for a buy, MLX for a sale
stableUSDC or USDTthe coin a buy pays with; USDC when left out
accountwallet nameoptional: also checks that wallet's balance

See Market.

Paying from the wallet

buy_node with pay: "WALLET" pays for a seat from the whole wallet (planWalletPay in lib/chain/walletpay.ts):

  1. USDC first.
  2. Then USDT, if any is left from before.
  3. Then the fewest unlocked MLX that sell for the rest at the spot sell price (mlxForUsd).

The sale and the seat settle in one step. The MLX goes to treasury.mlx, and the dollars it fetches go straight to the seat, so no sell-side liquidity is drawn. The position moves back by the sale's units, then forward by the seat's units. The seat's record carries sold: { mlx, usd }.

The wallet runs the same plan in the browser and signs maxMlx: its quote plus a small margin (maxMlxFor). If the price moved and the plan needs more MLX than that, the ledger refuses with "The MLX price moved beyond your limit".

Reading it

WhatWhere
Position, price, next halving, seat ratesGET /api/curve
Live spread (market), position (stats.units), treasury liquidityGET /api/stats
An exact quoteGET /api/market/quote
Supply and allocationGET /api/supply