Summary
Funding rates are pushed on-chain by an off-chain solver engine. Retries, reorderings, and delayed inclusion mean a stale update can land after a newer one and overwrite it, and an update that is no longer wanted still executes when it finally confirms.
v0.8.6 adds a setFundingFee overload on SymmioPartyB that carries a per-symbol nonce and a deadline.
Updates that are stale or expired are skipped and reported rather than reverted, so one out-of-date symbol cannot
fail the batch it travelled in.
Interface
function setFundingFee(
uint256[] calldata symbolIds,
int256[] calldata longFees,
int256[] calldata shortFees,
int256[] calldata marketPrices,
uint256[] calldata nonces,
uint256 deadline
) external whenNotPaused;
nonces[i] belongs to symbolIds[i]. Callers must hold MANAGER_ROLE or
TRUSTED_ROLE on the PartyB contract, or hold INSTANT_LAYER_ROLE on the Symmio core.
What is accepted, skipped, and forwarded
After the contract-address and caller-role checks, the deadline is checked before array lengths or per-symbol state. If it has passed, the whole call reports a skip and returns without touching funding-nonce state or validating array lengths.
Otherwise each symbol is compared against its last accepted nonce, and the call takes one of three paths.
| Case | Forwarded to core | Emitted |
|---|---|---|
| deadline passed | nothing | FundingFeeUpdateSkipped, reason 1 |
| every symbol stale | nothing | FundingFeeUpdateSkipped, reason 0 |
| no symbol stale | all symbols | nothing |
| mixed | the fresh symbols only | FundingFeeUpdateSkipped for the stale subset, reason 0 |
A symbol is stale when its supplied nonce is strictly lower than the stored one. An equal nonce is accepted, which lets the engine replace or retry the latest update for a symbol without inventing a new nonce and without breaking the surrounding template.
Accepted symbols write their nonce before the forward. This ordering does not make the nonce single-use: because an equal nonce remains acceptable, replaying the same batch forwards it again. The mapping prevents older updates from overwriting a newer accepted nonce; callers still need their own idempotency policy if duplicate forwarding matters.
Reporting
event FundingFeeUpdateSkipped(uint256[] symbolIds, uint256[] nonces, uint256 deadline, uint8 reason);
reason is 0 for a stale nonce and 1 for an expired deadline. In the mixed case the
arrays carry only the skipped symbols, not the whole submission.
Batched calls are routed back through the gate
SymmioPartyB._call forwards each entry to the Symmio core. An entry targeting this contract's own
setFundingFee selector would therefore have bypassed the nonce gate entirely. _call now detects that
selector and delegatecalls it back into this contract instead, so a funding update carries the same guarantees
whether it is submitted directly or inside a batch.
Storage
Two slots are appended after the existing v0.8.4-compatible layout, so no existing field moves.
uint256 private deprecatedFundingNonce; // slot N+4: superseded global nonce, unused
mapping(uint256 => uint256) public fundingNonce; // slot N+5: symbolId => last accepted nonce
fundingNonce is public, so the engine can read the current floor per symbol and resynchronise after a restart
rather than guessing.
Integration requirements
- Supply a per-symbol nonce that never decreases for that symbol. A shared counter across symbols works but wastes headroom.
- Set a deadline that reflects how long the update stays meaningful, not how long inclusion might take.
- Read
fundingNonce(symbolId)on startup to recover the floor after an engine restart. -
Treat
FundingFeeUpdateSkippedas expected traffic; alert on a symbol that is skipped repeatedly, which means the engine's nonce has fallen behind. - Reuse the same nonce when resubmitting the latest update for a symbol; a higher nonce is only needed for a genuinely newer rate.