How Perpl settles funding payments for 100,000+ positions with two storage reads instead of 100,000 writes.
Perpetual exchanges use a funding rate to keep the perpetual price anchored to the underlying asset. Periodically — roughly every hour — longs pay shorts (or vice versa) based on the rate and position size. On a centralized exchange this is trivial: a background job debits and credits every account. On a decentralized exchange running on a general-purpose EVM chain, it's a fundamental scaling problem.
With 100,000 open positions, paying out funding every hour requires 100,000 on-chain state writes per funding event. Each write to a position's storage slot costs at least 5,000 gas. The arithmetic is unforgiving: 100,000 positions × 5,000 gas = 500 million gas — roughly 16 full blocks — just to settle one hour of funding. At Monad's block rate of ~2.5 blocks per second, that's six seconds of block space consumed every hour, purely by bookkeeping.
In practice it's worse. Each position update involves reads, balance changes, and event emissions. The real cost is closer to 25,000 gas per position. At 100,000 positions that's 2.5 billion gas per event — 83 blocks. This isn't a scalability inconvenience; it's a protocol design constraint that has shaped every decentralized perp that exists.
The key observation is that a position's cumulative funding payment depends only on three things: its lot size, when it was opened, and when it was closed. The lot size and side are fixed between open and close (the contract forces settlement if they change). This means the per-event payment for any position factors cleanly:
The funding product Fproduct[j] is entirely market-level data — it doesn't depend on any individual position. So instead of writing to every position at each event, you can store a single running sum: the funding product sum, Fsum.
When a position opens, the contract records the current Fsum as the position's funding checkpoint. Call it Fsum[m]. When the position closes, the contract reads the current Fsum[j]. The cumulative funding payment — the position's premium PNL — is:
It doesn't matter if the position was held through 1 funding event or 1,000. The cumulative effect telescopes into the difference between two stored sums. No loop, no iteration, no per-position writes at event time.
For a naive DEX, settlement gas scales linearly with position count: double the traders, double the gas. Perpl's gas cost for a funding event is constant regardless of how many positions are open. A single storage write to update Fsum, plus whatever overhead the permissioned rate-setter transaction requires. The protocol never loops over positions.
The settlement cost is deferred and amortized. Each position pays its cumulative funding when it changes or closes — folded into the settlement transaction the trader was going to execute anyway. The chain never does work for dormant positions.
The contract enforces a constraint: any change to a position's lot size or side triggers immediate premium PNL realization. This is what makes the virtualization safe. If a trader could silently grow or shrink their position without settling, the Fsum checkpoint would become invalid. The forced settlement means the checkpoint is always correct relative to the current position parameters.