Margin, mark price, funding, liquidation and the insurance fund as the contracts compute them: formulas, precision, rounding and worked examples. The live panels at the end are read from the vault; the examples are not.
Each position holds its own margin. Nothing else backs it, and nothing else is at risk when it fails.
A position is one signed quantity per account and market. Its margin is collateral moved from the account’s available bucket into the locked bucket of the vault, and only that margin can be lost on that position. Up to 32 positions per account may be open at once; each is independent.
Initial margin
Opening or increasing a position requires initialMarginFraction (IMF) of the new notional, where IMF = 1 / maximum leverage. The launch markets use 20x for BTC, ETH, SOL and the indices (IMF 5%), 10x for HYPE, equities and metals and oil (10%), and 5x for natural gas (20%).
margin = |qty| × price × IMFMargin locked when a fill opens or increases exposure. Rounded up.
Maintenance margin
A position may be liquidated when its equity, margin plus unrealized PnL at the mark, falls below maintenanceMarginFraction (MMF) of its notional at the mark. In the launch catalogue MMF is half the IMF.
An order reserves, at placement, the initial margin and the taker fee for its full quantity at its limit price. The reservation moves from available to reserved, returns on cancellation or expiry, and is released in proportion as the order fills (the fill then locks the real margin and charges the real fee). Reduce-only orders reserve nothing.
reserved = notional × IMF + notional × takerFeeorderReservation in @elysta/protocol, mirroring reserveForOrder.
Adding and removing margin
A position’s owner can add margin from available at any time, and remove it as long as the position stays at or above its initial margin requirement at the mark with funding settled first. There is no cross-margin: a healthy position never covers an unhealthy one.
Mark price
The mark is what unrealized PnL, liquidation and funding read. It is derived from the validated index and the live book, never from the last trade.
mark = clamp(mid, index − index × markBandBps, index + index × markBandBps)markPrice in the risk engine. markBandBps is 100 (1%) on every launch market.
Two-sided book: the mid of the best bid and best ask, clamped to the band around the index.
One-sided or empty book: the index itself.
Invalid index: there is no mark. Liquidation, funding settlement and margin removal revert with OracleInvalid; the market is halted.
Three prices are therefore never conflated: the index (the validated reference from the registry), the mark (above), and the last trade (a fact about the book, used by charts and nothing else). Market orders use the mark too: their protective limit is the mark moved by maxImpactBps (1% at launch), tightened by the trader’s own protection price.
Funding
Funding keeps the mark near the index by moving collateral between longs and shorts at every interval. The rate is computed on chain from a time-weighted premium; no service chooses it.
Premium accrual
On every state change of a market, and whenever anyone calls accruePremium, the engine adds premium × elapsed seconds to the market’s accumulator, where premium is (mark − index) / index. Seconds during which the index was invalid add nothing: a halted market neither pays nor receives funding for the gap.
Settlement
At each interval boundary (every 60 minutes at launch) settleFunding, callable by anyone, turns the average premium into a rate. Premiums are quoted per 8 hours, the industry reference period, and prorated to the market’s interval, so an hourly interval pays one eighth of the 8-hour premium. The rate is clamped to maxFundingRatePerInterval (0.0375% per interval (0.000375)).
rate = clamp(premiumTwap × intervalSeconds / 28,800, −cap, +cap)
cumulativeIndex += rate × marksettleFunding. premiumTwap is the accumulator divided by the window length.
Payment
A position pays or receives qty × (cumulativeIndex now − cumulativeIndex at its last settlement) whenever it is touched: on a fill, a liquidation or a margin change. A positive rate means longs pay shorts; a negative rate means shorts pay longs. Payments owed are taken from the position’s margin (and, should the margin not suffice, from the insurance fund, which halts the market if it cannot cover); payments received are added to margin.
payment = qty × Δ cumulativeIndexfundingPayment in @elysta/protocol. Positive: the account pays.
Liquidation
Permissionless, at the mark price, partial where a smaller quantity restores health and full otherwise.
Who and when
Anyone except the position’s owner may call liquidate(account, marketId, maxQty) on a position whose equity is below maintenance margin, in a market that is not halted or inactive, with a valid index. maxQty is the most the liquidator is willing to take over; the call reverts with LiquidationQtyTooSmall if that is less than the quantity the formula requires.
How much
A partial liquidation leaves the remaining equity in the position and must bring it back to the initial margin ratio after the fee. The engine solves for the smallest quantity that does so, rounds it up to the lot, and liquidates everything if the result would be the whole position or would leave less than the minimum order quantity.
q = (|Q| × mark × IMF − equity) / (mark × (IMF − fee)), rounded up to a lot
full if equity ≤ 0, q ≥ |Q|, or |Q| − q < minOrderQty_liquidationQty. IMF and fee are WAD fractions; fee is liquidationFeeBps / 10,000.
What happens
Funding is settled for both the position and the liquidator.
PnL on the liquidated quantity is realized at the mark: a gain is added to the margin; a loss is taken from it, and past the margin from the insurance fund.
The penalty, liquidationFeeBps (1%) of the liquidated notional, is taken from the remaining margin (never more than remains) and split: liquidatorShareBps (50%) to the liquidator’s available collateral, the rest to the insurance fund.
The liquidator takes over the quantity at the mark on the same side, locking its own initial margin for it, subject to the market’s position limit.
On a full liquidation whatever margin remains after loss and penalty is returned to the trader’s available collateral.
Liquidated and two PositionChanged events record it all; if any bad debt was recorded the market is halted with reason BadDebt.
Liquidation price
For a long, the mark at which the position becomes liquidatable is (entry − margin / |Q|) / (1 − MMF); for a short, (entry + margin / |Q|) / (1 + MMF). It moves as margin is added or removed and as funding is settled into margin. The terminal shows it from liquidationPrice() on the risk engine.
Insurance fund and the loss waterfall
Losses are paid in a fixed order, and the order is visible on chain at every step.
The position’s margin. A loss, a funding payment or a liquidation penalty is taken from the position’s own locked margin first.
The insurance fund. Whatever the margin could not cover is requested from the fund (coverFromInsurance). The covered amount moves into the PnL pool, where it backs the counterparties’ gains in full.
Bad debt. Whatever the fund could not cover is recorded as bad debt (BadDebtRecorded), the market is halted with reason BadDebt, and the status page shows the total. A bad-debt halt is never lifted automatically: a market manager lifts it after the fund has been replenished.
The fund is credited by 50% of every trading fee, by the insurance share of every liquidation penalty, and by voluntary contributions through fundInsurance. In this version no function pays it out: it can only grow or cover losses. When the collateral is the test dollar, the fund is seeded with it at deployment.
There is no auto-deleveraging. The thesis requires any such mechanism to be separately specified, simulated and tested before it is enabled, and none has been.
Precision and rounding
Every price, quantity, notional, collateral amount and fraction on chain is an 18-decimal integer (WAD). The direction of rounding is fixed per rule and always favours solvency.
Prices are USD per unit of the underlying, quantities are units of the underlying, collateral is USD. Token decimals are normalised once, at the vault’s edge: a deposit of 1,000.000000 tUSD (6 decimals) becomes 1,000 × 1018 in the ledger, and scale = 1012. Basis-point parameters are the only non-WAD numbers and are always named *Bps.
Quantity
Rounds
Why
Notional (qty × price)
Down
Never overstate exposure.
Initial and maintenance margin
Up
Against the trader: slightly more is required than the exact fraction.
Trading fees
Up
Against the trader.
Funding owed by the payer
Up
Against the payer; the receiver’s credit rounds toward zero.
Realized and unrealized gains
Down
Never create collateral.
Realized and unrealized losses
Up
Never understate a loss.
Margin released on a partial close
Down
The dust stays in the position’s margin until it closes.
Liquidation quantity
Up, then up to a lot
Liquidate enough to restore health, never too little.
Penalty, incentive and insurance split
Down (basis points of notional)
Capped at the margin that remains.
The dust these rules leave between a gain rounded down and the matching loss rounded up stays in the vault’s PnL pool, so rounding can never create collateral. The terminal’s estimates use the same functions (@elysta/protocol’s mulWad, mulWadUp, divWadUp) so that what you see before signing is what the chain computes.
Oracle validation
The registry turns adapter observations into one validated index, and refuses to trade on anything less.
On every refreshIndex the registry reads the market’s primary adapter, falls back to the secondary when the primary is missing or stale, and accepts a price only when all of the following hold:
The price is positive and the observation is no older than heartbeatSeconds (90 s for crypto, 180 s for scheduled markets at launch).
The move from the last valid price is within maxDeviationBps (2%), or within reopenDeviationBps (20%) when more than reopenGapSeconds (2 h) have passed since the last accepted update, because a market reopening after a closed session may gap.
Otherwise the price is held as pending. If later observations stay consistent with it for deviationConfirmSeconds (120 s) the move is confirmed and adopted; if they return to the old level the pending price is discarded.
While a market has no acceptable price its status becomes Halted, the safe state: no orders, no matching, no liquidation, no funding settlement. Open positions keep their margin and can still be cancelled out of resting orders. A fresh valid price lifts an oracle halt automatically (MarketStatusChanged, reason OracleRecovered); an oracle manager can also lift it by hand after review, optionally adopting the pending price. A halt caused by bad debt is never lifted by a price.
Launch oracle
The adapter is fed by Elysta’s own keeper from HyperCore’s published oracle prices. The registry treats it like any adapter and validates every observation; the adapter is isolated behind IOracleAdapter so that a decentralised feed can replace it market by market. A deployment that settles real collateral must not rely on a single-updater adapter, and the roadmap says so; today’s deployments settle in test collateral.
Worked examples
Computed with the bigint functions of @elysta/protocol on the BTC-USD launch parameters (20x, 0.1 tick, 0.0001 lot). They illustrate the rules; they are not live data and no market is at these prices.
Example 1
Placing and filling a long
Worked example · not live data
A trader buys 0.5 BTC with a limit order at 60,000 on a market with 20x maximum leverage (initial margin fraction 5%, taker fee 0.05%).
Inputs
Quantity
0.5000 BTC
Limit price
60,000.0 USD
Initial margin fraction
5.00%
Taker fee
0.05%
Notionalqty × price, rounded down
30,000.00 USD
Initial marginnotional × IMF, rounded up
1,500.00 USD
Taker feenotional × takerFee, rounded up
15.00 USD
Reserved on placementinitial margin + taker fee
1,515.00 USD
If 0.2 BTC fills firstreservation × 0.2 / 0.5 is released, rounded down
606.00 USD
Fee split on a full fillinsuranceShareBps 50%
7.50 USD to the insurance fund, 7.50 USD to protocol fees
The position opens with 1,500.00 USD of isolated margin locked and 15.00 USD charged as a taker; it becomes liquidatable if the mark falls to 58,461.53 USD.
Example 2
Mark price from index and book
Worked example · not live data
The mark is the book mid clamped to ±1% (markBandBps 100) around the validated index. It is what unrealized PnL, liquidation and funding read.
Inputs
Index price
60,000.0 USD
Mark band
±600.0 USD (1%)
Book 59,990 / 60,010mid 60,000 is inside the band
60,000.0 USD
Book 60,900 / 61,000mid 60,950 exceeds index + band, so it is clamped
60,600.0 USD
Bid only, no askno two-sided quote: the index itself
60,000.0 USD
A thin or one-sided book cannot move the mark more than 1% from the index, and an empty book cannot move it at all.
Example 3
An hourly funding settlement
Worked example · not live data
Over one hour the mark averaged 0.08% above the index (the time-weighted premium). The interval is 3,600 s; the cap is 0.0375% per interval.
Inputs
Premium TWAP
0.08%
Interval
3,600 s (1 h)
Reference period
28,800 s (8 h)
Mark at settlement
60,000.0 USD
RatepremiumTwap × 3,600 / 28,800, clamped to ±cap
0.0100%
Payment per unitrate × mark, added to the cumulative funding index
6.0000 USD per BTC
A long of 0.5 BTCqty × index delta; positive means the account pays
pays 3.00 USD
A short of 0.5 BTC
receives 3.00 USD
If the premium had been 1%raw rate 0.1250% exceeds the cap
clamped to 0.0375%
Longs pay shorts when the premium is positive, shorts pay longs when it is negative, and no single interval can move more than the cap.
Example 4
A partial liquidation
Worked example · not live data
The long from the first example (0.5 BTC at 60,000 with 1,500 USD of margin) is marked at 58,000. Maintenance margin fraction is 2.5%, the liquidation fee 1% of liquidated notional, split half to the liquidator and half to the insurance fund.
Inputs
Position
long 0.5000 BTC at 60,000.0 USD
Margin
1,500.00 USD
Mark
58,000.0 USD
Liquidation price
58,461.53 USD
Unrealized PnLqty × (mark − entry), a loss rounded up
-1,000.00 USD
Equitymargin + PnL
500.00 USD
Maintenance margin|Q| × mark × MMF, rounded up
725.00 USD — equity is below it, so the position is liquidatable
Required initial margin|Q| × mark × IMF
1,450.00 USD
Quantity to liquidate(required − equity) / (mark × (IMF − fee)), rounded up
0.409482758620689656 BTC exact
Rounded up to the lotlot 0.0001; the remainder 0.0905 is at least the minimum order
0.4095 BTC (partial)
Loss realised on that quantity at the mark
819.00 USD
PenaltyliqQty × mark × 1%, capped at the margin left
237.51 USD
Liquidator incentive / insurance share50% / 50% of the penalty
118.755 USD / 118.755 USD
Margin left on the remaining 0.0905 BTC
443.49 USD against 262.45 USD required
The liquidator's new longtakes over liqQty at the mark and must lock its own initial margin
0.4095 BTC at 58,000.0 USD, margin 1,187.55 USD
0.4095 BTC is taken over at 58,000.0 USD; the trader keeps 0.0905 BTC with 443.49 USD of margin, back above the initial requirement.
Example 5
The loss waterfall after a gap
Worked example · not live data
The same long is marked at 56,000 after a price gap: the loss exceeds the position's own margin.
Inputs
Position
long 0.5000 BTC at 60,000.0 USD, margin 1,500.00 USD
Mark
56,000.0 USD
Unrealized PnL
-2,000.00 USD
Equitymargin + PnL, at or below zero
-500.00 USD — full liquidation
Step 1: the position's marginthe whole margin is debited
1,500.00 USD
Step 2: the insurance fundcoverFromInsurance(shortfall)
500.00 USD requested
With a fund of 250,000 USD
500.00 USD covered, no bad debt; the fund falls to 249,500.00 USD
With a fund of only 200 USDcovered = min(shortfall, fund)
200.00 USD covered, 300.00 USD recorded as bad debt, market halted (reason BadDebt)
Penalty280.00 USD by formula, capped at the margin left
0.00 USD: nothing remains, so the liquidator earns no incentive
The counterparties' gains are still paid in full: the covered amount moves from the insurance fund into the PnL pool. Anything the fund cannot cover is bad debt, visible on the status page, and the market stays halted until a market manager lifts it after the fund is replenished.
Example 6
Where rounding goes
Worked example · not live data
Every amount is an 18-decimal integer. When a result does not fit, the direction of rounding is fixed by the rule, never by the caller.
Inputs
WAD
1e18 = 1.000000000000000000
tUSD token unit
1e-6 USD = 0.000001000000000000 in the ledger
Closing 0.1 of a 0.3 BTC position with 1,000 USD marginmargin × 0.1 / 0.3, rounded down
333.333333333333333333 USD released; the last 1e-18 stays in the position's margin
950 / 2,320 as a quantitywadDiv rounds down, wadDivUp rounds up
0.409482758620689655 vs 0.409482758620689656
Gains and lossesa gain rounds down, the matching loss rounds up
the difference accumulates in the vault's PnL pool
WithdrawalstokenAmount × scale ≤ available
a balance smaller than one token unit cannot be withdrawn and stays in the ledger
Rounding can only ever favour the vault's solvency: no rule rounds in a direction that could create collateral.
Live figures
Read from the vault through the API and refreshed while you read. Each panel says where its figures came from and at which block; when the API cannot be reached, it says that instead.
Live data arrives with the Elysium mainnet launch
This panel reads the exchange API, which goes live with the Elysium mainnet launch. Until then there is nothing to show, and nothing here is simulated.
Live data arrives with the Elysium mainnet launch
This panel reads the exchange API, which goes live with the Elysium mainnet launch. Until then there is nothing to show, and nothing here is simulated.
Live data arrives with the Elysium mainnet launch
This panel reads the exchange API, which goes live with the Elysium mainnet launch. Until then there is nothing to show, and nothing here is simulated.
The status page shows the same vault figures beside the health of every service and oracle feed, refreshed every ten seconds.