Protocol · Disputes & committees
A bonded committee ladder — never a token vote
Voided and every market built on it refunds.Dispute bond
1 unit
0.01 ETH default · 0.0005 on testnet
Tier 1
≤7 · 1 h
3 units per vote
Tier 2
≤15 · 2 h
8 units per vote
To decide
66%
of committee SIZE, not of votes cast
Try it live
The ladder
Proposed outcome
quorum agreed
Dispute
1 bond unit, in window
Tier 1
≤7 resolvers · 1 h
Tier 2
≤15 resolvers · 2 h
Finalized or Voided
no Tier 3
Two ways into a dispute
Challenge — dispute(eventId)
ProposedOutcome and its dispute window (set per event, e.g. 10 minutes) is still open. The disputer sends exactly DISPUTE_BOND (one bond unit). The event moves to Disputed and Tier 1 opens.Split quorum — escalateNonConvergence(eventId)
Step by step
- 1
Committee drawn
DisputeManagerUp to 7 authorized resolvers are drawn for Tier 1 (the whole pool if it is smaller). The draw is seeded from block data and the event ID. - 2
Members vote with a bond
1 hourEach member callssubmitTier1Vote(eventId, outcome)with the Tier-1 bond (3 units). Resolver nodes do this automatically: they re-run the same adapter and vote what they observe. - 3
66% decides
instantThe moment one side reaches 66% of the committee size, the tier resolves: the Registry finalizes that outcome (finalizeFromDispute) and bonds are settled. - 4
No decision → Tier 2
keeperIf the hour ends without 66%,escalateTier2refunds every Tier-1 vote bond in full and draws up to 15 resolvers with the Tier-2 bond (8 units) and a 2-hour window. - 5
Still no decision → VOID
floorvoidAfterTier2Timeoutmarks the event permanentlyVoided. All Tier-2 bonds and the disputer's bond are refunded. Nothing escalates further.
How many votes decide?
The rule in code is votes × 100 ≥ committeeSize × 66. It counts the committee's size, not how many voted, so members who stay silent can't let a small group decide.
Authorized pool
Tier-1 committee
Votes to decide
Tier-2 committee
Votes to decide
Authorized pool
Tier-1 committee
Votes to decide
Tier-2 committee
Votes to decide
Authorized pool
Tier-1 committee
Votes to decide
Tier-2 committee
Votes to decide
Authorized pool
Tier-1 committee
Votes to decide
Tier-2 committee
Votes to decide
Authorized pool
Tier-1 committee
Votes to decide
Tier-2 committee
Votes to decide
Authorized pool
Tier-1 committee
Votes to decide
Tier-2 committee
Votes to decide
| Authorized pool | Tier-1 committee | Votes to decide | Tier-2 committee | Votes to decide |
|---|---|---|---|---|
| 2 | 2 | 2 | 2 | 2 |
| 3 (today) | 3 | 2 | 3 | 2 |
| 5 | 5 | 4 | 5 | 4 |
| 7 | 7 | 5 | 7 | 5 |
| 10 | 7 | 5 | 10 | 7 |
| 15+ | 7 | 5 | 15 | 10 |
Where the bonds go
When a tier decides, everyone who voted with the decision gets their bond back. The losing side's bonds are split in thirds:
Third
Goes to
Third
Goes to
Third
Goes to
| Third | Goes to |
|---|---|
| ⅓ | Burned (sent to 0x…dEaD) |
| ⅓ | The protocol treasury — the TreasuryVault, which sweeps it in with sweepDisputeProceeds() |
| ⅓ | Shared equally by the members who voted with the decision (rounding dust goes to the treasury) |
The disputer's bond
Committee decides…
Disputer gets
Committee decides…
Disputer gets
Committee decides…
Disputer gets
| Committee decides… | Disputer gets |
|---|---|
| against the original proposal (the disputer was right) | their bond back in full |
| the same as the original proposal (the disputer was wrong) | nothing: ⅓ burned, ⅔ to the treasury |
| nothing — event Voided | their bond back in full |
Worked example
Tier 1, 7 members: 5 vote TRUE, 2 vote FALSE
On top of the bonds, the committee is paid from market fees: the TreasuryVault's committee third for that event goes to the deciding tier's members who voted the final outcome. See Treasury & fee thirds.
Pull payments
DisputeManager never pushes ETH to members inside a vote. Everything owed is credited to pendingWithdrawals[address] and collected with withdraw(), so a contract that reverts on receiving ETH can't freeze a dispute. Resolver nodes withdraw automatically.
Constants
Bonds come from one deploy-time unit
DISPUTE_BOND is the unit; Tier-1 and Tier-2 vote bonds are always 3× and 8× it, so the escalation economics are identical at any scale. The default unit is 0.01 ETH. The Robinhood Chain testnet deployment uses 0.0005 ETH so three faucet-funded resolvers can actually post committee bonds — a full Tier-1 dispute costs each of them under 0.002 ETH.Read directly from contracts/DisputeManager.sol.
Constant
Value
Meaning
Constant
Value
Meaning
Constant
Value
Meaning
Constant
Value
Meaning
Constant
Value
Meaning
Constant
Value
Meaning
Constant
Value
Meaning
Constant
Value
Meaning
| Constant | Value | Meaning |
|---|---|---|
| DISPUTE_BOND | 1 unit · 0.01 ETH default · 0.0005 testnet | Bond to challenge a proposed outcome. |
| TIER1_BOND | 3 units · 0.03 / 0.0015 ETH | Bond per Tier-1 vote. |
| TIER1_COMMITTEE_SIZE | 7 | Maximum Tier-1 members (the whole pool if smaller). |
| TIER1_WINDOW | 1 hour | Time Tier 1 has to decide. |
| TIER2_BOND | 8 units · 0.08 / 0.004 ETH | Bond per Tier-2 vote. |
| TIER2_COMMITTEE_SIZE | 15 | Maximum Tier-2 members. |
| TIER2_WINDOW | 2 hours | Time Tier 2 has to decide. |
| AGREEMENT_BPS | 66 | Percent of committee size needed to decide. |
Functions
Function
Who
When
Function
Who
When
Function
Who
When
Function
Who
When
Function
Who
When
Function
Who
When
Function
Who
When
| Function | Who | When |
|---|---|---|
| dispute(eventId) | anyone, DISPUTE_BOND | ProposedOutcome, inside the dispute window |
| escalateNonConvergence(eventId) | anyone | observation deadline passed without quorum |
| submitTier1Vote / submitTier2Vote(eventId, outcome) | drawn committee members, with the tier bond | inside the tier window |
| escalateTier2(eventId) | anyone | Tier-1 window over, no 66% |
| voidAfterTier2Timeout(eventId) | anyone | Tier-2 window over, no 66% |
| withdraw() | anyone owed ETH | any time |
| getCommittee · getVote · getTierTally · getCaseSummary | views | any time |
Drawing a committee: commit-reveal
While the resolver pool fits in a tier (≤ 7 for Tier 1, ≤ 15 for Tier 2), the committee is the whole pool and voting starts at once. Once the pool is larger, the tier first runs a two-step draw that no single party — the sequencer included — can predict or steer:
- 1
Commit
10 minEach authorized resolver callscommitSeed(eventId, keccak256(eventId, tier, resolver, salt)). Nodes derive the salt from their own signature, so they can always reveal it later. - 2
Reveal
10 minEach committer callsrevealSeed(eventId, salt). The salts are XOR-combined, so the order of reveals doesn't matter. - 3
Draw
anyonedrawCommittee(eventId)seeds the draw with the combined salts. Committers that never revealed are excluded — withholding can only remove yourself. The voting window starts here.