Skip to content

Docs

How it works, in full.

Orbacle is one contract and one kind of node. This page is the whole mechanism: the calls, the answer shapes, the quorum rule, what operators put up, what the protocol takes, and a row-by-row statement of what on this site is real.


The shape of it

A request is a bounty, not an assignment. The asker names a model, a prompt, an answer shape, a quorum and a fee; the fee sits in the contract; any bonded operator may answer. There is nobody to route the question through and nobody who can decline to.

The fee is Orbio CREDIT: six decimals, one unit per millionth of a dollar of inference. An operator is paid in the thing it spends, so the oracle needs no treasury, no token emissions and no price feed to keep running. If the model that answered cost $0.004 of tokens and the fee was $0.05, the operator kept the difference as CREDIT it can activate for the next question.

Answers are typed. A contract cannot do anything with prose, so Bool, Uint and Choice are fixed-width bytes the contract checks on the way in, and only Text is free-form. The quorum rule applies to the typed shapes; Text is one operator’s reply because two models never agree on prose byte for byte.

Fee token
Orbio CREDIT · 6 decimals
Minimum fee
0.01 CREDIT per answer
Quorum
1 to 3 operators
Settles when
a digest reaches ⌊q/2⌋+1
Text answers
quorum 1, up to 2,048 bytes
Prompt
up to 8,192 bytes, emitted not stored
Deadline
2 minutes to 7 days
Protocol cut
fixed at deployment, capped at 20%
Operator stake
$ORBACLE above an immutable minimum
Unbonding
1 day
Admin functions
None
Upgradeability
None

The calls

01

ask

ask(string model, Kind kind, uint8 quorum, uint32 callbackGas,
    uint40 ttl, uint96 fee, string prompt) returns (uint256 id)

Pulls `fee` CREDIT from the caller (approve first) and emits the prompt in the Asked event. The prompt is never stored: an eight-kilobyte question costs the same storage as a one-line one, which is none.

Validation is strict and cheap: quorum 1–3, Text forces quorum 1, ttl between two minutes and seven days, fee at least 0.01 CREDIT per answer, callback gas at most 500,000, prompt at most 8,192 bytes.

The returned id is what you keep. For a contract, it is the key you will see again in onAnswer and the argument to boolAnswer, uintAnswer, choiceAnswer or answerOf.

02

reply

reply(uint256 id, bytes answer, bytes32 receipt, string model)

Only a bonded operator, only while the request is open and before its deadline, and only once per request. The answer must match the shape the asker chose or the call reverts: one byte for Bool and Choice, thirty-two for Uint, one to 2,048 for Text.

The contract hashes the answer and tallies it. The first digest to reach a majority of the quorum settles the request, pays every operator who submitted that digest an equal share of the fee after the cut, and stores the answer. If `quorum` replies arrive with no majority, the fee is refunded and nobody is paid.

`receipt` is keccak256 of the gateway response id and `model` is the model that actually answered, both from Orbio’s response. Neither is enforced — the contract cannot see the gateway — but both are in the log, and anyone with an Orbio key can check them.

03

refund

refund(uint256 id)

After the deadline, anyone may send the escrowed fee back to the asker. Operators who replied to a request that then expired are paid nothing, which is why a node skips requests it cannot finish in time.

04

stake · unbond · withdraw

stake(uint256 amount)
unbond()
withdraw()

Bond $ORBACLE to become an operator; the minimum is an immutable set at deployment. Unbonding starts a one-day clock during which you may not reply, and withdraw returns the whole stake once it has run. Re-staking cancels an unbond.

There is no slashing. The penalty for a wrong or lazy answer is that it earns nothing, and the stake exists so that an operator has something at rest while it answers — and so that “three operators” costs something to fake.


The four answer shapes

KindBytesQuorumWhat the operator’s node doesRead it with
Bool1 · 0x00 or 0x011–3Asks for “true” or “false”, temperature 0, and encodes the first word.boolAnswer(id)
Uint32 · ABI uint2561–3Asks for one whole number in digits; strips separators; refuses anything above 2²⁵⁶−1.uintAnswer(id)
Choice1 · an index1–3Asks for the index of the option, 0-based, from a numbered list in your prompt.choiceAnswer(id)
Text1–2,048 · UTF-81 onlyAsks for the answer only, no preamble, and truncates to the cap.answerOf(id)

From a contract

Inherit OrbacleClient. It approves CREDIT once, gives you _askBool, _askUint, _askChoice and _askText, checks that a callback really comes from the oracle for a request you made, and hands you the decoded value in one overridable hook per shape. You never touch bytes.

The oracle calls back with the gas you named, inside a try/catch, in the same transaction as the settling reply — so a revert in your hook costs you the callback and nothing else, and the operator is still paid. Fund the contract with CREDIT before it asks; reclaim(id) pulls back an expired fee. The example beside this is the one the test suite runs; a second one, Grader, pays a bounty on a 0–100 score.

Write prompts the way you would write an acceptance test: name the shape of the answer you want in the prompt itself, number your options for Choice, and give the model what it needs to decide rather than a link it cannot open. The operator relays your prompt unchanged; it does not fetch anything for you.

import {OrbacleClient, IOrbacle} from "orbacle/OrbacleClient.sol";

contract Verdict is OrbacleClient {
    mapping(uint256 => bool) public settled;
    mapping(uint256 => bool) public verdicts;

    constructor(IOrbacle oracle) OrbacleClient(oracle) {}

    function decide(string calldata q, uint96 fee)
        external returns (uint256 id)
    {
        id = _askBool(
            "anthropic/claude-sonnet-5",
            3,        // quorum
            1 hours,  // ttl
            fee,      // CREDIT, 6 decimals
            q
        );
    }

    function _onBool(uint256 id, bool v) internal override {
        settled[id] = true;
        verdicts[id] = v;
    }
}

The state table

What is real, one row each

A site that will not say what it has not built is not worth reading. Every claim Orbacle makes appears below with its status attached.

ClaimStatusWhat that means
The Orbacle contractWritten and testedcontracts/src/Orbacle.sol compiles to 8,084 bytes with solc 0.8.36. It has not been deployed to any chain. The deploy script is ready and waits for the stake token address.
The property testsPass · 62/62Run on a real EVM in process (@ethereumjs/vm, Cancun). They cover escrow, every validation revert, the majority rule at quorum 1, 2 and 3, total-disagreement refunds, the four answer shapes, deadlines, the callback including a client whose callback reverts, the Grader example end to end, and the unbonding clock. They are mine and so is the reasoning: this is not an audit.
Orbio CREDIT, Exchange and gatewayReal · theirsCREDIT at 0xe33322da1380e61e5ae5dfb21e7f62924c73004c, the Exchange at 0x6951ffd32630b05e06f50062aea801625a58ebc0, both confirmed to hold code on chain 4663. The gateway is https://api.orbio.so/api/v1. Orbacle uses the public ABI subsets Orbio publishes and nothing private. Orbio has not endorsed this.
The CREDIT price shown on the home pageLiveAn eth_call to the Exchange’s getQuote for a 10 USDG order, made by your browser against a public RPC, every thirty seconds. The discount is one minus the price. It is Orbio’s order book, read, not a number of ours.
The token $ORBACLENot launchedIt will be launched on Pons and is the token operators bond. Until it exists the oracle cannot be deployed, because the stake token is a constructor argument.
The operator nodeWritten · 34 checks · untested liveoperator/node.mts watches the log, infers through Orbio, encodes to the asker’s shape, replies, and activates earned CREDIT when its balance runs low. Its pure core (encoding, the shape prompts, the accept/decline policy) passes 34 checks including a round trip against a fake OpenAI-shaped gateway. It has never answered a live request, because there is no live oracle yet.
An auditNoneNobody independent has reviewed this code.

Known limits

  • A model can be wrong

    A quorum of three makes a wrong settlement rarer, not impossible. Ask questions a careful reader could answer from the prompt alone, and keep the stakes proportionate to the fee.

  • Operators can collude

    Three operators can be one person with three wallets and thirty thousand tokens. The stake makes that cost something; it does not make it impossible. Prefer well-known operators for high-value questions, by reading their won/answered record.

  • Text is unverified

    A Text answer is one operator’s reply. The receipt lets you check what the gateway returned, after the fact. Do not settle money on a Text answer.

  • The gateway is a dependency

    If Orbio’s gateway is down, nobody can answer. Fees refund after the deadline, so an outage costs askers time, not CREDIT.

  • The prompt is public

    It is in the event log forever. Do not put in it anything you would not put on a block explorer.

  • No audit

    Nobody independent has reviewed this code. Fifty-seven passing properties on a real EVM are worth something; they are not that.

Run the node, or ask the first question.

The operator node is one file and one wallet. The app validates a question before it asks you to sign anything.