Documentation

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. depth1pct is the notional that moves the price 1%, so it is the denominator of the impact term. On the shipped config depth1pct = 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 shipped skewCoeffBps = 100 is 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 the notional/2 averaging below charges it on the midpoint of the imbalance. If a market's oiCap is 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.

ActionCounts asFill relative to the mid
Open longBuymid plus spread (fills above)
Close shortBuymid plus spread (fills above)
Open shortSellmid minus spread (fills below)
Close longSellmid 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 <= mid

Floor 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.

Note
The spread is entirely separate from trading fees. The open fee (0.08% of gross notional, deducted from collateral at open) and the close fee (0.08% of adjusted size at close) are charged on top of the spread-adjusted fill, not baked into it.

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,040

Four 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 impactSkew+ constantTotal spread
10 USDG (dust)0 bps0 bps2 bps2 bps (0.02%)
92,000 USDG (retail)0 bps2 bps2 bps4 bps (0.04%)
1,000,000 USDG10 bps25 bps2 bps37 bps (0.37%)
2,000,000 USDG (= OI cap)20 bps50 bps2 bps72 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.
Tip
Set your max slippage to the widest spread you are willing to pay for that trade. If the computed spread exceeds it, the fill reverts and nothing happens — your collateral stays escrowed and you can cancel for a full refund or wait for the market to calm down. A tolerance is protection, not a target: it never makes your fill wider, it only rejects fills that are too wide.

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.

Warning
The most important thing to internalize: the spread is only ever charged against you and is never a rebate. A buy never fills below mid and a sell never fills above it, and opening then closing pays it twice. At extreme leverage the entry spread alone can trip the liquidatable-at-open guard — size your leverage so the spread does not eat your maintenance buffer before the trade even starts. This is unaudited testnet software; tokens have no monetary value and leverage can lose your entire margin.