Protocol · TreasuryVault
Every fee is split in thirds — and only the right answers get paid
⅓
Resolvers
Split equally among resolvers whose observation matched the final outcome.
claimResolverReward(eventId)
⅓
Committee or insurance
Disputed: the deciding tier's members who voted the outcome. Undisputed: the insurance reserve.
claimCommitteeReward(eventId)
⅓
Treasury
Protocol treasury (team multisig later), plus rounding dust.
withdrawTreasury(to, amount)
Range-market fee
1%
per trade (tradeFeeBps = 100)
Yes/no market fee
1%
of the losing pool at settlement (feeBps = 100)
Max fee
5%
MAX_FEE_BPS, enforced in each market
Events per deposit
≤16
MAX_EVENTS_PER_DEPOSIT
Fees in, rewards out
Market settles
fees accrued
depositFees(ids, amt)
tagged per event
Event decided
Finalized / Voided / Expired
allocate(id)
split into thirds
Pull claims
resolvers · committee
- 1
Deposit
A market callsdepositFees(eventIds, amount). The amount is split equally across the IDs. A composite ID is expanded one level into its primitive operands, so a market on “NVDA up AND TSLA down” pays the resolvers of both. Deeper nesting, unknown IDs and rounding go to the treasury. - 2
Wait for the decision
Fees sit inpendingFees[eventId]until the event is Finalized, Voided or Expired. - 3
Allocate
allocate(eventId)is permissionless (the keeper calls it, and every claim calls it first). It snapshots the final outcome, how many resolvers observed it, and — if there was a dispute — how many members of the deciding tier voted it. - 4
Claim
Each resolver or committee member calls the claim function and receives its equal share. The resolver node's rewards duty does this automatically.
The rules, case by case
Event ended…
Resolver third
Committee third
Treasury third
Event ended…
Resolver third
Committee third
Treasury third
Event ended…
Resolver third
Committee third
Treasury third
Event ended…
Resolver third
Committee third
Treasury third
| Event ended… | Resolver third | Committee third | Treasury third |
|---|---|---|---|
| Finalized, never disputed | correct resolvers | → insurance reserve | treasury |
| Finalized by a committee | correct resolvers | deciding tier's correct voters, + a bonus of up to one more third from insurance | treasury |
| Finalized, but no resolver observed the final outcome | → treasury | as above | treasury |
| Voided or Expired | → treasury | → treasury | treasury (all of it) |
Why an insurance reserve?
Disputes are rare, so committee members would rarely be paid if they only earned from the fees of the event they judged — and a disputed event can have thin volume. The committee third of every undisputed event therefore fills an insurance reserve, and each later disputed event draws a bonus of up to one extra third from it. Honest committee work is paid even when the market behind it was small.
Worked example
An NVDA range market with 6 ranges collects 6.00 USDG in trade fees
The second inflow: dispute bonds
ETH from disputes
treasury. The treasury third of every losing committee bond, and ⅔ of a wrong disputer's bond, is credited to it. sweepDisputeProceeds() pulls that ETH in (the keeper calls it).Owner controls
withdrawTreasury, withdrawInsurance, withdrawEth — each emitting an event. The owner can't touch resolver or committee pools.Function reference
Function
Who
What
Function
Who
What
Function
Who
What
Function
Who
What
Function
Who
What
Function
Who
What
Function
Who
What
Function
Who
What
Function
Who
What
| Function | Who | What |
|---|---|---|
| depositFees(bytes32[] ids, uint256 amount) | markets | Pull USDG and attribute it to events. |
| allocate(bytes32 id) | anyone | Split a decided event's pending fees into thirds. |
| claimResolverReward(bytes32 id) | resolvers | Collect the resolver share (runs allocate first). |
| claimCommitteeReward(bytes32 id) | committee members | Collect the committee share (runs allocate first). |
| claimableResolverReward / claimableCommitteeReward(id, who) | view | What an address can claim now. |
| pendingFees(id) · getRewards(id) | view | Undivided fees; the per-event snapshot and pools. |
| treasuryBalance() · insuranceReserve() | view | Protocol balances. |
| sweepDisputeProceeds() | anyone | Pull credited dispute ETH from the DisputeManager. |
| withdrawTreasury · withdrawInsurance · withdrawEth | owner | Spend protocol balances. |
The vault is protocol infrastructure, not a consumer: it reads the Registry, Composer and DisputeManager to work out who is paid. Markets only push fees into it and still read outcomes through the Event Bus.