Skip to main content

Oracle consensus

The settlement price doesn't come from a single source. It's the median of the submissions from a multi-oracle set, gated by a consensus threshold.

Why this design?

A single oracle is a single point of failure — operationally, financially, and politically. For an FX rate that determines whether thousands of dollars get paid out, that's not good enough.

A multi-signer median with a tolerance window has three properties we want:

  1. Robust to a single bad oracle. Median is unmoved by one outlier.
  2. Robust to a sluggish oracle. If 5 signers are configured but only 3 are required, the contract settles as soon as 3 agree — without waiting for the laggards.
  3. Verifiable. Anyone can read which oracles submitted, what price each submitted, and at what timestamp. The state is on-chain.

The consensus parameters

The owner controls three numbers via OracleFacet:

ParamMeaningTypical value
requiredSignersHow many oracles must agree (within tolerance) before the contract settles.3 of 5
toleranceBpsHow close (in basis points) submissions must be to qualify as agreeing. 700 bps = 7%.700
maxOraclesMaximum size of the signer set.10

Read them at any time:

curl https://api.blockfinax.com/v1/oracle/config/8453
{
"data": {
"chainId": 8453,
"requiredSigners": 3,
"toleranceBps": 700,
"oracleCount": 5,
"maxOracles": 10
}
}

Submissions are public

Each submission is recorded on-chain. Read them per-event:

curl https://api.blockfinax.com/v1/oracle/submissions/8453/1
{
"data": {
"chainId": 8453,
"eventId": 1,
"count": 5,
"submissions": [
{ "oracle": "0x1f03…", "price": "11700000", "timestamp": 1775676000, "isStale": false },
{ "oracle": "0x488f…", "price": "11710000", "timestamp": 1775676100, "isStale": false },
{ "oracle": "0xa1b2…", "price": "11650000", "timestamp": 1775676200, "isStale": false },
{ "oracle": "0xc3d4…", "price": "12400000", "timestamp": 1775676300, "isStale": false },
{ "oracle": "0xe5f6…", "price": "11680000", "timestamp": 1775676400, "isStale": false }
]
}
}

The integrator API exposes this so you can render an explorer-style view of the consensus process in your front-end.

Who runs the oracles?

The signer set is mutable by the contract owner via addOracle / removeOracle. On mainnet today the set is operated by BlockFinaX and a small number of partner data providers. Over time the set is expected to broaden — but the protocol's correctness doesn't depend on any single operator, because of the median-based consensus.

If you're building a venue that wants its own settlement source, you can run your own facets / events: the protocol code is open, and creating a new Diamond instance with a different oracle set is a few minutes' work. The integrator API is chain-agnostic — point it at your Diamond's address and you have a custom venue.

Submitting rates (for oracle operators)

If you're an authorised oracle, you call submitRate(eventId, price) after the event's expiry. The integrator API has a calldata builder so you don't need to bundle the ABI:

curl -X POST https://api.blockfinax.com/v1/tx/oracle/submit-rate \
-H "Content-Type: application/json" \
-d '{ "chainId": 8453, "eventId": 1, "price": "11700000" }'

Sign + broadcast with your signer's wallet.

Stale submissions (older than the staleness window) are flagged via isStale: true in the read response and dropped from consensus computation. They never settle stale prices.