Skip to main content

Funding

Variables used

  • Pmark(t)P_{\text{mark}}(t): mark price at time tt.
  • Pindex(t)P_{\text{index}}(t): index/oracle price at time tt.
  • Premium(t)\mathrm{Premium}(t): per-sample premium.
  • XX: sampling interval (seconds).
  • NN: samples per hour.
  • ZZ: per-sample clamp magnitude.
  • YY: per-hour clamp magnitude.
  • FmarketF_{\text{market}}, FuserF_{\text{user}}: market and user funding indexes.
  • pos_size\text{pos\_size}: signed position size.

Premium sampling and TWAP

  • Sample interval: X seconds.
  • Per-sample premium is (Pmark(t)/Pindex(t))1\bigl(P_{\text{mark}}(t) / P_{\text{index}}(t)\bigr) - 1, clamped to ±Z (e.g., set ZYZ \le Y).
  • Over one hour, collect NN samples and use their average as the hourly premium TWAP.
Premium(t)=min ⁣(Z,max(Z,  Pmark(t)/Pindex(t)1))\mathrm{Premium}(t) = \min\!\bigl(Z, \max(-Z,\; P_{\text{mark}}(t)/P_{\text{index}}(t) - 1)\bigr) twaphour=1Nk=1NPremium(tk),tk sampled every X seconds\mathrm{twap}_{\mathrm{hour}} = \frac{1}{N} \sum_{k=1}^{N} \mathrm{Premium}(t_k), \quad t_k \text{ sampled every X seconds}

Funding increment and index

  • Funding increment for the hour is the hourly premium TWAP divided by 24 (hourly slice of a daily rate). No price multiplication needed at this level.
  • Apply a clamp to the hourly increment: pick a cap YY (e.g., 0.010.01 for 1%) and use ΔFclamped=clip(ΔF,Y,Y)\Delta F_{\text{clamped}} = \mathrm{clip}(\Delta F, -Y, Y). Use the clamped value when updating the funding index.
  • Store the funding index as an accumulator per market.
ΔF=1241Nk=1NPremium(tk)\Delta F = \frac{1}{24} \cdot \frac{1}{N} \sum_{k=1}^{N} \mathrm{Premium}(t_k) Fmarket,new=Fmarket,old+Pindexclip(ΔF,  Y,  Y)F_{\text{market,new}} = F_{\text{market,old}} + P_\text{index}\cdot\mathrm{clip}(\Delta F,\; -Y,\; Y)

where PindexP_\text{index} is captured at funding time.

Margin impact

  • Each account tracks its last funding index per market. The unrealized funding owed/receivable is based on the change in index and position size.
  • Variables:
    • pos_size\text{pos\_size}: signed position size (positive = long, negative = short).
    • FmarketF_{\text{market}}: current market funding index.
    • FuserF_{\text{user}}: user's last funding index for this market.
  • Positive position with rising index pays; negative position receives.
UF=pos_size((Fmarket,newFuser))UF = \text{pos\_size} \cdot \bigl(-(F_{\text{market,new}} - F_{\text{user}})\bigr)

Settling funding into PnL

  • When settling, move UF into realized PnL and advance the user's funding index to the market's.
RPnLnew=RPnLold+UF,Fuser,new=FmarketRPnL_{\mathrm{new}} = RPnL_{\mathrm{old}} + UF, \quad F_{\mathrm{user,new}} = F_{\mathrm{market}}

Attempted funding manipulation

  • Flow of play (MM skews quotes to offload inventory):
    1. Attacker leans on one side to push PmarkP_{\text{mark}} away from PindexP_{\text{index}} across successive samples. Premium(t)\mathrm{Premium}(t) moves toward +Z or -Z.
    2. The MM accumulates inventory on the pressured side and skews quotes the other way to shed that risk, re-centering toward PindexP_{\text{index}}. Each further push now requires the attacker to absorb more inventory at increasingly unfavorable prices as the MM skews.
    3. With samples every X seconds, holding Premium(t)\mathrm{Premium}(t) near the clamp for an hour forces the attacker to keep trading into the skewed book repeatedly, driving cumulative cost higher.
    4. Per-sample clamp at ±Z limits how far any single Premium(t)\mathrm{Premium}(t) can move; per-hour clamp at ±Y caps the funding drift. Upside is bounded while the inventory cost to maintain the skew keeps rising.
    5. Net: to achieve a capped funding shift (±Y/hour), the attacker must sustain growing inventory absorption against an MM that continuously skews toward index, making a prolonged attempt increasingly expensive and likely loss-making.

Outage

If an outage accrues for 1 minute or more, funding accrued during the outage is ignored (set to zero). This is calculated per funding period.

RFQ

Funding sampling

To find out funding premiums for RFQ markets, RFQ makers are sent fake requester orders. Fake orders are very short lived (max seconds), they look as usual RFQ orders so that RFQ makers honestly try to fill them. They never execute. A valid maker response is accepted only as a funding-price observation and does not change balances or positions.

Just fake orders created periodically.

Public sampling response

Funding sampling uses the normal protobuf FillRFQResult and TypeScript SDK RFQ fill result. Because sampling is non-executable, protobuf omits filled_size and trade_id, and the SDK exposes both filledSize and tradeId as null. Real RFQ executions use the same result shape with both values set.

Funding formalization

For funding, Nord should run a separate sampler. Every X seconds, the sampler sends a standardized request-to-fill to subscribed RFQ makers for the configured impact size. Nord may accept a valid response as a non-executable observation, but never executes the probe as a trade. The response is used only to observe the impact price.

The sampler should collect both bid-side and ask-side impact prices and derive pmid from them:

Pmid=Pbid impact+Pask impact2P_{\text{mid}} = \frac{P_{\text{bid impact}} + P_{\text{ask impact}}}{2}

For funding tick kk and side dd, let Fd,kF_{d,k} be the funding-participating RFQ makers that return fresh, valid, non-executable impact proposals:

Fd,k={iBi,m=1 and ad,k,iAmax and Vd,k,i=1}F_{d,k} = \{i \mid B_{i,m} = 1 \text{ and } a_{d,k,i} \le A_{\text{max}} \text{ and } V_{d,k,i} = 1\}

For each side, aggregate the valid impact proposals into an impact price: the bid impact is the highest valid bid proposal, and the ask impact is the lowest valid ask proposal.

Pbid impact,k=max({Pbid,k,iiFbid,k})P_{\text{bid impact}, k} = \max(\{P_{\text{bid}, k, i} \mid i \in F_{\text{bid}, k}\}) Pask impact,k=min({Pask,k,iiFask,k})P_{\text{ask impact}, k} = \min(\{P_{\text{ask}, k, i} \mid i \in F_{\text{ask}, k}\}) Pmid,k=Pbid impact,k+Pask impact,k2P_{\text{mid}, k} = \frac{P_{\text{bid impact}, k} + P_{\text{ask impact}, k}}{2}

Funding premium is then computed against the index:

Premiumk=Pmid,kPindex,k1\text{Premium}_k = \frac{P_{\text{mid}, k}}{P_{\text{index}, k}} - 1

If either side has no valid proposal, the tick has no PmidP_{\text{mid}} sample:

Fbid,k=0 or Fask,k=0Sk=|F_{\text{bid}, k}| = 0 \text{ or } |F_{\text{ask}, k}| = 0 \Rightarrow S_k = \emptyset

Funding edge cases:

  • if only one side is returned, the sample is missing for PmidP_{\text{mid}};
  • if the index price is unavailable, ignore the sample or use the existing outage policy;

These materials are provided for informational purposes only and do not constitute financial, investment, legal, or tax advice, or an offer or solicitation to buy or sell any asset. Trading digital assets and derivatives involves substantial risk, including the possible loss of some or all capital. Products may not be available in all jurisdictions. Users are responsible for evaluating suitability and complying with applicable laws.