Pricing & Spread
Every Levant trade fills at a verified oracle mid adjusted by a deterministic spread built from three parts: a 2 bps constant, a size-vs-depth price-impact term, and a skew premium. The result is floored at the mid (never in your favor) and capped at 5%, and your max-slippage tolerance is your own cap on it. Because the whole thing is a pure formula over on-chain state, you can compute your exact fill before you sign.
The oracle mid is the anchor
Levant is oracle-priced, not order-book-matched. Every open and close executes against the Levant Vault — the shared ERC-4626 liquidity vault that is the counterparty to all trades — at the next verified oracle price. That price is the mid: the fair, un-adjusted reference from which your fill is derived. You escrow collateral on-chain (step 1), then a keeper fills your intent with a signed price report (step 2), so the mid you receive is the next report after your intent lands, not the number displayed when you clicked.
Levant then applies a spread to that mid. The spread is the only price adjustment on the protocol: there is no separate slippage, no price improvement, and no hidden markup. It is fully deterministic — the same trade against the same market state always produces the same spread — and it only ever moves your fill against you.
The spread has three components
The total spread, expressed in basis points of the mid, is the sum of a fixed constant, a linear price-impact term, and a signed skew premium. It is then floored at 0 and capped at 500 bps:
totalSpreadBps = constantSpreadBps // flat, every trade
+ priceImpact // grows with size vs. market depth
+ skew // grows with how much you unbalance the book
priceImpact = notional * 100 / depth1pct
// depth1pct = the notional that moves price 1% (= 100 bps).
// A trade the size of depth1pct therefore pays exactly 100 bps of impact.
// Buys use depth1pctAbove; sells use depth1pctBelow.
skew = skewCoeffBps * signedImbalance / oiCap
// signedImbalance = (book imbalance on the trade's side) + notional/2
// denominator is the OI CAP, not total OI, so a small trade pays a small premium.
// > 0 when the trade pushes the book further out of balance (you pay more);
// <= 0 when it balances the book (contributes nothing after the floor).
totalSpreadBps = clamp(totalSpreadBps, 0, 500) // never better than mid; hard 5% cap- Constant — 0.02% (2 bps). A flat baseline applied to every trade regardless of size. It is the minimum cost of transacting against the vault.
- Price impact — anchored to 1%.
priceImpact = notional * 100 / depth1pct.depth1pctis the notional that moves the price 1%, so it is the denominator of the impact term. On the shipped configdepth1pct = 10,000,000 USDG, so a 10M-notional trade pays a full 100 bps of impact and everything smaller scales linearly down from there. - Skew — denominated in the OI cap.
skew = skewCoeffBps * signedImbalance / oiCap. Because the denominator is the OI cap (shipped:2,000,000 USDG) rather than total open interest, size matters: a small trade pays a small premium and a large trade pays a large one. The shippedskewCoeffBps = 100is the premium a marginal same-side trade pays into a fully skewed book (one side already at the OI cap); a cap-sized trade into a fresh, balanced book pays about half of that (50 bps), because thenotional/2averaging below charges it on the midpoint of the imbalance. If a market'soiCapis unset (0), the skew term is disabled entirely.
The signedImbalance uses your trade's average effect on the book, which is why it adds half your own notional (+ notional/2): your fill is charged on the midpoint between the imbalance before and after your trade, not on the final imbalance. A trade that pushes the crowded side further out pays a positive skew term; a trade that pulls the book back toward balance produces a negative term that is floored away — so it never earns you a rebate, it only stops short of adding a premium.
Buy side vs. sell side
The spread is always applied worse for the incoming trade. Trades that create buying pressure fill above the mid; trades that create selling pressure fill below it. Opening and closing the same position sit on opposite sides — so a round trip pays the spread at both ends.
| Action | Counts as | Fill relative to the mid |
|---|---|---|
| Open long | Buy | mid plus spread (fills above) |
| Close short | Buy | mid plus spread (fills above) |
| Open short | Sell | mid minus spread (fills below) |
| Close long | Sell | mid minus spread (fills below) |
// Applied to the oracle mid, worse-for-trade (1e18 price scale preserved):
execPrice = buy ? mid * (10000 + totalSpreadBps) / 10000 // buy -> execPrice >= mid
: mid * (10000 - totalSpreadBps) / 10000 // sell -> execPrice <= midFloor and cap
Two hard rails bound every spread. The floor at 0 means a fill is never better than mid: a buy never fills below the mid and a sell never fills above it, even when your trade reduces imbalance. The cap at 500 bps (5%) is a safety rail: the spread can never exceed 5% no matter how large the trade or how skewed the book. On the shipped 10M-depth / 2M-cap config an ordinary trade is nowhere near it — you would need a notional many multiples of the entire market's OI cap, and a trade that large would trip the liquidatable-at-open guard or exceed your own slippage tolerance long before the raw spread reached 5%. In practice the cap exists to bound a mis-configured parameter, not to shape an ordinary fill.
A worked example (shipped parameters)
All 20 markets ship with the same config today. Take a retail-sized long into a fresh, balanced book and the spread comes out to just a few basis points:
// Shipped market config (all 20 markets):
constantSpreadBps = 2 // 0.02%
skewCoeffBps = 100 // premium at a FULLY skewed book
depth1pct = 10,000,000 USDG // notional that moves price 1%
oiCap = 2,000,000 USDG // skew denominator
// Retail long into an empty book (longOI = shortOI = 0), 92,000 USDG notional:
constant = 2 bps
priceImpact = floor(92,000 * 100 / 10,000,000) = floor(0.92) = 0 bps
skew = floor(100 * (0 + 92,000/2) / 2,000,000)
= floor(100 * 46,000 / 2,000,000) = floor(2.3) = 2 bps
total = 2 + 0 + 2 = 4 bps (0.04%)
// On a $100,000 mid, the long fills at:
execPrice = 100,000 * (10000 + 4) / 10000 = $100,040Four basis points. A retail trade pays essentially the constant plus a sliver of skew; the price-impact term rounds to zero because 92,000 is a rounding error against 10M of depth. (Each term is integer-divided to whole bps on-chain, which is why the 0.92 and 2.3 above floor to 0 and 2.) The premium only becomes meaningful as your size approaches the depth and cap parameters:
| Trade notional (empty book) | Price impact | Skew | + constant | Total spread |
|---|---|---|---|---|
| 10 USDG (dust) | 0 bps | 0 bps | 2 bps | 2 bps (0.02%) |
| 92,000 USDG (retail) | 0 bps | 2 bps | 2 bps | 4 bps (0.04%) |
| 1,000,000 USDG | 10 bps | 25 bps | 2 bps | 37 bps (0.37%) |
| 2,000,000 USDG (= OI cap) | 20 bps | 50 bps | 2 bps | 72 bps (0.72%) |
Even a trade the size of the entire market's OI cap pays only 0.72%. These figures assume a balanced book; opening on the already-crowded side of a skewed market adds to the skew term (up to the 100 bps a marginal trade pays into a fully one-sided book), while taking the underweight side removes it down to the floor.
Why this replaces order-book slippage
On an order book your effective price depends on how deep you eat into resting orders and who else trades in the same block — slippage is discovered only at execution and is exposed to front-running. Levant removes that uncertainty. The spread is a closed-form function of the mid, your size, and market skew, so your worst-case fill is computable before you sign.
- No order book, no queue. You trade against the vault at the oracle mid, not against resting limit orders that can be pulled or picked off.
- No sandwich MEV. Price comes from the verified oracle and the spread is formula-driven, so a searcher cannot insert trades around yours to move your fill — there is no book to push and no discretionary price to exploit.
- Deterministic and auditable. The same trade in the same market state always yields the same spread, computed on-chain and reproducible by anyone.
Max slippage: your cap on the spread
The spread and the max-slippage tolerance are two different things: the spread is what the engine charges, and your tolerance is the ceiling you place on it. Every open and limit intent carries a mandatory maxSlippageBps in the range [1, 500] — there is no implicit default, because a silent one is how a trader ends up filled far from the price they were shown. In the UI you pick a Max slippage such as 0.10%, 0.30%, 0.50%, or 1.00%.
// At fill time the engine measures how far the spread moved entry from the mid:
deviationBps = (isLong ? entryPrice - mid : mid - entryPrice) * 10000 / mid
if (deviationBps > maxSlippageBps) revert SlippageExceeded
// the intent stays PENDING (not consumed); your escrow is fully reclaimable
// via cancelIntent(). The keeper can retry and fill once the spread narrows
// back inside your tolerance.High-leverage caveat: liquidatable at open
Because the entry spread pushes your fill worse-for-trade, at very high leverage it can, on its own, move a fresh position under its 10% maintenance margin the instant it exists. Levant refuses to mint a position that would be liquidatable at the mark it filled against: executeOpen reverts with LiquidatableAtOpen, the whole transaction unwinds so no open fee is taken, and your intent stays pending and refundable. The engine will not open a position that is dead on arrival.
