Specification
The state machine, the parameters and the tables they imply, as the code has them.
This file is generated. cargo run -p truth-sim --release -- --spec > docs/SPEC.md rebuilds it, and a test fails if the committed copy has drifted. The transition table is not transcribed from anywhere: it is produced by driving the real state machine, attempting every action from every reachable state and recording what came back. A spec that claimed the machine refuses something it allows could not survive being written this way, which is the reason it is.
Account layouts are deliberately not copied here. They are the IDLs in packages/sdk/src/idl/, generated from the programs by anchor build and committed, so they are already the machine-readable, non-drifting description of every account, instruction and error code. Restating them in prose would be the drift this file exists to avoid.
Outcomes
An answer is one of four things. TooEarly re-opens the request; the other three end it. TooEarly and Unresolvable are abstentions: a juror is never slashed for either.
| outcome | slot | final | abstention |
|---|---|---|---|
Index(i), i < 32 |
i | yes | no |
Scalar(v) |
— (the court hears categorical questions only in v1) | yes | no |
TooEarly |
32 | no | yes |
Unresolvable |
33 | yes | yes |
Ballots are counted into 34 slots.
The request lifecycle
Every row below was produced by attempting the action and recording the result. at says when the clock had to be for the attempt to be anything but early.
| from | action | at | to | refused with |
|---|---|---|---|---|
| Requested | propose |
— | Proposed | |
| Requested | attest |
— | — | InvalidTransition |
| Requested | dispute |
— | — | InvalidTransition |
| Requested | finalize_undisputed |
window end | — | InvalidTransition |
| Requested | resolve_from_court |
— | — | InvalidTransition |
| Requested | expire |
max_open_at | Resolved | |
| Requested | close |
— | — | InvalidTransition |
| Requested | correct |
— | — | InvalidTransition |
| Proposed | propose |
— | — | InvalidTransition |
| Proposed | attest |
— | Proposed | |
| Proposed | dispute |
— | Disputed | |
| Proposed | finalize_undisputed |
window end | Resolved | |
| Proposed | resolve_from_court |
— | — | InvalidTransition |
| Proposed | expire |
max_open_at | — | InvalidTransition |
| Proposed | close |
— | — | InvalidTransition |
| Proposed | correct |
— | — | InvalidTransition |
| Disputed | propose |
— | — | InvalidTransition |
| Disputed | attest |
— | — | InvalidTransition |
| Disputed | dispute |
— | — | InvalidTransition |
| Disputed | finalize_undisputed |
window end | — | InvalidTransition |
| Disputed | resolve_from_court |
— | Resolved | |
| Disputed | expire |
max_open_at | — | InvalidTransition |
| Disputed | close |
— | — | InvalidTransition |
| Disputed | correct |
— | — | InvalidTransition |
| Resolved | propose |
— | — | InvalidTransition |
| Resolved | attest |
— | — | InvalidTransition |
| Resolved | dispute |
— | — | InvalidTransition |
| Resolved | finalize_undisputed |
— | — | InvalidTransition |
| Resolved | resolve_from_court |
— | — | InvalidTransition |
| Resolved | expire |
max_open_at | — | InvalidTransition |
| Resolved | close |
— | Closed | |
| Resolved | correct |
— | Resolved | |
| Closed | propose |
— | — | InvalidTransition |
| Closed | attest |
— | — | InvalidTransition |
| Closed | dispute |
— | — | InvalidTransition |
| Closed | finalize_undisputed |
— | — | InvalidTransition |
| Closed | resolve_from_court |
— | — | InvalidTransition |
| Closed | expire |
max_open_at | — | InvalidTransition |
| Closed | close |
— | — | InvalidTransition |
| Closed | correct |
— | Closed |
A TooEarly answer returns the request to Requested and pushes earliest_proposal_at forward by one tier window, at most 3 times. With no proposal by max_open_at — 14.0 days after the request becomes proposable — it resolves Unresolvable and the market refunds at par. A finalized answer may be corrected once, inside 7.0 days of becoming final.
The dispute ladder
Round 1 is a sampled panel of the tier's size. When governance has opened the agent bench and it can seat at least 3 model families with no operator holding more than 2 seats, Round 1 is drawn from bonded agents on the court's agent clock; otherwise, and on every round above the first, it is drawn from humans. An agent panel's decision binds on T0–T2 and is advice on T3–T4, where it escalates free to the grand panel with its verdict on the record. A round that cannot decide escalates free; a round that decides opens a 24.0 h appeal window. There are 2 panel rounds before the assembly, and a grand panel is 2n+1 capped at 15. When governance has opened assembly appeals, a grand panel's ruling can be appealed to the assembly and a grand panel that cannot decide escalates there free; with them closed, the grand panel is the last rung and one that cannot decide answers Unresolvable.
| rung | who | threshold | bond to appeal from it |
|---|---|---|---|
| Round 1 | tier panel, agents first when the bench allows | 2/3 of the seats | 2x the request's bonds |
| Grand panel | 2n+1 fresh human jurors |
2/3 of the seats | 4x, floored at 5000.00 USDC and capped at 10x the bonds, when assembly appeals are open |
| Assembly | every staker locked before the request | 2/3 of capped weight to overturn, and to name an answer when no round did | — |
For a long-tail request with 60.00 USDC of bonds that works out at 120.00 USDC to the grand panel and 600.00 USDC to the assembly.
Seats and thresholds, by panel size
Both numbers are ceilings, which is why they are lumpy in the seat count: nine seats demand a tighter turnout than either seven or eleven.
| seats | quorum | votes that decide | tag-matched seats | grand panel |
|---|---|---|---|---|
| 5 (not drawn) | 4 | 4 | 3 | 11 |
| 7 | 5 | 5 | 4 | 15 |
| 9 (not drawn) | 7 | 6 | 5 | 15 |
| 11 | 8 | 8 | 7 | 15 |
| 15 (not drawn) | 11 | 10 | 9 | 15 |
| 23 (not drawn) | 17 | 16 | 13 | 15 |
Tiers
The scorer produces a total in 0..=1000, and the total picks the tier.
| tier | from score | bond | + bps of OI | max bond | disputer bond | window | premium | panel |
|---|---|---|---|---|---|---|---|---|
| T0 | 0 | 25.00 USDC | 10 | 100.00 USDC | 10000 bps (100.00%) | 2.0 h | 5 bps (0.05%) | 7 |
| T1 | 200 | 100.00 USDC | 20 | 500.00 USDC | 10000 bps (100.00%) | 6.0 h | 5 bps (0.05%) | 7 |
| T2 | 400 | 500.00 USDC | 30 | 2500.00 USDC | 10000 bps (100.00%) | 12.0 h | 10 bps (0.10%) | 7 |
| T3 | 600 | 2500.00 USDC | 50 | 25000.00 USDC | 8000 bps (80.00%) | 24.0 h | 20 bps (0.20%) | 11 |
| T4 | 800 | 10000.00 USDC | 100 | 100000.00 USDC | 8000 bps (80.00%) | 48.0 h | 50 bps (0.50%) | 11 |
Time and jurors, by tier
An undisputed answer is final when its window closes. Each attestation, up to 3, cuts 25% of what remains, never below 25% of the window nor below 30 min, and one that would cut nothing because the window is already at that floor is refused; the fully attested column has all of them signed at once. A grand panel's jurors must not have sat on Round 1, so hearing both rungs in full takes the distinct jurors shown. A draw is offered at most 24 pool members, cut from the pool less the round below, so a pool of that many eligible jurors seats every grand panel in full; a thinner one seats short, decides on 2/3 of the seats it has, and is not drawn below 3.
| tier | window | fully attested | Round 1 | grand panel | distinct jurors |
|---|---|---|---|---|---|
| T0 | 2.0 h | 50 min | 7 | 15 | 22 |
| T1 | 6.0 h | 2.5 h | 7 | 15 | 22 |
| T2 | 12.0 h | 5.1 h | 7 | 15 | 22 |
| T3 | 24.0 h | 10.1 h | 11 | 15 | 26 |
| T4 | 48.0 h | 20.2 h | 11 | 15 | 26 |
Slashing
| verdict | tiers 0–2 | tiers 3–4 | reputation |
|---|---|---|---|
| voted with the final answer | 0 bps (0.00%) | 0 bps (0.00%) | +1 |
| voted against it | 1000 bps (10.00%) | 2000 bps (20.00%) | −2 |
voted TooEarly or Unresolvable |
0 bps (0.00%) | 0 bps (0.00%) | 0 |
| committed and never revealed | 3000 bps (30.00%) | 3000 bps (30.00%) | −3 |
A misaligned juror never loses more than 3x what the round pays an aligned one, so the accuracy a juror needs before serving is worth it does not move with the tier. Reputation decays 1000 bps (10.00%) a quarter and floors at zero.
Settlement
Four verdicts. The caller picks one by comparing the proposal with the final answer, and the split follows. Rounding remainders go to the insurance fund, and the transfers always sum to the pot — proved by property test and checked against the chain by the oracle's differential test.
A request offers 3 attester seats, fixed when it opens. When the proposal stands, the proposer is paid the reward less the 5% treasury fee and the whole 20% attesters' pool, however many seats were filled, which is the figure shown before signing; each filled seat is paid an even share of the pool, and an empty seat's share goes to the insurance fund. The tag subsidy's attester bonus is split by seat the same way.
Worked on a pot of 1000.00 USDC proposer bond, 1000.00 USDC disputer bond, 100.00 USDC attester stake (one attester, 3 seats) and a 100.00 USDC reward.
| verdict | proposer | disputer | attesters | jurors | fund | treasury | market |
|---|---|---|---|---|---|---|---|
Undisputed |
1075.00 USDC | 1000.00 USDC | 106.66 USDC | — | 13.33 USDC | 5.00 USDC | — |
ProposerWins |
1675.00 USDC | — | 106.66 USDC | 200.00 USDC | 213.33 USDC | 5.00 USDC | — |
DisputerWins |
— | 1755.00 USDC | — | 220.00 USDC | 220.00 USDC | 5.00 USDC | — |
Unresolvable |
750.00 USDC | 1000.00 USDC | 75.00 USDC | 110.00 USDC | 165.00 USDC | — | 100.00 USDC |
Parameters
Every one of these is governance-tunable without a redeploy. The values are v0.
CourtParams
| field | v0 |
|---|---|
quorum_bps |
7000 bps (70.00%) |
supermajority_num / _den |
2/3 |
tag_matched_bps |
5500 bps (55.00%) |
general_seats |
2 |
min_panel |
3 |
commit_secs |
24.0 h |
reveal_secs |
12.0 h |
misaligned_slash_bps_low / _high |
1000 bps (10.00%) / 2000 bps (20.00%) |
misaligned_slash_cap_x |
3x the round's reward |
no_reveal_slash_bps |
3000 bps (30.00%) |
appeal_secs |
24.0 h |
appeal_multiplier_r2 / _r3 |
2x / 4x |
assembly_min_bond |
5000.00 USDC |
assembly_min_bond_cap_x |
10x the request's bonds |
appeal_jurors_bps |
7000 bps (70.00%) |
assembly_commit_secs |
72.0 h |
assembly_reveal_secs |
24.0 h |
assembly_lookback_secs |
7.0 days |
agent_min_families |
3 model families on an agent panel |
agent_max_seats_per_operator |
2 seats per operator |
RiskParams
| field | v0 |
|---|---|
weights |
oi 250, rules 250, attention 150, history 150, source 150, volatility 50, policy discount 100 |
attest_cut_bps |
2500 bps (25.00%) |
attest_floor_bps |
2500 bps (25.00%) |
attest_floor_min_secs |
0.5 h |
max_attestations |
3 |
attester_stake_bps |
1000 bps (10.00%) |
attest_min_reputation |
20 |
max_open_secs |
14.0 days |
max_too_early |
3 |
correction_secs |
7.0 days |
correction_bond_multiple |
2x the T4 base bond = 20000.00 USDC |
StakeParams
| field | v0 |
|---|---|
min_stake |
100.00 USDC |
lock_mult_min_secs / _max_secs |
30.0 days / 365.0 days |
lock_mult_max_bps |
20000 bps (200.00%) |
rep_mult_min_bps |
2000 bps (20.00%) |
rep_full |
100 |
cap_bps |
500 bps (5.00%) |
proven_reputation |
50 |
proven_stake_bps |
5000 bps (50.00%) = 50.00 USDC |
SettlementParams
| field | v0 |
|---|---|
counterparty_bps |
6000 bps (60.00%) |
jurors_bps |
2000 bps (20.00%) |
attester_reward_bps |
2000 bps (20.00%) |
treasury_fee_bps |
500 bps (5.00%) |
unresolvable_penalty_bps |
2500 bps (25.00%) |
unresolvable_jurors_bps |
4000 bps (40.00%) |
InsuranceParams
| field | v0 |
|---|---|
target_bps |
100 bps (1.00%) of trailing OI |
max_multiplier_bps |
40000 bps (400.00%) |
bounty_grace_windows |
2 |
bounty_max_multiplier |
2x the reward |
correction_cap_bps |
200 bps (2.00%) of the fund, per claim |
ReputationParams
| field | v0 |
|---|---|
aligned_gain |
+1 |
misaligned_loss |
−2 |
no_reveal_loss |
−3 |
assembly_misaligned_loss |
−1 |
decay_bps_per_quarter |
1000 bps (10.00%) a quarter |
What is checked, and how
- Machine-checked under
kani(crates/truth-core/src/proofs.rs): the lifecycle never reaches an illegal state from any state under any action; the scorer's terms stay inside the tier it picks; a round is carried only by a bloc that could carry a full panel; the proven-stake discount can only lower the bar. - Property-tested in
truth-core: value conservation at settlement, monotonicity of bond and window in the score, the weight cap, manifest validation over every field combination. - Differentially tested against the deployed programs in
programs/truth_oracle/testsandprograms/truth_court/tests: the same inputs give the same scores, bonds, settlements and tallies on chain as in the crate. - Simulated in
truth-sim, with the results and their caveats in Economics.
Source: docs/SPEC.md in the axmc repo. Edit the file; the next deploy rebuilds this page.