Leverage / The mathematics
Leverage
The mathematics
The formulas the contracts run. Integer math truncates. The chain is the source of truth; the trade panel estimate can differ by a unit.
#Units and notation
| Quantity | Representation |
|---|---|
| Money | USDG, 6 decimals. $1.00 is 1e6. |
| Prices | 18 decimals, denoted ONE = 1e18. A $0.50 outcome is 0.5e18. |
| Rates and fractions | Basis points, BPS = 10_000. So 150 is 1.5% and 20_000 is 2.0x. |
#Opening a position
Given a margin m, a leverage L in basis points, a spot price s, and a direction:
#Position size
size = (m × L) / BPS#Entry price
The spread always moves against the trader, and the vault keeps the difference.
long entry = (s × (BPS + spreadBps)) / BPS
short entry = (s × (BPS − spreadBps)) / BPS
clamped into (0, ONE): entry of 0 becomes 1, entry >= ONE becomes ONE − 1#Fee and net margin
fee = (size × openFeeBps) / BPS
netMargin = m − fee
opening reverts if m <= feeNote the base: the fee is a percentage of size, not of margin. At 2x a 1.5% fee therefore consumes 3% of the margin posted, and at 5x it consumes 7.5%.
#Shares
shares = (size × ONE) / entryThese are synthetic. They are the unit the position is marked in, not shares held at the venue.
#The vault reservation
The vault locks the worst it could ever owe on the position, which is not the borrowed amount:
long reserve = shares > size ? shares − size : 0
short reserve = sizeThe reasoning is the payoff structure. A long is worth shares if the price reaches $1.00, so the profit owed is shares − size. A short gains the entire position size if the price reaches zero. Reserving only the leverage top-up would let a few winners leave the vault unable to pay.
#Marking a position
value = (shares × s) / ONE
long pnl = value − size
short pnl = size − valueProfit and loss is signed and computed against size, which is why a 2x position moves twice as fast as the margin would suggest.
#Carry on borrowed capital
borrowed = size > m ? size − m : 0
owed = (borrowed × borrowRateBps × elapsed) / (BPS × 3600)
capped: owed > netMargin -> netMarginelapsedis in seconds since the position opened, so carry accrues continuously rather than in hourly steps.- The base is
size − margin, so a 1x position borrows nothing and pays nothing. borrowRateBpsis stored per position at open, so a later change to the global rate does not apply to it.- The cap matters: once carry would exceed the margin at risk, the position is already liquidatable and the vault takes the whole margin anyway.
#Liquidation
#The condition
Not a comparison against a stored price. The test is whether losses plus carry have eaten the permitted share of net margin:
loss = pnl < 0 ? −pnl : 0
charged = loss + owed
liquidatable when charged >= (netMargin × liquidationThresholdBps) / BPS#The liquidation price
Invert the profit and loss expression for the price at which the loss equals a given budget:
maxLoss = (netMargin × liquidationThresholdBps) / BPS
long loss = size × (1 − P/entry) -> P = entry × (size − maxLoss) / size
short loss = size × (P/entry − 1) -> P = entry × (size + maxLoss) / size
long, if maxLoss >= size -> P = 0
short, if P >= ONE -> P = ONE − 1#Two liquidation prices, and which one to trust
The figure stored at open never moves. The live figure subtracts accrued carry from the loss budget first, which pulls it closer as the position ages:
budget = (netMargin × liquidationThresholdBps) / BPS
maxLoss = budget > owed ? budget − owed : 0
then the same inversion, with this smaller maxLoss#Closing
A partial close takes a fraction f in basis points and scales every component by it:
closedSize = (size × f) / BPS
closedShares = (shares × f) / BPS
closedMargin = (margin × f) / BPS
closedNet = (netMargin × f) / BPS
closedReserve= (reserved × f) / BPS
closedOwed = (accruedFunding × f) / BPS
exit fee = (closedSize × closeFeeBps) / BPSBecause both size and margin shrink by the same fraction, the remainder accrues carry from the original timestamp on a smaller base, and the two pieces sum to what the whole position would have owed. Nothing is double charged and nothing is forgiven. Entry price and liquidation price are unchanged, so the remainder is the same trade in miniature.
Passing the full BPS closes everything. Anything less must leave a margin that still clears the minimum.
#The settlement order
What the trader receives is computed by working down from the net margin being closed. The order is fixed, and each deduction is capped by what is still left, which is how a wiped-out position settles without ever going negative:
remaining = closedNet
profit remaining += pnl (paid out of the vault)
loss loss = min(−pnl, remaining) (absorbed by the vault)
remaining −= loss
carry owed = min(owed, remaining)
remaining −= owed
exit fee fee = min(fee, remaining)
remaining −= fee
payout = remaining- Profit is added before anything is deducted, so a winning position pays its carry and exit fee out of the enlarged balance.
- Each of the three deductions is capped at what remains. A position whose loss consumed the whole margin therefore pays no carry and no exit fee, not because they are waived, but because there is nothing to take.
- The floor is zero. A trader can lose the entire margin and no more, and the vault cannot claim beyond it.
Losses and liquidated margin are credited to the vault by a different path than fees and carry, which is why the two have separate splits.
#Liquidation and the emergency exit
liquidated absorbed = netMargin (trader receives nothing)
emergency close refund = netMargin (trader receives all of it)The symmetry is the point. Both bypass the profit and loss calculation entirely. One because the margin is spent, the other because no trustworthy price exists to settle against. In both cases the entry fee stays with the vault, having been collected at open, and no exit fee is charged.
#Worked example
A 2x long on a $0.50 outcome with $2.50 of margin, at the default parameters:
| Quantity | Working | Result |
|---|---|---|
| Size | 2.50 × 20000 / 10000 | $5.00 |
| Entry price | 0.50 × 10100 / 10000 | $0.505 |
| Entry fee | 5.00 × 150 / 10000 | $0.075 |
| Net margin | 2.50 − 0.075 | $2.425 |
| Shares | 5.00 / 0.505 | 9.900990 |
| Vault reservation | 9.900990 − 5.00 | $4.900990 |
| Max loss | 2.425 × 0.90 | $2.1825 |
| Liquidation price | 0.505 × (5.00 − 2.1825) / 5.00 | $0.284568 |
Worth reading the last row carefully: liquidation is a 43% fall from the $0.50 spot price, not the 20-odd percent that “2x with a 90% threshold” might suggest at a glance. The threshold applies to net margin, and the loss is measured against size.
Note also that the vault reserves $4.90 against a position the trader entered with $2.50, nearly twice the borrowed amount. That is the cost of reserving the true worst case, and it is why a $100 vault at the 30% exposure cap backs about six concurrent $5 positions rather than twelve.
#Capacity
Two independent ceilings, and the binding one is whichever is lower:
used = lockedAssets
byExposure = (totalAssets × maxPoolExposureBps) / BPS
byLiquidity = used + freeAssets
ceiling = min(byExposure, byLiquidity)
available = ceiling > used ? ceiling − used : 0The exposure ceiling is the risk limit, a deliberate cap on how much of the vault may be committed. The liquidity ceiling is physical: capital that is not there cannot be reserved regardless of what the risk limit permits.
A position is rejected if its reservation exceeds what remains available, and the check runs before any transfer, so hitting a full pool costs the trader nothing but gas and returns a distinguishable error rather than a generic failure.
#Available leverage
Read from the tier schedule against live vault assets, then capped:
walk the tiers while totalAssets >= tier.minTvl,
taking the last matching tier.maxLeverageBps
result = min(tierLeverage, maxLeverageBps)
default schedule
$0 -> 20_000 (2.0x)
$1,000 -> 30_000 (3.0x)
$5,000 -> 40_000 (4.0x)
$20,000 -> 50_000 (5.0x)A replacement schedule must start at zero assets, ascend, and contain no row above the ceiling. Lowering the ceiling caps the result immediately, whatever the schedule says, which is the emergency brake.
#Vault share accounting
totalAssets = seniorAssets + juniorAssets
freeAssets = totalAssets > lockedAssets ? totalAssets − lockedAssets : 0
deposit shares = totalShares == 0 || seniorAssets == 0
? assets
: (assets × totalShares) / seniorAssets
withdraw assets = (shares × seniorAssets) / totalShares
reverts if assets > freeAssets
holding assetsOf(lp) = (sharesOf[lp] × seniorAssets) / totalShares#How income is split
fees toSenior = (amount × feeSeniorBps) / BPS
toJunior = amount − toSenior
absorbed margin toSenior = (amount × liquidationSeniorBps) / BPS
toJunior = amount − toSenior
both default to 7_000, i.e. 70% seniorBoth add to the tranche totals without minting shares, which is exactly why the share price rises rather than balances changing.
#How losses are paid
fromJunior = amount > juniorAssets ? juniorAssets : amount
fromSenior = amount − fromJunior
reverts if fromSenior > seniorAssetsThis is the first-loss rule in three lines: junior is drained to zero before senior is touched at all. The revert should be unreachable while the exposure cap holds, and exists because a silent underflow here would corrupt every depositor’s share price.
#Price feed constraints
| Rule | Default | Effect |
|---|---|---|
| Maximum price age | 5 minutes | Older than this is treated as no price; opening halts. |
| Maximum deviation per update | 20% | A larger gap is walked in over several updates rather than applied at once. |
| Converging | n/a | True while the stored price differs from the reported target. Opening reverts; closing and liquidation stay available. |
The clamp is computed on-chain from the true reported midpoint, so the contract knows the size of the gap itself. A compromised reporter cannot hide one by flattening it before submission.
#Where rounding falls
All of the above is integer arithmetic with truncating division. The directions are worth knowing:
sharestruncates down, so a trader receives marginally less exposure than the exact quotient.- Fees truncate down, which favours the trader by at most one unit, and is precisely why a minimum margin exists, since below roughly $0.67 a 1.5% fee truncates to zero.
- The senior share of income truncates down and the junior tranche receives the remainder, so the buffer collects the dust.
- Deposit shares truncate down, so a depositor never mints more claim than they paid for.
#Panel vs chain
The browser quotes in floating point. The contract uses integer division. If they disagree, the contract is right. Read quoteOpen on-chain for the number you will be held to. Markets are keyed by the hash of the slug. No venue ids on-chain.
Defaults above are deploy-time and admin-settable. Leverage markets for traders, Earning as an LP for the vault.