Virtualized Funding: Technical Diagrams

Position lifecycle, Fsum accumulation, gas cost scaling, and storage layout

Figure 1: Position Lifecycle with Virtual Funding
OPEN POSITION
Store Fsum[m]
as funding checkpoint
1 read + 1 write
(the checkpoint)
FUNDING EVENTS
Fsum[j] += Fproduct[j]
for each event j
Position NOT touched ✓
1 write per event
regardless of positions
SIZE CHANGE
Forces settlement:
θ_pnl realized now
New checkpoint stored
2 reads → compute
reset checkpoint
CLOSE POSITION
θ_pnl = (Fsum[j] −
Fsum[m]) × L
Final settlement
2 reads → exact PNL
any # of events
Key invariant: The contract forces premium PNL realization whenever lot size or side changes. This keeps the checkpoint valid: the stored Fsum[m] always corresponds to the current position parameters. Dormant positions are never touched between open and close — their funding accumulates silently in Fsum.
Figure 2: Fsum Accumulation — 8 Funding Events
Event Block Frate (10⁻⁶) Price (USDC) Fproduct = P × rate / 10⁶ Fsum (running) Note
00.000contract genesis
FE18,571+5060,000+3.0003.000
FE217,142+8061,000+4.8807.880← position opens here (stores 7.880)
FE325,713−3060,500−1.8156.065
FE434,284+12062,000+7.44013.505
FE542,855+6063,000+3.78017.285
FE651,426−2062,000−1.24016.045← position closes here
FE759,997+9064,000+5.76021.805
FE868,568+4063,500+2.54024.345
Example: Long 10 lots opened at FE2 (Fsum[m] = 7.880), closed at FE6 (Fsum[j] = 16.045).
θ_pnl = (16.045 − 7.880) × 10 × (−1) = −81.65 USDC (long pays funding — 4 positive rate events minus 1 negative, net positive).
Computed from 2 reads: Fsum[m] stored at open, Fsum[j] read at close.
Figure 3: Gas Cost vs Position Count (per funding event)
Gas required per funding event settlement █ = Block gas limit (30M)
At 1,000 positions
Naive DEX
25M gas
Perpl ✓
~5k gas — O(1)
At 5,000 positions
Naive DEX
125M gas (4× limit)
Perpl ✓
~5k gas — O(1)
At 100,000 positions
Naive DEX
2.5B gas (83× limit)
Perpl ✓
~5k gas — O(1)
Assumptions: 25,000 gas per position update (SSTORE warm: 5k + reads + events + arithmetic). Block gas limit: 30M. Naive approach: one SSTORE per position per event. Perpl: one SSTORE for Fsum, regardless of position count.
Figure 4: Formula Derivation
Funding payment per event
Fpayment[j] = Pi[j] × Frate[j] × L
Pi[j] = spot index price at event j
Frate[j] = funding rate (10⁻⁶ units)
L = signed lot size (+long, −short)
Define the funding product (market-level)
Fproduct[j] = Pi[j] × Frate[j]
Independent of any individual position.
One value computed per event.
Rewrite payment using product
Fpayment[j] = Fproduct[j] × L
Payment factored into market term × position term.
Define the running sum
Fsum[j] = Σ Fproduct[k], k = 0..j
Cumulative product sum, updated once per event.
Initialized to 0 at contract creation.
Recover any single event from sum
Fproduct[j] = Fsum[j] − Fsum[j−k]
Difference of adjacent sums = one event's product.
Generalize to any holding period
θpnl = (Fsum[j] − Fsum[m]) × L
m = Fsum stored at position open
j = Fsum read at position close
Two reads. Exact. Any duration.
Figure 5: On-Chain Storage Layout
Market state (one per perp)
fSumint128updated each funding event
fRateint32current rate (10⁻⁶)
fPriceuint64index price at last event
fundingBlockuint64block of last event
Position record (one per open position)
fSumCheckpointint128Fsum[m] stored at open
lotSizeint64signed (+ long, − short)
entryPriceuint64for delta PNL
deposituint64collateral locked
Settlement on close reads market.fSum and position.fSumCheckpoint — two reads, constant cost. The funding event transaction writes only market.fSum — one write, constant cost.
Figure 6: Settlement System Comparison
Property CEX Naive DEX Appchain (Hyperliquid) ✓ Perpl (Virtualized)
Gas per funding eventNoneO(N) positionsN/A — custom opcodeO(1) — one write
Scales to 100k positions✗ (83 blocks at 100k)
Trustless / on-chainPartially✓ Fully
Requires dedicated chainN/A✓ Required
Settlement cost per positionServer time~25k gas/event~0 (absorbed by chain)~0 deferred to close
Reads at position closeN/AN/AN/A2 reads (exact)
Dormant positions touchedEvery eventEvery eventEvery event (cheap)Never
Multi-event historyServer sumsRequires loopCustom accumulatorTelescopes into 2 reads