Why funding exists
Perpetra’s perpetual price is set by its own orderbook, which can drift from the real spot price of the underlying asset. Funding is a periodic payment between longs and shorts that pulls the perpetual price back toward spot: whichever side is “winning” the price drift pays the other side.The rate formula
Each market’s funding rate is based on the premium between mark price and index (spot) price:Every market also has an
interestRateBps parameter in its config. It’s
reserved for a future premium-plus-interest model but isn’t applied in the
current implementation, the rate is the clamped premium alone.- Positive rate: mark price is trading above index price. Longs pay shorts.
- Negative rate: mark price is trading below index price. Shorts pay longs.
How the rate updates
A funding keeper callsupdateFundingRate(marketId) on a fixed schedule (the market’s fundingInterval, e.g. every hour). Each call is rate-limited: it reverts if less time than fundingInterval has passed since the last tick.
On each tick, the contract pulls fresh mark and index prices from the Oracle, computes the new rate, and advances a per-market cumulative index:
timeDelta is the actual time since the last update, so a late tick still accrues the correct amount rather than snapping to a fixed interval’s worth.
This update only touches the market’s shared state. It does not update any individual position, that happens lazily, per position, whenever it’s touched.
How a position settles funding
Every position stores a snapshot of the cumulative index from the moment it was last settled (positionFundingIndex). The Engine calls calcFundingOwed whenever a position is opened, closed, increased, decreased, or liquidated:
- For longs,
fundingOwedisrawFundingas computed. Positive means the position owes funding, deducted from collateral. - For shorts,
fundingOwedis-rawFunding. When longs are paying (positive delta), shorts receive.
estimateFundingOwed runs the same math as a read-only call, used by the
frontend to show “estimated funding” without actually settling anything.Checking the current rate
getCurrentRate(marketId) returns the rate in three forms for display purposes:
rate: raw signed value scaled toRATE_PRECISION(1e18)rateBps: the same rate converted to basis pointsisLongPaying:trueif the rate is positive
timeUntilNextFunding(marketId) returns the seconds remaining before the next tick is allowed, for countdown displays.