Skip to content
LogoLogo

Funding

A perpetual never expires, so something has to pull its traded price toward the underlying. On Flint that is funding: a continuous transfer between longs and shorts, sized by how far the makers' book sits from the index.

  • When the book bids above the index, the rate is positive and longs pay shorts.
  • When the book offers below the index, the rate is negative and shorts pay longs.

Funding is peer-to-peer. The protocol takes no cut of it.

The rate

The rate is computed in the contract's own units — ticks per lot per hour — from three readings taken at the moment of a funding crank.

1. Impact prices. The program walks a probe of impact_notional_atoms (PnL-currency atoms) into each side of the makers' merged book and takes the average fill price:

  • Only levels within max_level_divergence_bps of the index count.
  • A side that runs out of depth, or whose average is not richer than the index, contributes nothing.

2. Premium. How far each side sits on the rich side of the index:

premium = max(0, impact_bid − index) − max(0, index − impact_ask)

A two-sided book that straddles the index has a premium of zero.

3. Carry, clamp and cap.

rate  = premium + clamp(carry × index − premium,  ±carry_clamp × index)
cap   = min(max_rate_per_hour, max_rate_margin_factor × (imf − mmf)) × index
rate  = clamp(rate, ±cap)                      // ticks per lot per hour

carry_per_hour is a baseline hourly rate the premium is pulled toward, by at most carry_clamp. The cap is the smaller of a fixed hourly ceiling and a multiple of the contract's margin band, so funding can never outrun the room between initial and maintenance margin.

As a fraction, the hourly rate is rate / index. That is the figure FundingService.GetFundingRates reports: rate is a decimal fraction per interval_seconds = 3600, positive when longs pay.

Accrual

The rate is converted to ticks per lot per second and integrated continuously into a cumulative funding index on the contract (one for each side). A position owes:

funding = −lots × (index_now − index_at_last_settlement)

so a long (positive lots) pays when the index rises and a short receives the same amount.

Keepers crank each contract with sync_linear_perp_cache, which does three things in order:

  1. Charges the time since the last crank at the rate held over it. At most max_hold_secs is charged per crank; time beyond it goes uncharged, so a stalled crank never back-charges a large span.
  2. Samples a fresh rate from the book.
  3. Holds the next rate:
    • Within a UTC hour, the held rate moves toward each fresh sample as an exponential average, weighted by the time since the last sample (rate_per_second_retention).
    • At the first sample after the UTC hour changes, the period closes and the fresh sample replaces the held rate outright.

A new rate only applies from the moment it is sampled; no span is ever charged at a rate measured after it.

Parameters

Each contract carries its own funding parameters, set at listing and changeable by Flint (rate-moving ones only through the 24-hour timelock).

ParameterListing defaultRole
impact_notional_atoms1,000 USDCProbe size for the impact prices
max_level_divergence_bps500 (5%)How far from the index a level still counts
carry_per_hour0Baseline hourly rate
carry_clamp0Max pull of the carry on the rate
max_rate_per_hour0.05%Hard hourly ceiling
max_rate_margin_factor1k in the k × (imf − mmf) ceiling
rate_per_second_retention≈ 0.99923Exponential average; 15-minute half-life
max_hold_secs300Longest span one crank may charge
funding_activeonWhether funding accrues at all

With the defaults, the carry is zero and the rate is the clamped premium. Turning funding_active off stops accrual (the index holds) without pausing trading.

How it hits your PnL

Funding never moves tokens by itself. It is booked onto your position's funding leg in three ways:

WhenBooked through
Any fill on the positionThe current index — the old size pays for all the time it was held
settle_funding (permissionless; keepers run it periodically)The index as it stood when the current UTC-hour period began
Margin checksNot booked, but the accrued amount through the current index always counts toward health

The funding leg then moves into your settlement-asset balance with the rest of your unsettled PnL when settle_realised_pnl runs (see Collateral & margin). Credits and debits are whole ticks, rounded down; the sub-tick remainder is carried, so many small settlements add up to exactly what one large one would.

Worked example

On SOL-USDC-PERP (1 lot = 0.001 SOL, 1 tick = 1 USDC atom), the index is $150, which is 150,000 ticks per lot. A $1,000 probe walked into the bids fills at an average of 150,030 ticks; the asks are no richer than the index.

premium         = 150,030 − 150,000              = 30 ticks/lot/hour
hourly rate     = 30 / 150,000                   = 0.02% per hour
cap             = min(0.05%, 1 × (10% − 5%)) × 150,000
                = 0.05% × 150,000                = 75 ticks/lot/hour
charged         = 30 ticks/lot/hour  (inside the cap)

A long of 10 SOL (10,000 lots) held for an hour at that rate:

funding = −10,000 lots × 30 ticks  = −300,000 ticks = −0.30 USDC

The matching shorts receive 0.30 USDC between them. Check: $1,500 notional × 0.02% = $0.30.

Reading funding from the API

RPCReturns
FundingService.GetFundingRates / SubscribeFundingRatesThe held rate as an hourly fraction per contract
PerpPosition.accrued_funding_usdFunding accrued since the position's last booking
GetAccountHistory(include_perp_pnl=true)Estimated cumulative funding in perp PnL history

Funding accrues continuously, so no scheduled payment time is advertised (next_funding_at is unset). Funding-rate history and per-payment history RPCs are defined but not yet served.