Skip to main content

DVM voting

The DVM — Data Verification Mechanism — is OMY's Phase 2 resolver. Stake $OMY, vote on disputed assertions, earn rewards from slashed bonds. This page is for stakers (when Phase 2 launches) and for builders who want to understand the mechanism their disputes will route through.

:::info Phase 2 status The DVM contract is implemented and tested. The $OMY token has not launched yet — we gate it on traction metrics (why). This page describes how it works once it activates. :::

The flow

Assertion enters Disputed


Resolver opens a Case


┌─── Round N ──────────────────────────┐
│ Commit window — stakers post a │
│ hashed vote + lock $OMY weight │
├──────────────────────────────────────┤
│ Reveal window — stakers reveal │
│ their plaintext vote │
├──────────────────────────────────────┤
│ Tally: │
│ - quorum (GAT) reached? │
│ - supermajority (SPAT, 65%)? │
│ YES → resolve answer; slash + reward│
│ NO → reopen round (max 3) │
└──────────────────────────────────────┘

Becoming a staker

  1. Acquire $OMY from a public market.
  2. Send $OMY to the StakeVoteResolver contract — the jetton-transfer notification increments your stake.
  3. You can Unstake any amount that isn't currently locked in a commit.

Your free balance earns no rewards — it's the locked-on-commit stake that counts for vote weight and that can be slashed.

Voting on a case

When a disputed assertion sends OpenVote to the resolver, a Case is opened. Stakers have until the commit deadline to:

  1. Compute a commitment hash = H(answer || salt || assertion)
  • answer — the bool you believe is correct
  • salt — a random uint256 you keep secret
  • assertion — address of the assertion under dispute (anti-collision)
  1. Send CommitVote(case, hash, amount) — locks amount $OMY from your free balance into this case's escrow.

The locked amount IS your vote weight. You can split your stake across multiple cases if there are several disputes happening simultaneously.

Once the commit window closes, reveal:

  1. Send RevealVote(case, answer, salt) — the resolver re-hashes your inputs and verifies against your commitment. If they match, your vote is counted. If you don't reveal, you're slashed.

Tally rules

After the reveal window closes:

CheckThresholdIf passIf fail
Quorum (GAT)total revealed ≥ gatRequiredproceedreopen round
Supermajority (SPAT)winning side ≥ 65% of revealedresolvereopen round
Non-tiewinning side > losing sideresolvereopen round

If all three pass, the resolver sends Resolve{answer} to the disputed assertion. The losing side's stake gets slashed; the winning side's stake + the slashed pot gets distributed pro-rata to winners.

If any check fails, the case reopens for another round (up to 3). Each round has fresh commit/reveal windows; stakers can re-stake or sit it out.

After 3 failed rounds, anyone can call AbandonCase — all locked stake becomes claimable, the assertion eventually settles via TimeoutRefund.

Rewards & slashing

Conservation: sum(rewards) == sum(slashes). Nothing comes from the protocol budget; nothing accrues as protocol surplus. The voting pot is self-funded by losers.

OutcomeYour stake (committed amount)
You revealed + voted with the winning sideReturned + share of slashed pot
You revealed + voted with the losing sideSlashed (default 10% — see params)
You committed but did not revealSlashed (default 100% — punishes spam-commit-and-grief)
You did not commitNothing — stake stays in your free balance

Rewards are claim-based — call Claim(case) after the case resolves to withdraw your principal + reward. No automatic distribution; gas is paid by the claimant.

Anti-attack properties

Stake locked at commit, not reveal. This kills the "commit cheap, stake big only if winning" attack. Your weight is what you locked at commit time — you can't observe the reveal window and then load up.

Commitment binds to the assertion address. Prevents reusing a hash across cases (defense-in-depth).

No-reveal slashing. Spamming commits is expensive. Real stakers reveal; attackers who commit-then-bail lose 100%.

Reopen cap = 3. Prevents indefinite-dispute DoS. After 3 rounds with no quorum, the case is abandoned; the assertion falls through to TimeoutRefund.

Parameters

These are settable at deploy by governance. The defaults that ship to mainnet will be tuned by an external economist; treat them as illustrative:

ParameterDefaultMeaning
commitWindow4 hoursHow long stakers have to commit
revealWindow4 hoursHow long stakers have to reveal
gatRequireddynamic (snapshot at case open)Min revealed stake for quorum
gatFloor10 000 $OMYAbsolute minimum GAT
spatBps6500 (65%)Supermajority threshold
slashBps1000 (10%)Loser slash %
noRevealSlashBps10000 (100%)No-reveal slash %
minCommit1 $OMYDust-prevention floor
maxRounds3Reopen cap

gatRequired is a snapshot of the dynamic (circulating $OMY × gatBps) at case open — so it scales with token supply automatically, but is frozen for the duration of the case.

What stakers should think about

import {DocFeatures, DocFeature} from '@site/src/components/docs/DocFeatures';

The Schelling point is the obvious answer. Voting against it is just losing money in expectation. If you can't determine the truth from the question + sources, abstain. Reveal-without-commit is fine; commit-without-conviction is not. Anyone who knows your salt + answer before reveal can grief you. Treat it like a private key. No-reveal is 100% slash. Set a calendar reminder. Or use a bot. Locking your entire stake in one case is risky. Spread weight across multiple disputes if several are active. Your stake's value tracks protocol revenue. Pay attention to volume, integrations, fee inflows.

Source

The full implementation lives in StakeVoteResolver.tolk. It's ~600 lines of Tolk covering commit, reveal, tally, reopen, abandon, claim, and the escrow accounting that makes it solvent under every input.