Loss budget
Every market has a loss budget: the most it may cost the LPs over its life. A market tracking a thin asset can be moved cheaply. Without a budget, moving a spot price would buy access to the whole pool.
Key figures
| Raised by | backing posted behind the market, and nothing else |
| USDC, USDT backing | counts 100% |
| SOL backing | counts 80% of its value |
| Cut to depth by | anyone, on an observed market with a seasoned mark |
| Depth a cut uses | moves 10% of the gap per 20 seconds at most; up by no more than 10% of itself |
| Lowered by the authority | set_market_budget, down only |
| Pool size per batch | 5% of the remaining budget |
| Reserved per open position | nothing |
The remaining budget
remaining = loss_budget - net_loss when net_loss > 0
remaining = loss_budget otherwisenet_loss is what the market has cost the LPs so far, realized. A gain
unwinds earlier losses first. It never grows the budget past what was
underwritten: a market cannot bank profit into a larger allowance.
How the budget moves
Up. Only when someone posts backing, and only by what that deposit counts for, up to what stands behind the market:
cap = backing behind the market + net_loss
budget = max(budget, min(budget + counted, cap))Fee income credited to backers raises nothing. No key can raise a budget any other way, the authority included.
Down, by itself. The budget follows the backing down. When backing is
withdrawn, or a token it is held in falls in price, the budget is held to
cap. Adding back net_loss stops losses from counting twice: the budget is
a lifetime figure and the backing is what is left after losses drew on it.
Down, by depth. derive_market_budget is permissionless and only cuts. It
sets an observed market's budget to its budget depth, the cost of moving the
pool 1%, when that is below the budget and the mark is seasoned. Budget depth
is depth that has held:
- The first reading sets it.
- After that it moves toward each reading by 10% of the gap, at most once every 20 seconds.
- A rise is also capped at 10% of where it stands.
One thin reading cuts nothing. One deep reading undoes nothing. If a pool drains to a tenth of its depth and stays there, budget depth falls halfway in about 3 minutes and to twice the new depth in about 7. The venue's keeper sends the cut whenever budget depth is below the budget.
Down, by the authority. set_market_budget lowers a budget, never raises
it. It is a brake on a market the authority no longer trusts.
Depth can be rented for a slot. An account that could raise a budget by parking liquidity in the spot pool would be writing its own allowance. That is why the operation does not exist, rather than being restricted to a privileged caller.
What the budget limits
The budget is enforced on what the pool takes on and what winners are paid, not on what traders open.
- The pool's size. The pool fills at most 5% of the remaining budget per flow per batch. A spent budget means the pool stops quoting. Trades that bring the pool back toward flat are also taken, up to the long/short imbalance, so exits are not throttled.
- Crossed trades. Traders who cross each other still trade when the budget is spent. That fill adds no net exposure for the pool.
- Profit paid. A winning close is paid its collateral and its profit. When the market cannot cover every winner, profit is cut to a fair share. See Profit haircuts.
- Liquidations. A liquidated position is paid at most its collateral plus the remaining budget.
Leverage and open interest are checked when an order enters the batch, not against the budget. A close is never shrunk by the budget: it fills what the auction gives it, and only the profit it is paid can be cut.
So every batch settles, a market with no budget left stays open for exits, and no market pays out more than it was underwritten for.
Who pays a loss
A loss the market takes is paid in this order:
- Backing, posted by the market's underwriters.
- LP liquidity.
- Insurance fund, only for what liquidity cannot cover.
All three only up to the remaining budget. A later gain repays backing first, up to what losses drew from it, then goes to the LPs.
Backing held in tokens
Settlement pays in USDC only, so a loss reaches LP liquidity and the fund
once the USDC backing is spent, even when the market's backers also posted
tokens. The tokens then pay back what the LPs and the fund covered, at the
oracle (sync_backing, and every backing deposit or withdrawal).
- The fund first, then the LPs. That is the reverse of the order the two were drawn. Each market records what the fund has paid toward it and not been repaid.
- The fund holds the tokens it is repaid in. The LPs buy them back at the oracle with free liquidity on every sync, which puts the USDC where settlement can use it again. At the oracle the LPs neither gain nor lose.
- A recovery refunds the backers. If the market later wins the loss back, the gain reaches the LPs, and the LPs refund the backers in USDC, the fund's part included. The fund keeps what it was repaid.
- Tokens the LPs no longer bore a loss for go to the fund. If a gain has repaid the LPs for a loss they were already paid tokens for, while the fund is still owed, the LPs pass that part to the fund in USDC before anything goes back to the backers.
Example: a market's USDC backing of $2,000 is spent, LP liquidity pays $3, and the fund pays $4,999. Earlier liquidations had paid the LPs $1,001 on the market, so the loss past the USDC backing is $4,001, and the backers hold $10,000 of tokens. A sync moves $4,001 of tokens to the fund. The LPs get none: the market has not cost them anything. The fund is still owed $998, which the tokens do not owe because the market's loss past the USDC backing is only $4,001. Before this rule the $4,001 went to the LPs.
A batch is settled as one
Settlement is permissionless, so whoever settles a sealed batch chooses the order of its closes. Closed one at a time, a winner drew the backing and a loser repaid it only up to what had been drawn so far: settled winner first, the loser's loss repaid the backers; settled loser first, it went to the LPs and the winner's profit drew the backing for good.
Now a close settled out of a batch moves the backing to where the batch's net so far would leave it as one close:
- Net down: drawn up to what the backing held when the batch began. Fees the batch pays the backers are not drawn on.
- Net up: restored up to what was drawn before the batch.
- The fund: a gain in the batch puts back what the fund paid a winner earlier in the same batch.
- Never against the close's own direction: a winner is never paid by restoring backing, and a loser's gain never pays a draw.
Once every order has settled, the backers, the LPs and the fund hold the same in any order. Traders are paid the same as before; only where the pool's side of their PnL lands changed.
Example: $2,000 of backing, nothing drawn. A short and a long, $2,000 at 2x each, close in one batch after a 3% move. The winner is up $13.88 and the loser down the same.
| Settled | Before | Now |
|---|---|---|
| Winner first | backing $2,000, LPs flat | backing $2,000, LPs flat |
| Loser first | backing $1,987, LPs +$13.88 | backing $2,000, LPs flat |
Fees aside: the backers also keep their share of the two close fees.
Two things still depend on the order. Profit haircuts, when a market's winners can reach its remaining budget (see Profit haircuts). And the cuts of a close fee when LP liquidity is nearly gone: a cut liquidity cannot cover is not taken, so a settlement that lands before a fee refills liquidity gives up a cut that one after it takes. That moves at most the cuts of the batch's fees.
Numerical example
An observed market whose pool costs $40,000 to move 1%.
- Backers post $50,000 USDC. The budget is $50,000.
- Once budget depth has held at $40,000, anyone cuts the budget to $40,000. Posting $1 more raises it to $40,001, not back to $50,000.
- The pool's size per batch is 5% of $40,000: $2,000.
- Losses consume $30,000. Remaining budget: $10,000. Pool size: $500. Backing left: $20,000.
- A backer withdraws $15,000, leaving $5,000. Cap: $5,000 + $30,000 = $35,000. Budget: $35,000. Remaining: $5,000.
- Had they posted $10,000 instead: cap $60,000, budget $50,000, remaining $20,000.
Price sources
Every market has one reference mark. The mark breaks the last tie in the auction, sets the band orders clear inside, prices the pool's quote, values positions, and drives liquidation through the risk price. It never sets a clearing price on its own.
Verification
Kani is a model checker for Rust. A test checks the inputs somebody wrote down. A Kani harness makes its inputs symbolic, states what they may be, and checks a property for every input inside those bounds, or produces the input that breaks it.