T23 · Perp DEX
How do margin, funding, and a risk engine form one system?
- Capabilities practiced
- BuilderFinancial Literacy
- Hands on
- Implement position and margin calculations, simulate cascading liquidations, and record insurance-fund usage.
- AI Lab
- Have AI design a funding-rate formula. Backtest whether it pulls the price toward spot using historical data.
A Real-World Problem
Your perpetual trading venue has been live for three weeks. Most of your work went into matching: the order book, price-time priority, partial fills, cancellations, and event feeds. It runs cleanly. Latency is steady under load, and every fill is recorded.
Then one night the underlying asset drops 18% in twelve minutes.
The next morning, every subsystem log looks normal:
- Matching did not stall; every fill reached the database.
- The liquidation engine triggered 214 times, all successfully.
- The price source kept updating, and none of T21's four checks raised an alarm.
Yet the books do not balance.
A perpetual market is a zero-sum ledger: every dollar a long earns must be a dollar a short loses. The day's aggregate position P&L should be zero. Instead it is negative: the system owes users money.
You trace the difference. Thirty-one long positions were closed after their losses exceeded the margin they posted. The counterparties' gains are real, but the losing side has no funds left to pay. Not one line of your three-week matching implementation is wrong, and it cannot help.
Who owns the hole, and who fills it?
Thought Experiment
Strip away the exchange. Keep one sheet of paper and one person. The sheet says A is long ten units, B is short ten units, and the underlying price is 100. For each one-unit price move, one pays the other ten.
The person's job is not matching; A and B already matched. Their only job is to ensure every balance on the paper can always be paid. Now assume A and B posted only 50 margin each, rather than 1,000.
As price moves, four questions arise. They are the whole chapter.
First, how much does each person have right now? At 103, A has an unrealized gain of 30 and B an unrealized loss of 30. B has only 20 equity left. This must be computable at any moment, not only when the position closes.
Second, when must someone be removed? If B is removed only when equity reaches zero, price is at 105. Can the position close exactly at 105? No: execution takes time and price does not wait. The system must act earlier, while B still has money. The amount remaining at the trigger is a parameter you must write down.
Third, who covers a late close? Price jumps from 104 to 108, leaving B with negative 30 equity. A should receive 80, but B contributed only 50. Someone must provide that missing 30 for the ledger to balance. Leaving it pending makes A's balance fictional.
Fourth, what if everyone wants to go long? The sheet requires one long for each short. If a hundred want to go long and only three want to short, who takes the other ninety-seven?
The answer to the fourth question is the funding rate from Chapter 18: put a price on occupying the crowded side so payments encourage movement toward the scarce side. That chapter explained why funding holds the price near its anchor. This one asks how to implement it.
Together, the four questions define a machine that continuously reads prices, recalculates equity, closes positions before equity runs out, and finds someone to cover shortfalls when it acts too late.
Matching decides who trades with whom. This machine decides whether the venue can pay its debts.
Your Decision
Return to the thirty-one bankrupt positions. The shortfall is a definite number; someone must bear it today.
Who do you choose?
What Happens
The options all answer one question: who bears the zero-sum ledger's missing amount today?
| Bearer | Predictable to users? | When used | Main cost |
|---|---|---|---|
| Unsettled bad debt | No | Never resolved | First-come, first-served run |
| Dedicated fund | Yes | First fallback | Finite size; denomination may fall too |
| Proportional haircut | No | After fund exhaustion | Unpriceable loss source |
| Forced close of winners | Partly | Last defense | Correct traders lose part of a profitable position |
The first row is the only truly wrong choice. The other three can be layers of one defense. In sequence they form the chapter's skeleton:
- Liquidate at the maintenance margin line
- Use the position’s remaining margin
- Use the dedicated fund
- Force-close profitable counterparts
State the condition for bankruptcy as an inequality. It has the same shape as T22's:
A position goes bankrupt when:
Mark-price movement between liquidation trigger and completed close
>
Maintenance margin rate + portion reserved for liquidation
Where:
Left side = market speed × liquidation delay ← not under your control
Right side = your parameters ← design choicesTwo differences from T22 are why this chapter exists: the right-hand buffer is an order of magnitude smaller (lending may have twenty-plus percentage points, while high-leverage perpetual maintenance margins may be a few percent or less), and the gap cannot be carried (a lender can account for bad debt over time; a perp venue must settle with a user today).
Therefore, a perpetual venue is fundamentally a continuously running risk engine; matching is its shell. Matching decides fill quality. The risk engine decides whether one night leaves it owing users money.
Build a Model
Consider five components in the order they respond to a price change.
1. Mark price: the foundation for every decision
A perpetual market has three prices. Confusing them is one of its costliest errors:
| Name | What it is | Use |
|---|---|---|
| Index price | Weighted prices from external spot venues | Funding baseline and mark-price input |
| Mark price | Index price with a bounded deviation | P&L and liquidation |
| Last trade | Most recent fill on this venue | Display and matching |
Liquidation must use the mark, not the last trade. The last trade is set by this venue's own order book, which one trade can move. Using it lets anyone willing to hit a thin book decide which positions liquidate.
The simplest mark uses the external index as an anchor and allows trades to deviate only within a band:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
uint256 constant BPS = 10_000;
/// Anchor the mark to the external index and allow only a small deviation
function markPrice() public view returns (uint256) {
uint256 index = priceGuard.readPrice(); // Includes T21's four checks
uint256 last = lastTradePrice;
uint256 upper = index * (BPS + markBandBps) / BPS; // Configurable; often tens to hundreds of bps
uint256 lower = index * (BPS - markBandBps) / BPS;
if (last > upper) return upper;
if (last < lower) return lower;
return last;
}The snippet's value is raising attack cost from moving your own book to moving the external spot market. External market depth is the numerator of T21's safety margin. All of T21 lives inside readPrice(). If it returns a manipulated value, the next four components fail while executing normally and raising no error.
2. Positions and margin: equity available at any instant
int256 constant WAD = 1e18;
struct Position {
int256 size; // Positive for long, negative for short; underlying units
uint256 margin; // Margin posted for this position
uint256 entryPrice; // Mark price at opening
int256 entryFunding; // Cumulative funding index at opening; see next section
}
/// Unrealized P&L: signed size handles longs and shorts in one expression
function unrealizedPnl(Position memory p, uint256 mark) pure returns (int256) {
return p.size * (int256(mark) - int256(p.entryPrice)) / WAD;
}
/// Notional = absolute position size × mark price
function notional(Position memory p, uint256 mark) pure returns (uint256) {
int256 s = p.size >= 0 ? p.size : -p.size;
return uint256(s) * mark / uint256(WAD);
}A signed size is the important design choice: long and short P&L, funding, and liquidation share formulas instead of branching in every function. Branches almost inevitably create asymmetric boundary errors.
3. Funding: you cannot iterate over positions
Chapter 18 explained why funding anchors prices. Engineering imposes a hard constraint: you cannot iterate through every position every eight hours to collect payments. There may be tens of thousands; one onchain call has no such budget.
Use the same pattern as T22 interest: maintain a global cumulative index, and store its opening value in each position. Funding owed at any moment is a subtraction:
int256 public cumulativeFunding; // Cumulative amount owed per unit of long size, signed
uint256 public lastFundingAt;
/// Accrue funding since the last update into the index. O(1) regardless of position count
function accrueFunding(uint256 mark, uint256 index) internal {
uint256 elapsed = block.timestamp - lastFundingAt;
if (elapsed == 0) return;
// Premium: deviation of mark from index, scaled by WAD
int256 premium = (int256(mark) - int256(index)) * WAD / int256(index);
// Rate: premium spread per second plus interest term, then clamp it
int256 rate = premium / int256(fundingPeriod) + interestPerSecond;
if (rate > fundingCapPerSecond) rate = fundingCapPerSecond;
if (rate < -fundingCapPerSecond) rate = -fundingCapPerSecond;
cumulativeFunding += rate * int256(elapsed) * int256(index) / WAD;
lastFundingAt = block.timestamp;
}
/// Positive means the position pays; negative means it receives
function fundingOwed(Position memory p, int256 cumulative) pure returns (int256) {
return p.size * (cumulative - p.entryFunding) / WAD;
}
/// Equity = margin + unrealized P&L - funding owed
function equity(Position memory p, uint256 mark, int256 cumulative) pure returns (int256) {
return int256(p.margin) + unrealizedPnl(p, mark) - fundingOwed(p, cumulative);
}Three parameters need explicit decisions. All are configurable; none has a universal value:
| Parameter | Determines | If wrong |
|---|---|---|
fundingPeriod | How long the premium is spread over | Too long weakens the anchor; too short charges repeatedly even in calm markets |
fundingCapPerSecond | Maximum force of the anchor | Too narrow and it saturates during extremes, adding no more pressure |
| Charge basis | Notional or margin | These differ by leverage; using the wrong one creates a scale error |
The second row is often skipped. The cap is not just a safety setting; it limits the anchor's pull. Beyond it, a larger divergence no longer produces a larger payment. Arbitrageurs alone must restore price, precisely when they are most likely to retreat.
Another code requirement: accrue funding before checking liquidation. An idle position can cross maintenance purely through accumulated funding. Omit that update and apparently healthy positions may have needed liquidation long ago.
4. Liquidation: settle the ledger here
error NotLiquidatable();
/// Liquidatable when equity falls below the maintenance requirement
function isLiquidatable(
Position memory p,
uint256 mark,
int256 cumulative,
uint256 maintenanceBps // Configurable maintenance rate, often tens to hundreds of bps, tiered by size
) pure returns (bool) {
int256 e = equity(p, mark, cumulative);
if (e <= 0) return true;
return uint256(e) <= notional(p, mark) * maintenanceBps / BPS;
}
function liquidate(address trader) external {
Position storage p = positions[trader];
uint256 mark = markPrice();
accrueFunding(mark, priceGuard.readPrice()); // Settle funding before the decision
if (!isLiquidatable(p, mark, cumulativeFunding, maintenanceBps)) revert NotLiquidatable();
int256 e = equity(p, mark, cumulativeFunding);
uint256 fee = notional(p, mark) * liquidationFeeBps / BPS; // The liquidator's entire incentive
if (e > int256(fee)) {
_payout(msg.sender, fee); // Fee to liquidator
_payout(trader, uint256(e) - fee); // Return remainder to trader
} else if (e > 0) {
_payout(msg.sender, uint256(e)); // Only part of fee can be paid
} else {
// Negative equity: bankruptcy. Find a payer for the gap in this transaction
_coverShortfall(uint256(-e));
}
_closePosition(trader);
}
function _coverShortfall(uint256 gap) internal {
emit ShortfallCovered(gap);
if (insuranceFund >= gap) {
insuranceFund -= gap;
return;
}
uint256 remaining = gap - insuranceFund;
insuranceFund = 0;
_autoDeleverage(remaining); // Rank winners by profit and leverage; force-close a portion
}_coverShortfall is the one branch in the contract that must not revert. It may exhaust the fund and call the last defense, but it must return because the ledger must balance in this transaction.
Compare T22: lending's _recordBadDebt means “record now and resolve later.” Perpetuals' _coverShortfall means “find the funds now.” The same location has two different obligations.
5. Why liquidators arrive
As in T22, liquidators have no salary or duty. They appear only when notional times the liquidation fee exceeds gas plus slippage in closing the position. Thus the failure modes overlap: small positions are unprofitable, congestion destroys economics, and nine of ten competitors waste fees. The outcome differs: lending bad debt accumulates, while perpetuals can leave someone unable to withdraw today.
What It Is Called
A user's open exposure in this market: direction, size, entry price, and posted margin.
Represent direction with a signed quantity rather than a boolean so P&L, funding, and liquidation share formulas. Splitting long and short logic tends to fail at asymmetric boundaries.
Principal posted to support a leveraged position.
Distinguish initial margin, which limits position size, from maintenance margin, which triggers liquidation. Also distinguish margin modes: isolated margin gives a liquidation price calculable at opening; under cross margin that price moves continuously with P&L on other positions. Do not treat the opening estimate as a constant.
The price used for P&L and liquidation, anchored to an external index with only bounded deviation.
Its purpose is to move liquidation decisions from a thin market to a deep one. Replacing it with the last trade lets anyone trigger liquidation by moving a shallow book, a classic category of perpetual-market incident.
Periodic payments between long and short sides, based on deviation of mark from index.
It is not a protocol fee: money moves among users. Onchain implementation cannot iterate through positions; it needs a cumulative index with each position's entry value. Check three parameters: period, cap, and charge basis. The cap sets the anchor's maximum force.
Dedicated money to cover bankrupt positions, usually funded by liquidation surplus and retained fees.
Ask what asset it holds: the venue's own token may shrink during the same crisis. Also ask its size relative to open interest. Absolute fund size alone says little; open interest is the stock of leveraged exposure it must back.
When the fund cannot cover a gap, forcibly close part of profitable opposing positions according to a ranking.
It is the final defense and a distinctive perpetual risk: you may trade in the right direction, have a profit, and still be closed by the rules. Publish the ranking so users know where they stand.
Hands-on
Implement the central structure and four pure functions. Define Position and unrealizedPnl, notional, fundingOwed, and equity. Use a signed size.
Start with pure functions; verify every one by hand:
- A long of ten units entered at 100 and marked at 103 has 30 unrealized profit. An equally sized short (negative size) loses 30.
- If the cumulative funding index rises from 0 to 2, a ten-unit long owes 20 and the short receives 20.
- Funding across both sides must sum to zero. This is the first zero-sum test and should remain true in later tests.
Implement the mark and funding accrual. Use an index plus band for the mark and T21's PriceGuard as the source, retaining all four checks. With a controllable stub feed, verify three things: a last trade inside the band is returned; one outside returns the clamped boundary, not the trade; and an expired source makes the liquidation path follow the fallback policy you explicitly chose in T21.
Implement liquidation and both fallbacks. Write every branch in liquidate, especially negative e. When the insurance fund is insufficient, _coverShortfall must continue and must not revert. Test it directly: set the fund to zero, create a bankrupt position, and call liquidation. It must return successfully and trigger auto-deleveraging.
A revert leaves a position that can never be liquidated. T22 warned about this; here it also traps the opposing exposure and prevents others' gains from becoming withdrawable.
Simulate a liquidation cascade and track fund depletion. This is the Lab's main exercise. Create three batches of long positions with increasing leverage and drive a falling-price sequence. Re-read the mark, accrue funding, and reevaluate after every step, rather than calculating the whole sequence once.
Initial mark 100; choose your own maintenance margin rate
Three long batches: A at 5× leverage with 100 million notional,
B at 10× with 300 million,
C at 20× with 200 million
Depth assumption: each 50 million notional closed lowers the mark another 1%
Initial shock: mark falls to 96Record each round:
| Round | Mark | Notional liquidated this round | Bankruptcy gap | Fund balance | Auto-deleveraging? |
|---|---|---|---|---|---|
| 1 | |||||
| 2 | |||||
| 3 |
Find when the fund hits zero. That round is when your rules begin harming traders who were right about direction.
Now change only the depth assumption from “1% per 50 million” to “1% per 200 million,” and rerun. Side-by-side tables reveal the main lesson: the same leverage, parameters, and code can produce a routine pullback or an exhausted insurance fund solely because market depth changed. A perpetual on a poorly traded underlying can be an order of magnitude riskier without any contract difference.
Calculate attack economics. This is the chapter's quantitative exercise.
Earlier you asked whether the market might break the venue. Now ask: what would it cost someone to break it deliberately?
Scenario: your market has N notional at a leverage tier; liquidation prices
are d percent from the current mark
Step 1: Cost to push the mark by d
The mark is anchored to external spot markets, so those are what must move
T21 formula: about spot depth × (sqrt(1+d) - 1)
Step 2: Scale of liquidations triggered, and how much forced closing moves price again
Use the cascade and your depth assumption
Step 3: What the attacker receives
a) Gain on a pre-positioned opposite exposure
b) Liquidation fees when acting as liquidator
c) Discounted assets bought during forced closes
Step 4: Profit = Step 3 - Step 1 - fees - gasTry spot depths of five million, fifty million, and five hundred million, with d = 5%. The first case may be profitable. In a shallow underlying, liquidation can be a business someone creates, not just a consequence of falling prices.
Invert the exercise twice. First, how deep must external spot markets be for this attack to be unprofitable under your parameters? That is the minimum liquidity requirement for listing the asset, the same kind of threshold as T21 collateral admission. Second, if mark is replaced by last trade, what does Step 1 cost? Moving your own book may cost one or two orders of magnitude less than moving external spot. That multiple is the value of using a mark price.
Use only a local network, never real funds. Real funds enter only the capstone after Stage 5 security acceptance.
AI Lab
Ask in three steps; the third is the real output:
Step one:
Design a funding-rate formula for a perpetual market. Give the complete
expression, define each term, explain cap selection, and implement it onchain
in O(1) without iterating through positions. What do the period and caps protect?
Step two:
Given historical spot and simultaneous perpetual trade prices, calculate
funding period by period. For each period output deviation, rate, annualized
holding cost for longs, and annualized receipts for shorts. Mark periods that
hit either cap.
Step three:
During periods at the upper cap, did deviation keep growing or converge?
If it kept growing, what does that mean? How would you change parameters,
and what would the new costs be?Most models can shape a plausible formula for step one, but implementation is often wrong: they loop over every position or move the work offchain. Ask how much gas an eight-hour sweep of tens of thousands of positions would require.
Use real historical data for step two. Fetch public spot and perpetual sequences, preferably during volatile periods, and feed them to the model. Independently recalculate three periods by hand.
Step three is the Lab's value. If divergence grows while funding sits at its cap, the mechanism has stopped strengthening even though every accounting entry looks normal. Ask what still pulls the price back: arbitrageurs, who may retreat in stressed markets. Finally plug the formula into your Lab contract and run the cascade: judge its behavior, not the formula's elegance.
Verify these points yourself after using AI
- Does its formula include upper and lower caps? Without them extreme markets can produce absurd rates
- Substitute the caps and calculate maximum anchor pressure at a 10% deviation; is it enough?
- Does it charge on notional or on margin? These differ by leverage, so it must say which
- Does its implementation iterate through all positions? Onchain it must use a cumulative index
- When funding is negative, does it explain money flowing from shorts to longs and the accounting?
- Does the backtest distinguish index and mark prices? Mixing them makes results unreliable
- Treat every specific period, cap, or maintenance rate as a configurable starting point, not a fact
Real-World Case
Some early venues liquidated using their own contract's last trade. The attack is calculable: estimate a group of positions' trigger prices, estimate the cost of hitting a thin local book until it reaches them, and compare with forced-close volume. If the latter is larger, it is profitable. The forced orders hit the same thin book, stretching the wick and triggering more positions. Price later returns, but closed positions do not.
The industry moved broadly toward indexes weighted from external spot venues and marks constrained around them. The change is exactly what markPrice() does: it moves liquidation judgment from a thin market to a deep one. It is T21's problem in another form.
An attacker chose an underlying with shallow spot liquidity that nevertheless had a perpetual market. They built a large long perp position, then bought the spot market higher. The index rose and their unrealized profit became enormous; under that venue's rules, those gains could be withdrawn immediately.
No code misbehaved. They were profitable, so no liquidation triggered; the oracle accurately reflected a real spot rise; and margin arithmetic was correct. The false assumption was that “unrealized profit is real.”
Two lessons: check whether spot depth supports a market's exposure limit before listing, and decide separately whether unrealized profit may be withdrawn at once. Many systems restrict it.
A price gap leaves many positions below maintenance before closing begins. Losses exceed the remaining margin; the insurance fund drains and auto-deleveraging activates broadly. Many users who correctly chose the direction and had profitable positions are forcibly closed in part. They did nothing wrong and often did not expect it, though the rules disclosed it.
Common follow-up changes are to publish the fund-to-open-interest ratio, show users their place in the auto-deleveraging queue, and tier maintenance margin upward for larger positions, which need more buffer because closing them moves price further. The last is most effective and least popular among large traders.
Funding can sit at its upper or lower cap across many periods while price divergence keeps growing.
Do not mistake “the rate is at its maximum” for “pressure keeps strengthening.” Once capped, the rate no longer increases with divergence; only arbitrageurs pull the market back, and they face the greatest difficulty during stress.
The cap is the anchor's force limit. It belongs near the top of the parameter checklist for any perpetual market, though most users never inspect it.
Change One Variable
When the book is deep, code and tests look identical. The difference emerges as the book thins. It changes the nature of risk, not just its size: liquidation stops being a consequence of price moves and becomes something a trader can manufacture.
The multiple you calculated at the end of the Lab is the cost of this change. This is the last line to change in the chapter: it switches attack cost from moving external spot to moving your own book.
The move needed to bankrupt an individual position shrinks from about 4.5% to 0.5%. More importantly, the same margin can now support five times the notional. Open interest grows with new positions whose buffers are thin, while the insurance fund does not grow automatically. A 0.5% disturbance can now start a cascade that previously needed 5%.
Rerun the Lab's table with the higher leverage; fund exhaustion arrives earlier. A higher leverage limit is not merely an extra user choice. It reduces the disturbance needed to move the market from calm to failure.
The anchor tightens: divergence begins incurring cost immediately, without waiting for a settlement time. With a cumulative index, this is nearly free in design terms: call accrueFunding before each state change.
Three changes follow. Opening or closing just around a settlement boundary no longer offers an easy timing trade, a benefit. Each transaction needs another price read and index update, raising gas. Precision becomes important: per-block rates are tiny, and repeated integer truncation can systematically over- or undercharge across hundreds of thousands of blocks. Round to protect the fund, the same principle as T19's rule that rounding must favor the pool.
In ordinary times the fund looks large and inexpensive to maintain. During extreme markets, shortfalls grow while the token's price often falls, shrinking coverage exactly when needed. A second defense fails alongside the first.
Ask the deeper question from Chapter 21: is the insurance fund driven by the same risk it is supposed to insure? If yes, it acts more like leverage than insurance.
Takeaway Questions
Keep three payment flows separate: funding transfers between longs and shorts without passing through the protocol; liquidation fees flow from liquidated traders to liquidators; and bankruptcy gaps flow from the fund or winners to the bankrupt trader's counterparties. Users pay and receive most of these flows.
The protocol is primarily the accountant and backstop, not the fee recipient. Its failure mode is inability to pay balances, rather than an ordinary operating loss.
Perpetual liquidity has three layers: order-book depth governs opening and closing slippage; external spot depth governs whether the mark can be manipulated; and the insurance fund provides capital without finding a counterparty when a gap opens. Analyses often inspect only the first. A deep local book on a thin spot asset is the risk this chapter asks you to recognize.
Answer in four layers, matching the defense chain: normally, leveraged traders bear their own risk; during liquidation, some risk moves to the liquidator through slippage and losing the race; after bankruptcy, the fund pays; after fund exhaustion, profitable opponents pay. The last is unique to perpetuals: the rules can close you even when your market call was right. Inspect fund size, denomination, and auto-deleveraging rank.
Here is the concrete test: if the venue's own token fell to zero, how much insurance would remain? Extend it to all volatile dependencies: fund denomination, liquidators' hedging instruments, and market-maker incentives. Each can deteriorate together with the risk it is meant to address.
Chapter Check
Matching determines who trades and at what price. A perpetual is a zero-sum ledger: one side's gain must be paid by the other's loss. A separate machine enforces this by reading marks, recalculating equity, closing positions before money runs out, and covering late shortfalls from the fund or winners.
The distinction is direct: bad matching worsens execution prices; a bad risk engine makes balances fictional. One is a product problem; the other is a solvency problem.
The last trade is set on this market's own order book, which one order can move. Using it gives anyone willing to hit a thin book the power to choose who liquidates.
The mark is anchored to a weighted index from external spot venues and lets trades deviate only within a band. It raises attack cost from moving this book to moving outside spot markets.
Thus inspect which spot venues form the index and how deep they are. A thinner price source weakens the guard; it is the numerator of T21's safety margin.
Position count can grow without limit, while one onchain transaction has a bounded compute budget. A sweep across tens of thousands cannot fit and only worsens as the venue grows.
Maintain one global cumulative index of amount owed per unit of long size. Accrue into it before state changes. Each position stores its entry index, so its funding owed is one subtraction. This is the same technique as T22 interest accrual. When many accounts receive the same periodic adjustment, think cumulative index before loop.
The creditor differs. In lending, users owe the protocol; it can recognize the loss, draw reserves, and disclose it while maintaining a coherent ledger.
In perpetuals, a user owes another user. An unsettled gap means the winner's displayed balance is false. Early withdrawal requests succeed, later ones fail. Carrying a bankrupt gap is an undiscovered run already in progress.
That is why _coverShortfall must not revert. It may use up the fund and invoke auto-deleveraging, but it must settle the transaction.
There is no one set of values. Check that the sequence includes these, especially the first:
- Depth and venue distribution of external spot markets. They determine whether the index is manipulable and constrain every later parameter. If this fails, none of the rest help.
- The market's exposure cap: maximum open interest should follow from spot depth, not guesswork.
- Tiered maximum leverage and maintenance margin. Large positions move price more when closed and need larger buffers.
- Mark-price band and behavior of each entry point when its source is unavailable, revisiting T21's table.
- Funding period, caps, and charge basis. Caps limit the anchor's force.
- Insurance-fund size, denomination, and refill mechanism, plus whether users can see the auto-deleveraging ranking.
As in T22, build from the foundation: price source, exposure, then failure handling. Many start at item 3, though item 1 sets the scale of risk.
Key idea
A perpetual contract is fundamentally a continuously running risk engine; order matching is only its outer shell.